Merge pull request #201 from rixx/ticket165_reactivate_voucher

Fix #165 -- Reactivate voucher on cancelled orders
This commit is contained in:
Raphael Michel
2016-08-29 21:15:10 +02:00
committed by GitHub
4 changed files with 34 additions and 5 deletions

View File

@@ -7,7 +7,7 @@ from django.utils.translation import ugettext_lazy as _
from .base import LoggedModel from .base import LoggedModel
from .event import Event from .event import Event
from .items import Item, ItemVariation, Quota from .items import Item, ItemVariation, Quota
from .orders import CartPosition, OrderPosition from .orders import CartPosition, Order, OrderPosition
def generate_code(): def generate_code():
@@ -161,10 +161,12 @@ class Voucher(LoggedModel):
def is_ordered(self) -> int: def is_ordered(self) -> int:
""" """
Returns whether an order position exists that uses this voucher. Returns whether a non-canceled order position exists that uses this voucher.
""" """
return OrderPosition.objects.filter( return OrderPosition.objects.filter(
voucher=self voucher=self
).exclude(
order__status=Order.STATUS_CANCELLED
).exists() ).exists()
def is_in_cart(self) -> int: def is_in_cart(self) -> int:

View File

@@ -142,7 +142,7 @@ def cancel_order(order, user=None):
if isinstance(user, int): if isinstance(user, int):
user = User.objects.get(pk=user) user = User.objects.get(pk=user)
with order.event.lock(): with order.event.lock():
if order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED): if order.status != Order.STATUS_PENDING:
raise OrderError(_('You cannot cancel this order.')) raise OrderError(_('You cannot cancel this order.'))
order.status = Order.STATUS_CANCELLED order.status = Order.STATUS_CANCELLED
order.save() order.save()
@@ -152,6 +152,11 @@ def cancel_order(order, user=None):
if i: if i:
generate_cancellation(i) generate_cancellation(i)
for position in order.positions.all():
if position.voucher:
position.voucher.redeemed = False
position.voucher.save()
return order return order

View File

@@ -295,7 +295,7 @@ class OrderCancel(EventViewMixin, OrderDetailMixin, TemplateView):
self.kwargs = kwargs self.kwargs = kwargs
if not self.order: if not self.order:
raise Http404(_('Unknown order code or not authorized to access this 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) or not self.order.can_user_cancel: if self.order.status != Order.STATUS_PENDING or not self.order.can_user_cancel:
messages.error(request, _('You cannot cancel this order.')) messages.error(request, _('You cannot cancel this order.'))
return redirect(self.get_order_url()) return redirect(self.get_order_url())
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)

View File

@@ -10,7 +10,9 @@ from pretix.base.models import (
CachedFile, CartPosition, Event, Item, ItemCategory, ItemVariation, Order, CachedFile, CartPosition, Event, Item, ItemCategory, ItemVariation, Order,
OrderPosition, Organizer, Question, Quota, User, Voucher, OrderPosition, Organizer, Question, Quota, User, Voucher,
) )
from pretix.base.services.orders import mark_order_paid from pretix.base.services.orders import (
OrderError, cancel_order, mark_order_paid, perform_order,
)
class UserTestCase(TestCase): class UserTestCase(TestCase):
@@ -278,6 +280,26 @@ class QuotaTestCase(BaseQuotaTestCase):
self.assertEqual(self.quota.count_in_cart(), 1) self.assertEqual(self.quota.count_in_cart(), 1)
self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1)) self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 1))
def test_voucher_reuse(self):
self.quota.items.add(self.item1)
v = Voucher.objects.create(quota=self.quota, event=self.event, valid_until=now() + timedelta(days=5))
# use a voucher normally
cart = CartPosition.objects.create(event=self.event, item=self.item1, price=self.item1.default_price,
expires=now() + timedelta(days=3), voucher=v)
order = perform_order(event=self.event.id, payment_provider='free', positions=[cart.id])
# assert that the voucher cannot be reused
cart = CartPosition.objects.create(event=self.event, item=self.item1, price=self.item1.default_price,
expires=now() + timedelta(days=3), voucher=v)
self.assertRaises(OrderError, perform_order, event=self.event.id, payment_provider='free', positions=[cart.id])
# assert that the voucher can be re-used after cancelling the successful order
cancel_order(order)
cart = CartPosition.objects.create(event=self.event, item=self.item1, price=self.item1.default_price,
expires=now() + timedelta(days=3), voucher=v)
perform_order(event=self.event.id, payment_provider='free', positions=[cart.id])
class OrderTestCase(BaseQuotaTestCase): class OrderTestCase(BaseQuotaTestCase):
def setUp(self): def setUp(self):