diff --git a/src/pretix/control/forms/orders.py b/src/pretix/control/forms/orders.py index 8970f9ccf5..87aa96f6d3 100644 --- a/src/pretix/control/forms/orders.py +++ b/src/pretix/control/forms/orders.py @@ -15,6 +15,13 @@ from pretix.base.services.pricing import get_price class ExtendForm(I18nModelForm): + quota_ignore = forms.BooleanField( + label=_('Overbook quota'), + help_text=_('If you check this box, this operation will be performed even if it leads to an overbooked quota ' + 'and you having sold more tickets than you planned!'), + required=False + ) + class Meta: model = Order fields = ['expires'] @@ -25,6 +32,11 @@ class ExtendForm(I18nModelForm): }) } + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.instance.status == Order.STATUS_PENDING or self.instance._is_still_available(now(), count_waitinglist=False) is True: + del self.fields['quota_ignore'] + def clean(self): data = super().clean() data['expires'] = data['expires'].replace(hour=23, minute=59, second=59) diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index ee0cbb1150..507957a833 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -463,7 +463,7 @@ class OrderExtend(OrderView): try: with self.order.event.lock() as now_dt: is_available = self.order._is_still_available(now_dt, count_waitinglist=False) - if is_available is True: + if is_available is True or self.form.cleaned_data.get('quota_ignore', False) is True: self.form.save() self.order.status = Order.STATUS_PENDING self.order.save() @@ -474,6 +474,7 @@ class OrderExtend(OrderView): messages.success(self.request, _('The payment term has been changed.')) else: messages.error(self.request, is_available) + return self._redirect_here() except LockTimeoutException: messages.error(self.request, _('We were not able to process the request completely as the ' 'server was too busy.')) @@ -487,6 +488,12 @@ class OrderExtend(OrderView): return self._redirect_back() return super().dispatch(request, *kwargs, **kwargs) + def _redirect_here(self): + return redirect('control:event.order.extend', + event=self.request.event.slug, + organizer=self.request.event.organizer.slug, + code=self.order.code) + def get(self, *args, **kwargs): return render(self.request, 'pretixcontrol/order/extend.html', { 'order': self.order, diff --git a/src/tests/control/test_orders.py b/src/tests/control/test_orders.py index 8430976224..568f189782 100644 --- a/src/tests/control/test_orders.py +++ b/src/tests/control/test_orders.py @@ -420,6 +420,25 @@ def test_order_extend_expired_quota_empty(client, env): assert o.status == Order.STATUS_EXPIRED +@pytest.mark.django_db +def test_order_extend_expired_quota_empty_ignore(client, env): + o = Order.objects.get(id=env[2].id) + o.expires = now() - timedelta(days=5) + o.status = Order.STATUS_EXPIRED + o.save() + q = Quota.objects.create(event=env[0], size=0) + q.items.add(env[3]) + newdate = (now() + timedelta(days=20)).strftime("%Y-%m-%d %H:%M:%S") + client.login(email='dummy@dummy.dummy', password='dummy') + response = client.post('/control/event/dummy/dummy/orders/FOO/extend', { + 'expires': newdate, + 'quota_ignore': 'on' + }, follow=True) + assert 'alert-success' in response.rendered_content + o = Order.objects.get(id=env[2].id) + assert o.status == Order.STATUS_PENDING + + @pytest.mark.django_db def test_order_extend_expired_quota_partial(client, env): o = Order.objects.get(id=env[2].id)