diff --git a/src/pretix/control/static/pretixcontrol/js/ui/main.js b/src/pretix/control/static/pretixcontrol/js/ui/main.js index 5a28a2a82f..a5f63d822f 100644 --- a/src/pretix/control/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/control/static/pretixcontrol/js/ui/main.js @@ -23,5 +23,13 @@ $(function () { }); }); } + + $("#sumtoggle").find("button").click(function () { + $(".table-product-overview .sum").toggle($(this).attr("data-target") === ".sum"); + $("#sumtoggle").find("button").not($(this)).removeClass("active"); + $(this).addClass("active"); + $(".table-product-overview .count").toggle($(this).attr("data-target") === ".count"); + }); + $('.collapsible').collapse(); }); diff --git a/src/pretix/control/static/pretixcontrol/less/orders.less b/src/pretix/control/static/pretixcontrol/less/orders.less index a899b324e2..166758cbc8 100644 --- a/src/pretix/control/static/pretixcontrol/less/orders.less +++ b/src/pretix/control/static/pretixcontrol/less/orders.less @@ -12,4 +12,10 @@ th:not(:first-child) { text-align: right; } + span.sum { + display: none; + } +} +#sumtoggle { + margin-top: 20px; } \ No newline at end of file diff --git a/src/pretix/control/templates/pretixcontrol/orders/overview.html b/src/pretix/control/templates/pretixcontrol/orders/overview.html index b7828a2e10..03d9fb1792 100644 --- a/src/pretix/control/templates/pretixcontrol/orders/overview.html +++ b/src/pretix/control/templates/pretixcontrol/orders/overview.html @@ -1,7 +1,14 @@ {% extends "pretixcontrol/event/base.html" %} {% load i18n %} +{% load order_overview %} {% block title %}{% trans "Order overview" %}{% endblock %} {% block content %} +
+
+ + +
+

{% trans "Order overview" %}

@@ -20,31 +27,31 @@ {% if tup.0 %} - - - - - + + + + + {% endif %} {% for item in tup.1 %} - - - - - + + + + + {% if item.has_variations %} {% for var in item.all_variations %} - - - - - + + + + + {% endfor %} {% endif %} @@ -54,11 +61,11 @@ - - - - - + + + + +
{{ tup.0.name }}{{ tup.0.num_total }}{{ tup.0.num_pending }}{{ tup.0.num_cancelled }}{{ tup.0.num_refunded }}{{ tup.0.num_paid }}{{ tup.0.num_total|togglesum }}{{ tup.0.num_pending|togglesum }}{{ tup.0.num_cancelled|togglesum }}{{ tup.0.num_refunded|togglesum }}{{ tup.0.num_paid|togglesum }}
{{ item.name }}{{ item.num_total }}{{ item.num_pending }}{{ item.num_cancelled }}{{ item.num_refunded }}{{ item.num_paid }}{{ item.num_total|togglesum }}{{ item.num_pending|togglesum }}{{ item.num_cancelled|togglesum }}{{ item.num_refunded|togglesum }}{{ item.num_paid|togglesum }}
{{ var }}{{ var.num_total }}{{ var.num_pending }}{{ var.num_cancelled }}{{ var.num_refunded }}{{ var.num_paid }}{{ var.num_total|togglesum }}{{ var.num_pending|togglesum }}{{ var.num_cancelled|togglesum }}{{ var.num_refunded|togglesum }}{{ var.num_paid|togglesum }}
{% trans "Total" %}{{ total.num_total }}{{ total.num_pending }}{{ total.num_cancelled }}{{ total.num_refunded }}{{ total.num_paid }}{{ total.num_total|togglesum }}{{ total.num_pending|togglesum }}{{ total.num_cancelled|togglesum }}{{ total.num_refunded|togglesum }}{{ total.num_paid|togglesum }}
diff --git a/src/pretix/control/templatetags/__init__.py b/src/pretix/control/templatetags/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/pretix/control/templatetags/order_overview.py b/src/pretix/control/templatetags/order_overview.py new file mode 100644 index 0000000000..163a465ee8 --- /dev/null +++ b/src/pretix/control/templatetags/order_overview.py @@ -0,0 +1,18 @@ +from django import template +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils import formats + + +register = template.Library() + + +@register.filter(name='togglesum', needs_autoescape=True) +def cut(value, autoescape=True): + if autoescape: + esc = conditional_escape + else: + esc = lambda x: x + return mark_safe('{0}{1}'.format( + esc(value[0]), esc(formats.localize(value[1])) + )) diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 74459802c2..81cae8c416 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -1,7 +1,7 @@ from itertools import groupby from django.contrib import messages -from django.db.models import Count, Q +from django.db.models import Count, Q, Sum from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from django.http import HttpResponse @@ -202,6 +202,10 @@ class OrderExtend(OrderView): data=self.request.POST if self.request.method == "POST" else None) +def tuplesum(tuples): + return tuple(map(sum, zip(*list(tuples)))) + + class OverView(EventPermissionRequiredMixin, TemplateView): template_name = 'pretixcontrol/orders/overview.html' permission = 'can_view_orders' @@ -215,39 +219,39 @@ class OverView(EventPermissionRequiredMixin, TemplateView): ).order_by('category__position', 'category_id', 'name') num_total = { - (p['item'], p['variation']): p['cnt'] + (p['item'], p['variation']): (p['cnt'], p['price']) for p in OrderPosition.objects.current.filter(order__event=self.request.event).values('item', 'variation').annotate( - cnt=Count('id')) + cnt=Count('id'), price=Sum('price')) } num_cancelled = { - (p['item'], p['variation']): p['cnt'] + (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects.current .filter(order__event=self.request.event, order__status=Order.STATUS_CANCELLED) .values('item', 'variation') - .annotate(cnt=Count('id'))) + .annotate(cnt=Count('id'), price=Sum('price'))) } num_refunded = { - (p['item'], p['variation']): p['cnt'] + (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects.current .filter(order__event=self.request.event, order__status=Order.STATUS_REFUNDED) .values('item', 'variation') - .annotate(cnt=Count('id'))) + .annotate(cnt=Count('id'), price=Sum('price'))) } num_pending = { - (p['item'], p['variation']): p['cnt'] + (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects.current .filter(order__event=self.request.event, order__status__in=(Order.STATUS_PENDING, Order.STATUS_EXPIRED)) .values('item', 'variation') - .annotate(cnt=Count('id'))) + .annotate(cnt=Count('id'), price=Sum('price'))) } num_paid = { - (p['item'], p['variation']): p['cnt'] + (p['item'], p['variation']): (p['cnt'], p['price']) for p in (OrderPosition.objects.current .filter(order__event=self.request.event, order__status=Order.STATUS_PAID) .values('item', 'variation') - .annotate(cnt=Count('id'))) + .annotate(cnt=Count('id'), price=Sum('price'))) } for item in items: @@ -255,18 +259,18 @@ class OverView(EventPermissionRequiredMixin, TemplateView): key=lambda vd: vd.ordered_values()) for var in item.all_variations: variid = var['variation'].identity if 'variation' in var else None - var.num_total = num_total.get((item.identity, variid), 0) - var.num_pending = num_pending.get((item.identity, variid), 0) - var.num_cancelled = num_cancelled.get((item.identity, variid), 0) - var.num_refunded = num_refunded.get((item.identity, variid), 0) - var.num_paid = num_paid.get((item.identity, variid), 0) + var.num_total = num_total.get((item.identity, variid), (0, 0)) + var.num_pending = num_pending.get((item.identity, variid), (0, 0)) + var.num_cancelled = num_cancelled.get((item.identity, variid), (0, 0)) + var.num_refunded = num_refunded.get((item.identity, variid), (0, 0)) + var.num_paid = num_paid.get((item.identity, variid), (0, 0)) item.has_variations = (len(item.all_variations) != 1 or not item.all_variations[0].empty()) - item.num_total = sum(var.num_total for var in item.all_variations) - item.num_pending = sum(var.num_pending for var in item.all_variations) - item.num_cancelled = sum(var.num_cancelled for var in item.all_variations) - item.num_refunded = sum(var.num_refunded for var in item.all_variations) - item.num_paid = sum(var.num_paid for var in item.all_variations) + item.num_total = tuplesum(var.num_total for var in item.all_variations) + item.num_pending = tuplesum(var.num_pending for var in item.all_variations) + item.num_cancelled = tuplesum(var.num_cancelled for var in item.all_variations) + item.num_refunded = tuplesum(var.num_refunded for var in item.all_variations) + item.num_paid = tuplesum(var.num_paid for var in item.all_variations) nonecat = ItemCategory(name=_('Uncategorized')) # Regroup those by category @@ -281,18 +285,18 @@ class OverView(EventPermissionRequiredMixin, TemplateView): key=lambda group: (group[0].position, group[0].identity) if group[0] is not None else (0, "") ) for c in ctx['items_by_category']: - c[0].num_total = sum(item.num_total for item in c[1]) - c[0].num_pending = sum(item.num_pending for item in c[1]) - c[0].num_cancelled = sum(item.num_cancelled for item in c[1]) - c[0].num_refunded = sum(item.num_refunded for item in c[1]) - c[0].num_paid = sum(item.num_paid for item in c[1]) + c[0].num_total = tuplesum(item.num_total for item in c[1]) + c[0].num_pending = tuplesum(item.num_pending for item in c[1]) + c[0].num_cancelled = tuplesum(item.num_cancelled for item in c[1]) + c[0].num_refunded = tuplesum(item.num_refunded for item in c[1]) + c[0].num_paid = tuplesum(item.num_paid for item in c[1]) ctx['total'] = { - 'num_total': sum(c.num_total for c, i in ctx['items_by_category']), - 'num_pending': sum(c.num_pending for c, i in ctx['items_by_category']), - 'num_cancelled': sum(c.num_cancelled for c, i in ctx['items_by_category']), - 'num_refunded': sum(c.num_refunded for c, i in ctx['items_by_category']), - 'num_paid': sum(c.num_paid for c, i in ctx['items_by_category']) + 'num_total': tuplesum(c.num_total for c, i in ctx['items_by_category']), + 'num_pending': tuplesum(c.num_pending for c, i in ctx['items_by_category']), + 'num_cancelled': tuplesum(c.num_cancelled for c, i in ctx['items_by_category']), + 'num_refunded': tuplesum(c.num_refunded for c, i in ctx['items_by_category']), + 'num_paid': tuplesum(c.num_paid for c, i in ctx['items_by_category']) } return ctx