From 1cb956d5081524114fee7286b0e38fe270e13237 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 15 Aug 2016 16:42:39 +0200 Subject: [PATCH] Added setting to disable order cancelling for users --- src/pretix/base/models/orders.py | 4 ++++ src/pretix/base/settings.py | 4 ++++ src/pretix/control/forms/event.py | 5 +++++ .../pretixcontrol/event/settings.html | 1 + .../templates/pretixpresale/event/order.html | 2 +- src/pretix/presale/views/order.py | 5 ++++- src/tests/presale/test_orders.py | 19 ++++++++++++++----- 7 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index fede16055..efbf866e1 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -227,6 +227,10 @@ class Order(LoggedModel): return False # nothing there to modify + @property + def can_user_cancel(self) -> bool: + return self.event.settings.cancel_allow_user + @property def is_expired_by_time(self): return ( diff --git a/src/pretix/base/settings.py b/src/pretix/base/settings.py index 162798c67..b8d22b5c9 100644 --- a/src/pretix/base/settings.py +++ b/src/pretix/base/settings.py @@ -121,6 +121,10 @@ DEFAULTS = { 'default': None, 'type': datetime }, + 'cancel_allow_user': { + 'default': 'True', + 'type': bool + }, 'contact_mail': { 'default': None, 'type': str diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py index 7385b7cce..d388d4e1a 100644 --- a/src/pretix/control/forms/event.py +++ b/src/pretix/control/forms/event.py @@ -160,6 +160,11 @@ class EventSettingsForm(SettingsForm): required=False, help_text=_("Public email address for contacting the organizer") ) + cancel_allow_user = forms.BooleanField( + label=_("Allow user to cancel unpaid orders"), + help_text=_("If unchecked, users cannot cancel orders by themselves"), + required=False + ) def clean(self): data = super().clean() diff --git a/src/pretix/control/templates/pretixcontrol/event/settings.html b/src/pretix/control/templates/pretixcontrol/event/settings.html index da0e88334..c6f4528f0 100644 --- a/src/pretix/control/templates/pretixcontrol/event/settings.html +++ b/src/pretix/control/templates/pretixcontrol/event/settings.html @@ -39,6 +39,7 @@ {% bootstrap_field sform.max_items_per_order layout="horizontal" %} {% bootstrap_field sform.attendee_names_asked layout="horizontal" %} {% bootstrap_field sform.attendee_names_required layout="horizontal" %} + {% bootstrap_field sform.cancel_allow_user layout="horizontal" %}
- {% if order.status == "n" %} + {% if order.status == "n" and order.can_user_cancel %}

diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py index d56a75591..ebe5ff7c3 100644 --- a/src/pretix/presale/views/order.py +++ b/src/pretix/presale/views/order.py @@ -295,7 +295,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 not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED): + if self.order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) or 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) @@ -321,6 +321,9 @@ class OrderCancelDo(EventViewMixin, OrderDetailMixin, AsyncAction, View): def post(self, request, *args, **kwargs): if not self.order: raise Http404(_('Unknown order code or not authorized to access this order.')) + if not self.order.can_user_cancel: + messages.error(request, _('You cannot cancel this order.')) + return redirect(self.get_order_url()) return self.do(self.order.pk) def get_context_data(self, **kwargs): diff --git a/src/tests/presale/test_orders.py b/src/tests/presale/test_orders.py index 469b673f3..8ad11c884 100644 --- a/src/tests/presale/test_orders.py +++ b/src/tests/presale/test_orders.py @@ -229,10 +229,10 @@ class OrdersTest(TestCase): def test_orders_cancel_invalid(self): self.order.status = Order.STATUS_PAID self.order.save() - self.client.get( - '/%s/%s/order/%s/%s/cancel' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret) - ) - self.order = Order.objects.get(id=self.order.id) + self.client.post( + '/%s/%s/order/%s/%s/cancel/do' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), { + }, follow=True) + self.order.refresh_from_db() assert self.order.status == Order.STATUS_PAID def test_orders_cancel(self): @@ -247,7 +247,16 @@ class OrdersTest(TestCase): '/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), target_status_code=200) - assert Order.objects.get(id=self.order.id).status == Order.STATUS_CANCELLED + self.order.refresh_from_db() + assert self.order.status == Order.STATUS_CANCELLED + + def test_orders_cancel_forbidden(self): + self.event.settings.set('cancel_allow_user', False) + self.client.post( + '/%s/%s/order/%s/%s/cancel/do' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret), { + }, follow=True) + self.order.refresh_from_db() + assert self.order.status == Order.STATUS_PENDING def test_orders_download(self): self.event.settings.set('ticket_download', True)