From da7e1dee3e5edb89c07d4da96d05b5be135eb999 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Sun, 10 Nov 2019 12:58:49 +0100 Subject: [PATCH] Offset refunds: Catch exceptions in the right place --- src/pretix/base/models/orders.py | 3 ++- src/pretix/base/payment.py | 5 +++- src/pretix/control/views/orders.py | 2 +- src/tests/control/test_orders.py | 42 ++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index 6ab873472..ddf56b367 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -1213,6 +1213,7 @@ class OrderPayment(models.Model): """ return self.order.event.get_payment_providers(cached=True).get(self.provider) + @transaction.atomic() def _mark_paid(self, force, count_waitinglist, user, auth, ignore_date=False, overpaid=False): from pretix.base.signals import order_paid can_be_paid = self.order._can_be_paid(count_waitinglist=count_waitinglist, ignore_date=ignore_date, force=force) @@ -1281,7 +1282,7 @@ class OrderPayment(models.Model): 'provider': self.provider, }, user=user, auth=auth) - if self.order.status == Order.STATUS_PAID: + if self.order.status in (Order.STATUS_PAID, Order.STATUS_CANCELED): return payment_sum = self.order.payments.filter( diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 8553e217d..e5911772b 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -871,7 +871,10 @@ class OffsettingProvider(BasePaymentProvider): provider='offsetting', info=json.dumps({'orders': [refund.order.code]}) ) - p.confirm(ignore_date=True) + try: + p.confirm(ignore_date=True) + except Quota.QuotaExceededException: + pass @property def settings_form_fields(self) -> dict: diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 10d485fef..3f5060f96 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -767,7 +767,7 @@ class OrderRefundView(OrderView): if r.payment or r.provider == "offsetting": try: r.payment_provider.execute_refund(r) - except (PaymentException, Quota.QuotaExceededException) as e: + except PaymentException as e: r.state = OrderRefund.REFUND_STATE_FAILED r.save() messages.error(self.request, _('One of the refunds failed to be processed. You should ' diff --git a/src/tests/control/test_orders.py b/src/tests/control/test_orders.py index f9d3ddf41..c29104227 100644 --- a/src/tests/control/test_orders.py +++ b/src/tests/control/test_orders.py @@ -1965,6 +1965,48 @@ def test_refund_paid_order_offsetting_to_unknown(client, env): assert b'alert-danger' in r.content +@pytest.mark.django_db +def test_refund_paid_order_offsetting_to_expired(client, env): + with scopes_disabled(): + p = env[2].payments.last() + p.confirm() + client.login(email='dummy@dummy.dummy', password='dummy') + o = Order.objects.create( + code='BAZ', event=env[0], email='dummy@dummy.test', + status=Order.STATUS_EXPIRED, + datetime=now(), expires=now() + timedelta(days=10), + total=5, locale='en' + ) + o.positions.create(price=5, item=env[3]) + q = Quota.objects.create(event=env[0], size=0) + q.items.add(env[3]) + + client.post('/control/event/dummy/dummy/orders/FOO/refund', { + 'start-partial_amount': '5.00', + 'start-mode': 'partial', + 'start-action': 'mark_pending', + 'refund-offsetting': '5.00', + 'order-offsetting': 'BAZ', + 'manual_state': 'pending', + 'perform': 'on' + }, follow=True) + p.refresh_from_db() + assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED + env[2].refresh_from_db() + with scopes_disabled(): + r = env[2].refunds.last() + assert r.provider == "offsetting" + assert r.state == OrderRefund.REFUND_STATE_DONE + assert r.amount == Decimal('5.00') + assert env[2].status == Order.STATUS_PENDING + o.refresh_from_db() + assert o.status == Order.STATUS_EXPIRED + p2 = o.payments.first() + assert p2.provider == "offsetting" + assert p2.amount == Decimal('5.00') + assert p2.state == OrderPayment.PAYMENT_STATE_CONFIRMED + + @pytest.mark.django_db def test_refund_paid_order_offsetting(client, env): with scopes_disabled():