diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py
index f0fa566d2d..8fc147e781 100644
--- a/src/pretix/base/models/orders.py
+++ b/src/pretix/base/models/orders.py
@@ -334,7 +334,7 @@ class Order(LockModel, LoggedModel):
refund_sum=refund_sum_sq,
)
qs = qs.annotate(
- payment_refund_sum=Coalesce(payment_sum_sq, 0) - Coalesce(refund_sum_sq, 0),
+ computed_payment_refund_sum=Coalesce(payment_sum_sq, 0) - Coalesce(refund_sum_sq, 0),
)
qs = qs.annotate(
diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py
index 0ddfb1d87d..5ed301f55f 100644
--- a/src/pretix/control/forms/filter.py
+++ b/src/pretix/control/forms/filter.py
@@ -150,8 +150,8 @@ class OrderFilterForm(FilterForm):
(Order.STATUS_PENDING + Order.STATUS_PAID, _('Pending or paid')),
)),
(_('Cancellations'), (
- (Order.STATUS_CANCELED, _('Canceled')),
- ('cp', _('Canceled (or with paid fee)')),
+ (Order.STATUS_CANCELED, _('Canceled (fully)')),
+ ('cp', _('Canceled (fully or with paid fee)')),
('rc', _('Cancellation requested')),
)),
(_('Payment process'), (
@@ -159,7 +159,8 @@ class OrderFilterForm(FilterForm):
(Order.STATUS_PENDING + Order.STATUS_EXPIRED, _('Pending or expired')),
('o', _('Pending (overdue)')),
('overpaid', _('Overpaid')),
- ('underpaid', _('Underpaid')),
+ ('partially_paid', _('Partially paid')),
+ ('underpaid', _('Underpaid (but confirmed)')),
('pendingpaid', _('Pending (but fully paid)')),
)),
(_('Approval process'), (
@@ -245,6 +246,14 @@ class OrderFilterForm(FilterForm):
Q(status__in=(Order.STATUS_EXPIRED, Order.STATUS_PENDING)) & Q(pending_sum_t__lte=0)
& Q(require_approval=False)
)
+ elif s == 'partially_paid':
+ qs = Order.annotate_overpayments(qs, refunds=False, results=False, sums=True)
+ qs = qs.filter(
+ computed_payment_refund_sum__lt=F('total'),
+ computed_payment_refund_sum__gt=Decimal('0.00')
+ ).exclude(
+ status=Order.STATUS_CANCELED
+ )
elif s == 'underpaid':
qs = Order.annotate_overpayments(qs, refunds=False, results=False, sums=True)
qs = qs.filter(
diff --git a/src/pretix/control/templates/pretixcontrol/orders/index.html b/src/pretix/control/templates/pretixcontrol/orders/index.html
index 703b8648d8..4c6e08833b 100644
--- a/src/pretix/control/templates/pretixcontrol/orders/index.html
+++ b/src/pretix/control/templates/pretixcontrol/orders/index.html
@@ -162,11 +162,11 @@
{% elif o.is_pending_with_full_payment %}
{% trans "FULLY PAID" %}
{% endif %}
- {% if o.payment_refund_sum == o.total or o.payment_refund_sum == 0 %}
+ {% if o.computed_payment_refund_sum == o.total or o.computed_payment_refund_sum == 0 %}
{% endif %}
- {{ o.payment_refund_sum|money:request.event.currency }} /
- {% if o.payment_refund_sum == o.total or o.payment_refund_sum == 0 %}
+ {{ o.computed_payment_refund_sum|money:request.event.currency }} /
+ {% if o.computed_payment_refund_sum == o.total or o.computed_payment_refund_sum == 0 %}
{% endif %}
{{ o.total|money:request.event.currency }}
diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py
index 850631ed5a..64bcb951e9 100644
--- a/src/pretix/control/views/orders.py
+++ b/src/pretix/control/views/orders.py
@@ -160,7 +160,7 @@ class OrderList(OrderSearchMixin, EventPermissionRequiredMixin, PaginationMixin,
has_cancellation_request=Exists(CancellationRequest.objects.filter(order=OuterRef('pk')))
).values(
'pk', 'pcnt', 'is_overpaid', 'is_underpaid', 'is_pending_with_full_payment', 'has_external_refund',
- 'has_pending_refund', 'has_cancellation_request'
+ 'has_pending_refund', 'has_cancellation_request', 'computed_payment_refund_sum'
)
}
@@ -175,6 +175,7 @@ class OrderList(OrderSearchMixin, EventPermissionRequiredMixin, PaginationMixin,
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']
+ o.computed_payment_refund_sum = annotated.get(o.pk)['computed_payment_refund_sum']
o.sales_channel_obj = scs[o.sales_channel]
if ctx['page_obj'].paginator.count < 1000: