From f8cc332ed735b045e103fef92bb62552af6cbec1 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 15 Jan 2018 21:46:16 +0100 Subject: [PATCH] Use "cancel" method instead of "refund" for free orders (#743) * Use "cancel" method instead of "refund" for free orders * Adjust API --- src/pretix/api/views/order.py | 4 ++-- src/pretix/base/models/orders.py | 8 +++++++- src/pretix/base/services/orders.py | 2 +- .../templates/pretixcontrol/order/index.html | 2 +- src/pretix/control/views/orders.py | 4 ++-- .../templates/pretixpresale/event/order.html | 2 +- src/pretix/presale/views/order.py | 2 +- src/tests/control/test_orders.py | 15 +++++++++++++++ 8 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index 32aa1a2545..3450248264 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -109,9 +109,9 @@ class OrderViewSet(viewsets.ReadOnlyModelViewSet): send_mail = request.data.get('send_email', True) order = self.get_object() - if order.status != Order.STATUS_PENDING: + if not order.cancel_allowed(): return Response( - {'detail': 'The order is not pending.'}, + {'detail': 'The order is not allowed to be canceled.'}, status=status.HTTP_400_BAD_REQUEST ) diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index 612a8cb833..910ce00a68 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -213,6 +213,12 @@ class Order(LoggedModel): def net_total(self): return self.total - self.tax_total + def cancel_allowed(self): + return ( + self.status == Order.STATUS_PENDING + or (self.status == Order.STATUS_PAID and self.total == Decimal('0.00')) + ) + @staticmethod def normalize_code(code): tr = str.maketrans({ @@ -272,7 +278,7 @@ class Order(LoggedModel): """ positions = self.positions.all().select_related('item') cancelable = all([op.item.allow_cancel for op in positions]) - return self.event.settings.cancel_allow_user and cancelable + return self.cancel_allowed() and self.event.settings.cancel_allow_user and cancelable @property def is_expired_by_time(self): diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index f9f2113b26..1a2de403c9 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -245,7 +245,7 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None): if isinstance(api_token, int): api_token = TeamAPIToken.objects.get(pk=api_token) with order.event.lock(): - if order.status != Order.STATUS_PENDING: + if not order.cancel_allowed(): raise OrderError(_('You cannot cancel this order.')) order.status = Order.STATUS_CANCELED order.save() diff --git a/src/pretix/control/templates/pretixcontrol/order/index.html b/src/pretix/control/templates/pretixcontrol/order/index.html index b73f9fdfaa..d0ce6a098a 100644 --- a/src/pretix/control/templates/pretixcontrol/order/index.html +++ b/src/pretix/control/templates/pretixcontrol/order/index.html @@ -29,7 +29,7 @@ {% trans "Extend payment term" %} {% endif %} - {% if order.status == 'n' %} + {% if order.cancel_allowed %} {% trans "Cancel order" %} diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index fcf76230b2..dbda228292 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -219,7 +219,7 @@ class OrderTransition(OrderView): messages.warning(self.request, _('The order has been marked as paid, but we were unable to send a confirmation mail.')) else: messages.success(self.request, _('The order has been marked as paid.')) - elif self.order.status == Order.STATUS_PENDING and to == 'c': + elif self.order.cancel_allowed() and to == 'c': cancel_order(self.order, user=self.request.user, send_mail=self.request.POST.get("send_email") == "on") messages.success(self.request, _('The order has been canceled.')) elif self.order.status == Order.STATUS_PAID and to == 'n': @@ -241,7 +241,7 @@ class OrderTransition(OrderView): def get(self, *args, **kwargs): to = self.request.GET.get('status', '') - if self.order.status == Order.STATUS_PENDING and to == 'c': + if self.order.cancel_allowed() and to == 'c': return render(self.request, 'pretixcontrol/order/cancel.html', { 'order': self.order, }) diff --git a/src/pretix/presale/templates/pretixpresale/event/order.html b/src/pretix/presale/templates/pretixpresale/event/order.html index 24b7dca239..c814ac9526 100644 --- a/src/pretix/presale/templates/pretixpresale/event/order.html +++ b/src/pretix/presale/templates/pretixpresale/event/order.html @@ -202,7 +202,7 @@ {% endif %}
- {% if order.status == "n" and order.can_user_cancel %} + {% if order.can_user_cancel %}

diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py index e92374a5c8..ec055c0036 100644 --- a/src/pretix/presale/views/order.py +++ b/src/pretix/presale/views/order.py @@ -498,7 +498,7 @@ class OrderCancel(EventViewMixin, OrderDetailMixin, TemplateView): self.kwargs = kwargs if not self.order: raise Http404(_('Unknown order code or not authorized to access this order.')) - if self.order.status != Order.STATUS_PENDING or not self.order.can_user_cancel: + if not self.order.can_user_cancel: messages.error(request, _('You cannot cancel this order.')) return redirect(self.get_order_url()) return super().dispatch(request, *args, **kwargs) diff --git a/src/tests/control/test_orders.py b/src/tests/control/test_orders.py index 48eaec9fba..a5cb9c8bff 100644 --- a/src/tests/control/test_orders.py +++ b/src/tests/control/test_orders.py @@ -222,6 +222,21 @@ def test_order_transition(client, env, process): assert o.status == process[0] +@pytest.mark.django_db +def test_order_cancel_free(client, env): + o = Order.objects.get(id=env[2].id) + o.status = Order.STATUS_PAID + o.total = Decimal('0.00') + o.save() + client.login(email='dummy@dummy.dummy', password='dummy') + client.get('/control/event/dummy/dummy/orders/FOO/transition?status=c') + client.post('/control/event/dummy/dummy/orders/FOO/transition', { + 'status': 'c' + }) + o = Order.objects.get(id=env[2].id) + assert o.status == Order.STATUS_CANCELED + + @pytest.mark.django_db def test_order_invoice_create_forbidden(client, env): client.login(email='dummy@dummy.dummy', password='dummy')