Improved voucher interface with new methods (#284)

* Check that a voucher's variation matches its item

* Add method to check applicability of a voucher

* Add method to check if a voucher can be used

* Add tests for new voucher methods

* Test for ValidationErrors in Voucher.clean()

* Test for voucher state during ordering process
This commit is contained in:
Tobias Kunze
2016-10-24 12:40:06 +02:00
committed by Raphael Michel
parent 853510a375
commit aa63a4cded
3 changed files with 97 additions and 5 deletions

View File

@@ -2,6 +2,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.crypto import get_random_string
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from .base import LoggedModel
@@ -150,6 +151,8 @@ class Voucher(LoggedModel):
if self.variation and (not self.item or not self.item.has_variations):
raise ValidationError(_('You cannot select a variation without having selected a product that provides '
'variations.'))
if self.variation and not self.item.variations.filter(pk=self.variation.pk).exists():
raise ValidationError(_('This variation does not belong to this product.'))
if self.item.has_variations and not self.variation and self.block_quota:
raise ValidationError(_('You can only block quota if you specify a specific product variation. '
'Otherwise it might be unclear which quotas to block.'))
@@ -176,3 +179,25 @@ class Voucher(LoggedModel):
Returns whether an order position exists that uses this voucher.
"""
return self.orderposition_set.exists()
def applies_to(self, item: Item, variation: ItemVariation=None) -> bool:
"""
Returns whether this voucher applies to a given item (and optionally
a variation).
"""
if self.quota:
return item.quotas.filter(pk=self.quota.pk).exists()
if self.item and not self.variation:
return self.item == item
return (self.item == item) and (self.variation == variation)
def is_active(self):
"""
Returns True if a voucher has not yet been redeemed, but is still
within its validity (if valid_until is set).
"""
if self.redeemed:
return False
if self.valid_until and self.valid_until < now():
return False
return True

View File

@@ -117,9 +117,7 @@ def _add_new_items(event: Event, items: List[dict],
return error_messages['voucher_redeemed']
if voucher.valid_until is not None and voucher.valid_until < now_dt:
return error_messages['voucher_expired']
if voucher.item and voucher.item.pk != item.pk:
return error_messages['voucher_invalid_item']
if voucher.variation and (not variation or variation.pk != voucher.variation.pk):
if not voucher.applies_to(item, variation):
return error_messages['voucher_invalid_item']
doubleuse = CartPosition.objects.filter(voucher=voucher, cart_id=cart_id, event=event)
if 'cp' in i: