diff --git a/src/pretix/plugins/statistics/signals.py b/src/pretix/plugins/statistics/signals.py index 19c93fab31..d420781f88 100644 --- a/src/pretix/plugins/statistics/signals.py +++ b/src/pretix/plugins/statistics/signals.py @@ -4,10 +4,11 @@ from django.template import Context from django.template.loader import get_template from django.utils.translation import ugettext_lazy as _ +from pretix.base.signals import order_paid, order_placed from pretix.control.signals import html_head, nav_event -@receiver(nav_event) +@receiver(nav_event, dispatch_uid="statistics_nav") def control_nav_import(sender, request=None, **kwargs): url = resolve(request.path_info) if not request.eventperm.can_view_orders: @@ -25,7 +26,7 @@ def control_nav_import(sender, request=None, **kwargs): ] -@receiver(html_head) +@receiver(html_head, dispatch_uid="statistics_html_head") def html_head_presale(sender, request=None, **kwargs): url = resolve(request.path_info) if url.namespace == 'plugins:statistics': @@ -34,3 +35,14 @@ def html_head_presale(sender, request=None, **kwargs): return template.render(ctx) else: return "" + + +def clear_cache(sender, *args, **kwargs): + cache = sender.get_cache() + cache.delete('statistics_obd_data') + cache.delete('statistics_obp_data') + cache.delete('statistics_rev_data') + + +order_placed.connect(clear_cache) +order_paid.connect(clear_cache) diff --git a/src/pretix/plugins/statistics/views.py b/src/pretix/plugins/statistics/views.py index 93c672c857..a1244f492f 100644 --- a/src/pretix/plugins/statistics/views.py +++ b/src/pretix/plugins/statistics/views.py @@ -18,80 +18,91 @@ class IndexView(EventPermissionRequiredMixin, TemplateView): def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) + cache = self.request.event.get_cache() + # Orders by day - ordered_by_day = {} - for o in Order.objects.current.filter(event=self.request.event).values('datetime'): - day = o['datetime'].date() - ordered_by_day[day] = ordered_by_day.get(day, 0) + 1 - paid_by_day = {} - for o in Order.objects.current.filter(event=self.request.event, - payment_date__isnull=False).values('payment_date'): - day = o['payment_date'].date() - paid_by_day[day] = paid_by_day.get(day, 0) + 1 + ctx['obd_data'] = cache.get('statistics_obd_data') + if not ctx['obd_data']: + ordered_by_day = {} + for o in Order.objects.current.filter(event=self.request.event).values('datetime'): + day = o['datetime'].date() + ordered_by_day[day] = ordered_by_day.get(day, 0) + 1 + paid_by_day = {} + for o in Order.objects.current.filter(event=self.request.event, + payment_date__isnull=False).values('payment_date'): + day = o['payment_date'].date() + paid_by_day[day] = paid_by_day.get(day, 0) + 1 - data = [] - for d in dateutil.rrule.rrule( - dateutil.rrule.DAILY, - dtstart=min(ordered_by_day.keys() if ordered_by_day else datetime.date.today()), - until=max( - max(ordered_by_day.keys() if paid_by_day else [datetime.date.today()]), - max(paid_by_day.keys() if paid_by_day else [datetime.date(1970, 1, 1)]) - )): - d = d.date() - data.append({ - 'date': d.strftime('%Y-%m-%d'), - 'ordered': ordered_by_day.get(d, 0), - 'paid': paid_by_day.get(d, 0) - }) + data = [] + for d in dateutil.rrule.rrule( + dateutil.rrule.DAILY, + dtstart=min(ordered_by_day.keys() if ordered_by_day else datetime.date.today()), + until=max( + max(ordered_by_day.keys() if paid_by_day else [datetime.date.today()]), + max(paid_by_day.keys() if paid_by_day else [datetime.date(1970, 1, 1)]) + )): + d = d.date() + data.append({ + 'date': d.strftime('%Y-%m-%d'), + 'ordered': ordered_by_day.get(d, 0), + 'paid': paid_by_day.get(d, 0) + }) - ctx['obd_data'] = json.dumps(data) + ctx['obd_data'] = json.dumps(data) + cache.set('statistics_obd_data', ctx['obd_data']) # Orders by product - num_ordered = { - p['item']: p['cnt'] - for p in (OrderPosition.objects.current - .filter(order__event=self.request.event) - .values('item', 'variation') - .annotate(cnt=Count('id'))) - } - num_paid = { - p['item']: p['cnt'] - for p in (OrderPosition.objects.current - .filter(order__event=self.request.event, order__status=Order.STATUS_PAID) - .values('item', 'variation') - .annotate(cnt=Count('id'))) - } - item_names = { - i.identity: str(i.name) - for i in Item.objects.current.filter(event=self.request.event) - } - ctx['obp_data'] = [ - { - 'item': item_names[item], - 'ordered': cnt, - 'paid': num_paid.get(item, 0) - } for item, cnt in num_ordered.items() - ] + ctx['obp_data'] = cache.get('statistics_obp_data') + if not ctx['obp_data']: + num_ordered = { + p['item']: p['cnt'] + for p in (OrderPosition.objects.current + .filter(order__event=self.request.event) + .values('item', 'variation') + .annotate(cnt=Count('id'))) + } + num_paid = { + p['item']: p['cnt'] + for p in (OrderPosition.objects.current + .filter(order__event=self.request.event, order__status=Order.STATUS_PAID) + .values('item', 'variation') + .annotate(cnt=Count('id'))) + } + item_names = { + i.identity: str(i.name) + for i in Item.objects.current.filter(event=self.request.event) + } + ctx['obp_data'] = [ + { + 'item': item_names[item], + 'ordered': cnt, + 'paid': num_paid.get(item, 0) + } for item, cnt in num_ordered.items() + ] + cache.set('statistics_obp_data', ctx['obp_data']) - rev_by_day = {} - for o in Order.objects.current.filter(event=self.request.event, - status=Order.STATUS_PAID, - payment_date__isnull=False).values('payment_date', 'total'): - day = o['payment_date'].date() - rev_by_day[day] = rev_by_day.get(day, 0) + o['total'] + ctx['rev_data'] = cache.get('statistics_rev_data') + if not ctx['rev_data']: + rev_by_day = {} + for o in Order.objects.current.filter(event=self.request.event, + status=Order.STATUS_PAID, + payment_date__isnull=False).values('payment_date', 'total'): + day = o['payment_date'].date() + rev_by_day[day] = rev_by_day.get(day, 0) + o['total'] - data = [] - total = 0 - for d in dateutil.rrule.rrule( - dateutil.rrule.DAILY, - dtstart=min(rev_by_day.keys() if rev_by_day else [datetime.date.today()]), - until=max(rev_by_day.keys() if rev_by_day else [datetime.date.today()])): - d = d.date() - total += float(rev_by_day.get(d, 0)) - data.append({ - 'date': d.strftime('%Y-%m-%d'), - 'revenue': round(total, 2), - }) - ctx['rev_data'] = json.dumps(data) + data = [] + total = 0 + for d in dateutil.rrule.rrule( + dateutil.rrule.DAILY, + dtstart=min(rev_by_day.keys() if rev_by_day else [datetime.date.today()]), + until=max(rev_by_day.keys() if rev_by_day else [datetime.date.today()])): + d = d.date() + total += float(rev_by_day.get(d, 0)) + data.append({ + 'date': d.strftime('%Y-%m-%d'), + 'revenue': round(total, 2), + }) + ctx['rev_data'] = json.dumps(data) + cache.set('statistics_rev_data', ctx['rev_data']) return ctx