forked from CGM_Public/pretix_original
Use "cancel" method instead of "refund" for free orders (#743)
* Use "cancel" method instead of "refund" for free orders * Adjust API
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{% trans "Extend payment term" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if order.status == 'n' %}
|
||||
{% if order.cancel_allowed %}
|
||||
<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" %}
|
||||
</a>
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
{% endif %}
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% if order.status == "n" and order.can_user_cancel %}
|
||||
{% if order.can_user_cancel %}
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
<p>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user