forked from CGM_Public/pretix_original
Merge pull request #201 from rixx/ticket165_reactivate_voucher
Fix #165 -- Reactivate voucher on cancelled orders
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user