diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 293bc5f8a7..7979e4f75b 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -673,7 +673,7 @@ class OrderTransition(OrderView): def post(self, *args, **kwargs): to = self.request.POST.get('status', '') if self.order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) and to == 'p' and self.mark_paid_form.is_valid(): - ps = self.order.pending_sum + ps = max(0, self.order.pending_sum) try: p = self.order.payments.get( state__in=(OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED), diff --git a/src/tests/control/test_orders.py b/src/tests/control/test_orders.py index e052a88da0..3bf64c145a 100644 --- a/src/tests/control/test_orders.py +++ b/src/tests/control/test_orders.py @@ -587,6 +587,29 @@ def test_order_mark_paid_blocked(client, env): assert o.status == Order.STATUS_EXPIRED +@pytest.mark.django_db +def test_order_mark_paid_overpaid_exired(client, env): + o = Order.objects.get(id=env[2].id) + o.status = Order.STATUS_EXPIRED + o.expires = now() - timedelta(days=5) + o.save() + o.payments.create(state=OrderPayment.PAYMENT_STATE_CONFIRMED, amount=o.total * 2) + assert o.pending_sum == -1 * o.total + q = Quota.objects.create(event=env[0], size=0) + q.items.add(env[3]) + + client.login(email='dummy@dummy.dummy', password='dummy') + response = client.post('/control/event/dummy/dummy/orders/FOO/transition', { + 'status': 'p', + 'force': 'on' + }, follow=True) + assert 'alert-success' in response.rendered_content + o = Order.objects.get(id=env[2].id) + assert o.status == Order.STATUS_PAID + assert o.payments.last().amount == 0 + assert o.pending_sum == -1 * o.total + + @pytest.mark.django_db def test_order_mark_paid_forced(client, env): o = Order.objects.get(id=env[2].id)