Improve global order filters

This commit is contained in:
Martin Gross
2020-05-06 13:12:17 +02:00
parent c0972ef39d
commit 4b01c42f31
3 changed files with 94 additions and 5 deletions

View File

@@ -363,6 +363,28 @@ class OrderSearchFilterForm(OrderFilterForm):
)
)
status = forms.ChoiceField(
label=_('Order status'),
choices=(
('', _('All orders')),
(Order.STATUS_PAID, _('Paid (or canceled with paid fee)')),
(Order.STATUS_PENDING, _('Pending')),
('o', _('Pending (overdue)')),
(Order.STATUS_PENDING + Order.STATUS_PAID, _('Pending or paid')),
(Order.STATUS_EXPIRED, _('Expired')),
(Order.STATUS_PENDING + Order.STATUS_EXPIRED, _('Pending or expired')),
(Order.STATUS_CANCELED, _('Canceled')),
('cp', _('Canceled (or with paid fee)')),
('pa', _('Approval pending')),
('overpaid', _('Overpaid')),
('underpaid', _('Underpaid')),
('pendingpaid', _('Pending (but fully paid)')),
('testmode', _('Test mode')),
('rc', _('Cancellation requested')),
),
required=False,
)
def __init__(self, *args, **kwargs):
request = kwargs.pop('request')
super().__init__(*args, **kwargs)
@@ -381,6 +403,47 @@ class OrderSearchFilterForm(OrderFilterForm):
if fdata.get('organizer'):
qs = qs.filter(event__organizer=fdata.get('organizer'))
if fdata.get('status') == 'overpaid':
qs = Order.annotate_overpayments(qs, refunds=False, results=False, sums=True)
qs = qs.filter(
Q(~Q(status=Order.STATUS_CANCELED) & Q(pending_sum_t__lt=0))
| Q(Q(status=Order.STATUS_CANCELED) & Q(pending_sum_rc__lt=0))
)
elif fdata.get('status') == 'rc':
qs = qs.filter(
cancellation_requests__isnull=False
)
elif fdata.get('status') == 'pendingpaid':
qs = Order.annotate_overpayments(qs, refunds=False, results=False, sums=True)
qs = qs.filter(
Q(status__in=(Order.STATUS_EXPIRED, Order.STATUS_PENDING)) & Q(pending_sum_t__lte=0)
& Q(require_approval=False)
)
elif fdata.get('status') == 'underpaid':
qs = Order.annotate_overpayments(qs, refunds=False, results=False, sums=True)
qs = qs.filter(
status=Order.STATUS_PAID,
pending_sum_t__gt=0
)
elif fdata.get('status') == 'pa':
qs = qs.filter(
status=Order.STATUS_PENDING,
require_approval=True
)
elif fdata.get('status') == 'testmode':
qs = qs.filter(
testmode=True
)
elif fdata.get('status') == 'cp':
s = OrderPosition.objects.filter(
order=OuterRef('pk')
)
qs = qs.annotate(
has_pc=Exists(s)
).filter(
Q(status=Order.STATUS_PAID, has_pc=False) | Q(status=Order.STATUS_CANCELED)
)
return qs

View File

@@ -73,7 +73,24 @@
{% endif %}
</td>
<td>{{ o.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
<td class="text-right flip">{{ o.total|money:o.event.currency }}</td>
<td class="text-right flip">
{% if o.has_cancellation_request %}
<span class="label label-warning">{% trans "CANCELLATION REQUESTED" %}</span>
{% endif %}
{% if o.has_external_refund or o.has_pending_refund %}
<span class="label label-danger">{% trans "REFUND PENDING" %}</span>
{% elif o.has_pending_refund %}
<span class="label label-warning">{% trans "REFUND PENDING" %}</span>
{% endif %}
{% if o.is_overpaid %}
<span class="label label-warning">{% trans "OVERPAID" %}</span>
{% elif o.is_underpaid %}
<span class="label label-danger">{% trans "UNDERPAID" %}</span>
{% elif o.is_pending_with_full_payment %}
<span class="label label-danger">{% trans "FULLY PAID" %}</span>
{% endif %}
{{ o.total|money:o.event.currency }}
</td>
<td class="text-right flip">{% include "pretixcontrol/orders/fragment_order_status.html" with order=o %}</td>
</tr>
{% empty %}

View File

@@ -1,9 +1,10 @@
from django.conf import settings
from django.db.models import Count, IntegerField, OuterRef, Q, Subquery
from django.db.models import Count, Exists, IntegerField, OuterRef, Q, Subquery
from django.utils.functional import cached_property
from django.views.generic import ListView
from pretix.base.models import Order, OrderPosition
from pretix.base.models.orders import CancellationRequest
from pretix.control.forms.filter import OrderSearchFilterForm
from pretix.control.views import LargeResultSetPaginator, PaginationMixin
@@ -29,12 +30,14 @@ class OrderSearch(PaginationMixin, ListView):
annotated = {
o['pk']: o
for o in
Order.objects.using(settings.DATABASE_REPLICA).filter(
Order.annotate_overpayments(Order.objects).using(settings.DATABASE_REPLICA).filter(
pk__in=[o.pk for o in ctx['orders']]
).annotate(
pcnt=Subquery(s, output_field=IntegerField())
pcnt=Subquery(s, output_field=IntegerField()),
has_cancellation_request=Exists(CancellationRequest.objects.filter(order=OuterRef('pk')))
).values(
'pk', 'pcnt',
'pk', 'pcnt', 'is_overpaid', 'is_underpaid', 'is_pending_with_full_payment', 'has_external_refund',
'has_pending_refund', 'has_cancellation_request'
)
}
@@ -42,6 +45,12 @@ class OrderSearch(PaginationMixin, ListView):
if o.pk not in annotated:
continue
o.pcnt = annotated.get(o.pk)['pcnt']
o.is_overpaid = annotated.get(o.pk)['is_overpaid']
o.is_underpaid = annotated.get(o.pk)['is_underpaid']
o.is_pending_with_full_payment = annotated.get(o.pk)['is_pending_with_full_payment']
o.has_external_refund = annotated.get(o.pk)['has_external_refund']
o.has_pending_refund = annotated.get(o.pk)['has_pending_refund']
o.has_cancellation_request = annotated.get(o.pk)['has_cancellation_request']
return ctx