Added admin action to make an expired order pending again

This commit is contained in:
Raphael Michel
2016-10-03 11:14:20 +02:00
parent 59e2340529
commit b5a23224c8
7 changed files with 72 additions and 16 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 42 KiB

+1
View File
@@ -11,6 +11,7 @@ Pending --> Paid: successful payment
Pending --> Expired: automatically\nor manually\non admin action Pending --> Expired: automatically\nor manually\non admin action
Expired --> Paid: if payment is received\nonly if quota left Expired --> Paid: if payment is received\nonly if quota left
Expired --> Canceled Expired --> Canceled
Expired --> Pending: manually\non admin action
Paid --> Refunded: manually on\nadmin action\nor if an external\npayment provider\nnotifies about a\npayment refund Paid --> Refunded: manually on\nadmin action\nor if an external\npayment provider\nnotifies about a\npayment refund
Pending --> Canceled: on admin or\ncustomer action Pending --> Canceled: on admin or\ncustomer action
Paid -> Pending: manually on admin action Paid -> Pending: manually on admin action
-2
View File
@@ -286,8 +286,6 @@ class Order(LoggedModel):
raise Quota.QuotaExceededException(error_messages['unavailable']) raise Quota.QuotaExceededException(error_messages['unavailable'])
for quota in quotas: for quota in quotas:
# Lock the quota, so no other thread is allowed to perform sales covered by this
# quota while we're doing so.
if quota.id not in quota_cache: if quota.id not in quota_cache:
quota_cache[quota.id] = quota quota_cache[quota.id] = quota
quota.cached_availability = quota.availability(now_dt)[1] quota.cached_availability = quota.availability(now_dt)[1]
+7
View File
@@ -1,6 +1,7 @@
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.forms import I18nModelForm from pretix.base.forms import I18nModelForm
@@ -15,6 +16,12 @@ class ExtendForm(I18nModelForm):
'expires': forms.DateTimeInput(attrs={'class': 'datetimepicker'}), 'expires': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
} }
def clean(self):
data = super().clean()
if data['expires'] < now():
raise ValidationError(_('The new expiry date needs to be in the future.'))
return data
class ExporterForm(forms.Form): class ExporterForm(forms.Form):
@@ -23,11 +23,11 @@
<div class="btn-group" role="group"> <div class="btn-group" role="group">
{% if order.status == 'n' or order.status == 'e' %} {% if order.status == 'n' or order.status == 'e' %}
<button name="status" value="p" class="btn btn-default">{% trans "Mark as paid" %}</button> <button name="status" value="p" class="btn btn-default">{% trans "Mark as paid" %}</button>
{% endif %}
{% if order.status == 'n' %}
<a href="{% url "control:event.order.extend" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default"> <a href="{% url "control:event.order.extend" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}" class="btn btn-default">
{% trans "Extend payment term" %} {% trans "Extend payment term" %}
</a> </a>
{% endif %}
{% if order.status == 'n' %}
<a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=c" class="btn btn-default"> <a href="{% url "control:event.order.transition" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}?status=c" class="btn btn-default">
{% trans "Cancel order" %} {% trans "Cancel order" %}
</a> </a>
+12 -10
View File
@@ -442,16 +442,12 @@ class OrderExtend(OrderView):
permission = 'can_change_orders' permission = 'can_change_orders'
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
if self.order.status != Order.STATUS_PENDING:
messages.error(self.request, _('This action is only allowed for pending orders.'))
return self._redirect_back()
oldvalue = self.order.expires
if self.form.is_valid(): if self.form.is_valid():
if oldvalue > now(): if self.order.status == Order.STATUS_PENDING:
messages.success(self.request, _('The payment term has been changed.')) messages.success(self.request, _('The payment term has been changed.'))
self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={ self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={
'expires': self.order.expires 'expires': self.order.expires,
'state_change': False
}) })
self.form.save() self.form.save()
else: else:
@@ -460,8 +456,11 @@ class OrderExtend(OrderView):
is_available = self.order._is_still_available(now_dt) is_available = self.order._is_still_available(now_dt)
if is_available is True: if is_available is True:
self.form.save() self.form.save()
self.order.status = Order.STATUS_PENDING
self.order.save()
self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={ self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={
'expires': self.order.expires 'expires': self.order.expires,
'state_change': True
}) })
messages.success(self.request, _('The payment term has been changed.')) messages.success(self.request, _('The payment term has been changed.'))
else: else:
@@ -473,10 +472,13 @@ class OrderExtend(OrderView):
else: else:
return self.get(*args, **kwargs) return self.get(*args, **kwargs)
def get(self, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if self.order.status != Order.STATUS_PENDING: if self.order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED):
messages.error(self.request, _('This action is only allowed for pending orders.')) messages.error(self.request, _('This action is only allowed for pending orders.'))
return self._redirect_back() return self._redirect_back()
return super().dispatch(request, *kwargs, **kwargs)
def get(self, *args, **kwargs):
return render(self.request, 'pretixcontrol/order/extend.html', { return render(self.request, 'pretixcontrol/order/extend.html', {
'order': self.order, 'order': self.order,
'form': self.form, 'form': self.form,
+50 -2
View File
@@ -447,11 +447,11 @@ def test_order_extend_not_expired(client, env):
@pytest.mark.django_db @pytest.mark.django_db
def test_order_extend_expired_quota_left(client, env): def test_order_extend_overdue_quota_empty(client, env):
o = Order.objects.get(id=env[2].id) o = Order.objects.get(id=env[2].id)
o.expires = now() - timedelta(days=5) o.expires = now() - timedelta(days=5)
o.save() o.save()
q = Quota.objects.create(event=env[0], size=3) q = Quota.objects.create(event=env[0], size=0)
q.items.add(env[3]) q.items.add(env[3])
newdate = (now() + timedelta(days=20)).strftime("%Y-%m-%d %H:%M:%S") newdate = (now() + timedelta(days=20)).strftime("%Y-%m-%d %H:%M:%S")
client.login(email='dummy@dummy.dummy', password='dummy') client.login(email='dummy@dummy.dummy', password='dummy')
@@ -463,10 +463,30 @@ def test_order_extend_expired_quota_left(client, env):
assert o.expires.strftime("%Y-%m-%d %H:%M:%S") == newdate assert o.expires.strftime("%Y-%m-%d %H:%M:%S") == newdate
@pytest.mark.django_db
def test_order_extend_expired_quota_left(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=3)
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
}, follow=True)
assert 'alert-success' in response.rendered_content
o = Order.objects.get(id=env[2].id)
assert o.expires.strftime("%Y-%m-%d %H:%M:%S") == newdate
assert o.status == Order.STATUS_PENDING
@pytest.mark.django_db @pytest.mark.django_db
def test_order_extend_expired_quota_empty(client, env): def test_order_extend_expired_quota_empty(client, env):
o = Order.objects.get(id=env[2].id) o = Order.objects.get(id=env[2].id)
o.expires = now() - timedelta(days=5) o.expires = now() - timedelta(days=5)
o.status = Order.STATUS_EXPIRED
olddate = o.expires olddate = o.expires
o.save() o.save()
q = Quota.objects.create(event=env[0], size=0) q = Quota.objects.create(event=env[0], size=0)
@@ -479,6 +499,34 @@ def test_order_extend_expired_quota_empty(client, env):
assert 'alert-danger' in response.rendered_content assert 'alert-danger' in response.rendered_content
o = Order.objects.get(id=env[2].id) o = Order.objects.get(id=env[2].id)
assert o.expires.strftime("%Y-%m-%d %H:%M:%S") == olddate.strftime("%Y-%m-%d %H:%M:%S") assert o.expires.strftime("%Y-%m-%d %H:%M:%S") == olddate.strftime("%Y-%m-%d %H:%M:%S")
assert o.status == Order.STATUS_EXPIRED
@pytest.mark.django_db
def test_order_extend_expired_quota_partial(client, env):
o = Order.objects.get(id=env[2].id)
OrderPosition.objects.create(
order=o,
item=env[3],
variation=None,
price=Decimal("14"),
attendee_name="Peter"
)
o.expires = now() - timedelta(days=5)
o.status = Order.STATUS_EXPIRED
olddate = o.expires
o.save()
q = Quota.objects.create(event=env[0], size=1)
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
}, follow=True)
assert 'alert-danger' in response.rendered_content
o = Order.objects.get(id=env[2].id)
assert o.expires.strftime("%Y-%m-%d %H:%M:%S") == olddate.strftime("%Y-%m-%d %H:%M:%S")
assert o.status == Order.STATUS_EXPIRED
@pytest.mark.django_db @pytest.mark.django_db