def date_hierarchy(cl): """ Displays the date hierarchy for date drill-down functionality. """ if cl.date_hierarchy: field_name = cl.date_hierarchy field = get_fields_from_path(cl.model, field_name)[-1] dates_or_datetimes = 'datetimes' if isinstance( field, models.DateTimeField) else 'dates' year_field = '%s__year' % field_name month_field = '%s__month' % field_name day_field = '%s__day' % field_name field_generic = '%s__' % field_name year_lookup = cl.params.get(year_field) month_lookup = cl.params.get(month_field) day_lookup = cl.params.get(day_field) link = lambda filters: cl.get_query_string(filters, [field_generic]) if not (year_lookup or month_lookup or day_lookup): # select appropriate start level date_range = cl.queryset.aggregate(first=models.Min(field_name), last=models.Max(field_name)) if date_range['first'] and date_range['last']: if date_range['first'].year == date_range['last'].year: year_lookup = date_range['first'].year if date_range['first'].month == date_range['last'].month: month_lookup = date_range['first'].month if year_lookup and month_lookup and day_lookup: day = datetime.date(int(year_lookup), int(month_lookup), int(day_lookup)) return { 'field_name': field.verbose_name, 'show': True, 'back': { 'link': link({ year_field: year_lookup, month_field: month_lookup }), 'title': capfirst(formats.date_format(day, 'YEAR_MONTH_FORMAT')) }, 'choices': [{ 'title': capfirst(formats.date_format(day, 'MONTH_DAY_FORMAT')) }] } elif year_lookup and month_lookup: days = cl.queryset.filter(**{ year_field: year_lookup, month_field: month_lookup }) days = getattr(days, dates_or_datetimes)(field_name, 'day') return { 'show': True, 'field_name': field.verbose_name, 'current_filter': capfirst(MONTHS.get(int(month_lookup), 'UNKNOWN')), 'back': { 'link': link({year_field: year_lookup}), 'title': str(year_lookup) }, 'choices': [{ 'link': link({ year_field: year_lookup, month_field: month_lookup, day_field: day.day }), 'title': capfirst(formats.date_format(day, 'MONTH_DAY_FORMAT')) } for day in days] } elif year_lookup: months = cl.queryset.filter(**{year_field: year_lookup}) months = getattr(months, dates_or_datetimes)(field_name, 'month') return { 'show': True, 'field_name': field.verbose_name, 'current_filter': year_lookup, 'back': { 'link': link({}), 'title': _('All dates') }, 'choices': [{ 'link': link({ year_field: year_lookup, month_field: month.month }), 'title': capfirst(formats.date_format(month, 'YEAR_MONTH_FORMAT')) } for month in months] } else: years = getattr(cl.queryset, dates_or_datetimes)(field_name, 'year') return { 'show': True, 'current_filter': _('All'), 'field_name': field.verbose_name, 'choices': [{ 'link': link({year_field: str(year.year)}), 'title': str(year.year), } for year in years] }
def test_create_dynamic_db_model_instance(self): # Support MyModel.objects.none() empt = KingBook.objects.all() self.assertEqual(str(empt), '<QuerySet []>') # Support MyModel.objects.create() bk1 = KingBook.objects.create(name="Tony Stark", rate=3.5) bk2 = KingBook.objects.create(name="John Wick", rate=5) self.assertEqual(bk1.__class__.__name__, "KingBook") self.assertEqual(bk2.name, "John Wick") # self.assertEqual(bk3.rate, 1.0) # Support MyModel.objects.get() bk5 = KingBook.objects.get(name="Tony Stark") self.assertEqual(bk5.name, bk1.name) # Support MyModel.objects.get_or_create() bk6, bk6_created = KingBook.objects.get_or_create(name="John Wick") # Get self.assertEqual(bk6.name, "John Wick") bk7, bk7_created = KingBook.objects.get_or_create(name="Will Smith", rate=3.5) # Create self.assertEqual(bk7.id, 63) # Support MyModel.objects.count() all = KingBook.objects.all() cnt = KingBook.objects.count() self.assertEqual(len(all), cnt) # Support Save method bk8 = KingBook(name="Brad Pete") bk8.save() # Support default value bk9 = KingBook.objects.get(id=64) self.assertEqual(bk9.name, "Brad Pete") self.assertEqual(bk9.rate, '1.0') self.assertEqual(bk9.weight, 'None') # Support instance update bk9.rate = 1.33 bk9.save() bk10 = KingBook.objects.get(name="Brad Pete") self.assertEqual(bk10.rate, '1.33') # Support complex filter bk11 = KingBook.objects.filter(id__gt=62) self.assertEqual(len(bk11), 2) # Support Aggregation higher_rate = KingBook.objects.aggregate(models.Max('rate')) self.assertEqual(higher_rate, {'rate__max': '5'}) lower_rate = KingBook.objects.aggregate(models.Min('rate')) self.assertEqual(lower_rate, {'rate__min': '1.33'}) # SUM bugs with Postgres db # sum_rate = KingBook.objects.aggregate(models.Sum('rate')) # self.assertEqual(sum_rate, {'rate__sum': 13.33}) # Support delete() bk12 = KingBook.objects.create(name="Tony Stark2", rate=3.5) bk13 = KingBook.objects.create(name="John Wick1", rate=5) bk14 = KingBook.objects.create(name="John Wick2", rate=5) bk15 = KingBook.objects.create(name="John Wick3", rate=5) bk16 = KingBook.objects.create(name="John Wick4", rate=5) bk17 = KingBook.objects.create(name="John Wick5", rate=5) bk18 = KingBook.objects.create(name="John Wick6", rate=5) bk19 = KingBook.objects.create(name="John Wick7", rate=5) deleted = KingBook.objects.get(name="John Wick6").delete() self.assertEqual(deleted, (8, {'django_dynamic_database.KingBook': 8})) # Support update() bk20 = KingBook.objects.filter(id__lt=66).update(rate=1.5) bk12 = KingBook.objects.get(name="Tony Stark2") self.assertEqual(bk12.rate, '1.5')
def create_refund_lines(self, order, supplier, created_by, refund_data): context = self.get_context_from_order_source(order) lines = order.lines.all() if supplier: lines = lines.filter(supplier=supplier) index = lines.aggregate(models.Max("ordering"))["ordering__max"] tax_proportions = self._get_tax_class_proportions(order) refund_lines = [] product_summary = order.get_product_summary(supplier) available_for_refund = order.get_total_unrefunded_amount( supplier=supplier) zero = Money(0, order.currency) total_refund_amount = zero for refund in refund_data: index += 1 amount = refund.get("amount", zero) quantity = refund.get("quantity", 0) parent_line = refund.get("line", "amount") if not settings.SHUUP_ALLOW_ARBITRARY_REFUNDS and ( not parent_line or parent_line == "amount"): raise RefundArbitraryRefundsNotAllowedException restock_products = refund.get("restock_products") refund_line = None assert parent_line assert quantity if parent_line == "amount": refund_line = self._refund_amount( context, order, index, refund.get("text", _("Misc refund")), amount, tax_proportions, supplier=supplier, ) else: # ensure the amount to refund and the order line amount have the same signs if (amount > zero and parent_line.taxful_price.amount < zero ) or (amount < zero and parent_line.taxful_price.amount > zero): raise InvalidRefundAmountException if abs(amount) > abs(parent_line.max_refundable_amount): raise RefundExceedsAmountException # If restocking products, calculate quantity of products to restock product = parent_line.product # ensure max refundable quantity is respected for products if product and quantity > parent_line.max_refundable_quantity: raise RefundExceedsQuantityException if restock_products and quantity and product: from shuup.core.suppliers.enums import StockAdjustmentType # restock from the unshipped quantity first unshipped_quantity_to_restock = min( quantity, product_summary[product.pk]["unshipped"]) shipped_quantity_to_restock = min( quantity - unshipped_quantity_to_restock, product_summary[product.pk]["ordered"] - product_summary[product.pk]["refunded"], ) if unshipped_quantity_to_restock > 0: product_summary[product.pk][ "unshipped"] -= unshipped_quantity_to_restock if parent_line.supplier.stock_managed: parent_line.supplier.adjust_stock( product.id, unshipped_quantity_to_restock, created_by=created_by, type=StockAdjustmentType.RESTOCK_LOGICAL, ) if shipped_quantity_to_restock > 0 and parent_line.supplier.stock_managed: parent_line.supplier.adjust_stock( product.id, shipped_quantity_to_restock, created_by=created_by, type=StockAdjustmentType.RESTOCK, ) product_summary[product.pk]["refunded"] += quantity base_amount = amount if order.prices_include_tax else amount / ( 1 + parent_line.tax_rate) from shuup.core.models import OrderLine, OrderLineType refund_line = OrderLine.objects.create( text=_("Refund for %s" % parent_line.text), order=order, type=OrderLineType.REFUND, parent_line=parent_line, ordering=index, base_unit_price_value=-(base_amount / (quantity or 1)), quantity=quantity, supplier=parent_line.supplier, ) for line_tax in parent_line.taxes.all(): tax_base_amount = amount / (1 + parent_line.tax_rate) tax_amount = tax_base_amount * line_tax.tax.rate refund_line.taxes.create( tax=line_tax.tax, name=_("Refund for %s" % line_tax.name), amount_value=-tax_amount, base_amount_value=-tax_base_amount, ordering=line_tax.ordering, ) total_refund_amount += refund_line.taxful_price.amount refund_lines.append(refund_line) if abs(total_refund_amount) > available_for_refund: raise RefundExceedsAmountException return refund_lines
def get_highest_value_for_treatment_type(self, treatment_type): return (self.treatment_attempts.filter( treatment_type=treatment_type).aggregate(highest=models.Max( "value", output_field=models.IntegerField( default=0)))["highest"] or 0)
def get_last_id(cls): return cls.objects.all().aggregate( models.Max('color_id')).get('color_id__max')
def actions(self) -> List: last_updated_action_ts = Action.objects.filter( team_id=self.team_id).aggregate( models.Max("updated_at"))["updated_at__max"] actions = ( Action.objects.filter( team_id=self.team_id, steps__event=self.event, deleted=False, # filter by event name to narrow down ).distinct("id").prefetch_related( Prefetch("steps", queryset=ActionStep.objects.order_by("id")))) if not self._can_use_cached_query(last_updated_action_ts): TEAM_ACTION_QUERY_CACHE[ self.team_id], _ = actions.query.sql_with_params() if len(actions) == 0: return [] events: models.QuerySet[Any] = Event.objects.filter(pk=self.pk) for action in actions: events = events.annotate( **{ "action_{}".format(action.pk): Event.objects.filter(pk=self.pk).query_db_by_action( action).values("id")[:1] }) # This block is a little cryptic so bear with me # We grab the query and the params from the ORM here q, p = events.query.sql_with_params() # We then take the parameters and replace the event id's with a placeholder # We use this later to sub back in future event id's # The rest of the parameters are shared between action types qp = tuple(["%s" if i == self.pk else i for i in p]) # Create a cache item and add it to the cache keyed on team_id and event id qcache = {self.event: (q, qp)} TEAM_EVENT_ACTION_QUERY_CACHE[self.team_id].update(qcache) # Update the last updated team action timestamp for future reference LAST_UPDATED_TEAM_ACTION[self.team_id] = last_updated_action_ts else: # If we have reached this block we are about to use the sql query cache # Grab the actions using the cached action query actions.raw(TEAM_ACTION_QUERY_CACHE[self.team_id]) # Grab the cached query and query params, we will need to replace some params q, p = TEAM_EVENT_ACTION_QUERY_CACHE[self.team_id][self.event] # Replace the query param placeholders with the event id (opposite of what we did above) qp = tuple([self.pk if i == "%s" else i for i in p]) with connection.cursor() as cursor: # Format and execute the cached query using the mostly cached params qstring = cursor.mogrify(q, qp) cursor.execute(qstring) events = namedtuplefetchall(cursor) event = [event for event in events][0] filtered_actions = [ action for action in actions if getattr(event, "action_{}".format(action.pk), None) ] return filtered_actions
def set_position(self): if self.position is None: self.position = self.field.option_set.aggregate( max_position=Coalesce(models.Max('position'), 0) ).get('max_position', 0) + 10
def get_max_priority(self, customer): aggr = self.get_queryset().filter(customer=customer).aggregate( models.Max('priority')) priority = aggr['priority__max'] or 0 return priority
def _folder(self, related, filters, option=None, order_by=None): """Base code, in common to the folders.""" qs = self.all() if option == OPTION_MESSAGES else QuerySet( self.model, PostmanQuery(self.model), using=self._db) if related: qs = qs.select_related(*related) if order_by: qs = qs.order_by(order_by) if isinstance(filters, (list, tuple)): lookups = models.Q() for filter in filters: lookups |= models.Q(**filter) else: lookups = models.Q(**filters) if option == OPTION_MESSAGES: return qs.filter(lookups) # Adding a 'count' attribute, to be similar to the by-conversation case, # should not be necessary. Otherwise add: # .extra(select={'count': 'SELECT 1'}) else: qs = qs.extra( select={'count': '{0}.count'.format(qs.query.pm_alias_prefix)}) qs.query.pm_set_extra(table=( # extra columns are always first in the SELECT query # for tests with the version 2.4.1 of sqlite3 in py26, add to the select: , 'id': 'postman_message.id' self.filter(lookups, thread_id__isnull=True).extra(select={'count': 0})\ .values_list('id', 'count').order_by(), # use separate annotate() to keep control of the necessary order self.filter(lookups, thread_id__isnull=False).values('thread').annotate(count=models.Count('pk')).annotate(id=models.Max('pk'))\ .values_list('id', 'count').order_by(), )) return qs
def get_latest_peers(latest=LATEST_PEERS): if latest > 0: peers = [ c['key_remote_jid'] for c in Messages.objects.using( 'msgstore').values('key_remote_jid').exclude( Q(key_remote_jid=-1) | Q(key_remote_jid__icontains='-') | Q(key_remote_jid__startswith='Server')).annotate( models.Max('timestamp')).order_by('-timestamp__max') [:latest] ] else: peers = [ c['key_remote_jid'] for c in Messages.objects.using( 'msgstore').values('key_remote_jid').exclude( Q(key_remote_jid=-1) | Q(key_remote_jid__icontains='-') | Q(key_remote_jid__startswith='Server')).annotate( models.Max('timestamp')).order_by('-timestamp__max') ] ret = [] for peer in peers: data = Messages.objects.using('msgstore').filter( key_remote_jid=peer).values( 'data', '_id', 'media_wa_type', get_raw_column()).annotate( models.Max('timestamp')).order_by('-timestamp__max')[:1][0] try: peer_data = WaContacts.objects.filter(jid=peer).values( 'display_name', 'status')[0] except: peer_data = {} peer_data['display_name'] = 'N/A' peer_data['status'] = 'N/A' newdata = { 'key_remote_jid': peer, 'media_wa_type': data['media_wa_type'], '_id': data['_id'], 'timestamp': timestamp2utc(float(data['timestamp__max']) / 1000), 'data': data['data'], 'display_name': peer_data['display_name'], 'status': peer_data['status'], 'number': '+' + peer.split('@')[0] } if data['data'] is not None: newdata['img'] = set_media(data['media_wa_type'], data['data'], peer, str(data['_id']), False) elif data[get_raw_column()] is not None: newdata['img'] = set_media(data['media_wa_type'], data[get_raw_column()], peer, str(data['_id']), True) if newdata['data'] is None: newdata['data'] = '' ret.append(newdata) return ret