From cc424908321921582f5b6db50b155a7271e6f061 Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer <chrisjrn@gmail.com> Date: Wed, 23 Mar 2016 13:29:18 +1100 Subject: [PATCH] Applying a voucher to a cart now uses the voucher code rather than the voucher object. Adds tests for constraints on vouchers. --- registrasion/controllers/cart.py | 8 ++++++-- registrasion/models.py | 5 +++++ registrasion/tests/test_invoice.py | 2 +- registrasion/tests/test_voucher.py | 31 ++++++++++++++++++++++-------- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/registrasion/controllers/cart.py b/registrasion/controllers/cart.py index 5cbe5c8c..59b308ed 100644 --- a/registrasion/controllers/cart.py +++ b/registrasion/controllers/cart.py @@ -121,13 +121,17 @@ class CartController(object): old_quantity = 0 self.set_quantity(product, old_quantity + quantity) - def apply_voucher(self, voucher): - ''' Applies the given voucher to this cart. ''' + def apply_voucher(self, voucher_code): + ''' Applies the voucher with the given code to this cart. ''' # TODO: is it valid for a cart to re-add a voucher that they have? # Is voucher exhausted? active_carts = rego.Cart.reserved_carts() + + # Try and find the voucher + voucher = rego.Voucher.objects.get(code=voucher_code.upper()) + carts_with_voucher = active_carts.filter(vouchers=voucher) if len(carts_with_voucher) >= voucher.limit: raise ValidationError("This voucher is no longer available") diff --git a/registrasion/models.py b/registrasion/models.py index c84a6abf..96ecf219 100644 --- a/registrasion/models.py +++ b/registrasion/models.py @@ -99,6 +99,11 @@ class Voucher(models.Model): def __str__(self): return "Voucher for %s" % self.recipient + def save(self, *a, **k): + ''' Normalise the voucher code to be uppercase ''' + self.code = self.code.upper() + super(Voucher, self).save(*a, **k) + recipient = models.CharField(max_length=64, verbose_name=_("Recipient")) code = models.CharField(max_length=16, unique=True, diff --git a/registrasion/tests/test_invoice.py b/registrasion/tests/test_invoice.py index 4d0360ce..637e82db 100644 --- a/registrasion/tests/test_invoice.py +++ b/registrasion/tests/test_invoice.py @@ -91,7 +91,7 @@ class InvoiceTestCase(RegistrationCartTestCase): ).save() current_cart = CartController.for_user(self.USER_1) - current_cart.apply_voucher(voucher) + current_cart.apply_voucher(voucher.code) # Should be able to create an invoice after the product is added current_cart.add_to_cart(self.PROD_1, 1) diff --git a/registrasion/tests/test_voucher.py b/registrasion/tests/test_voucher.py index 169a1b79..50b83417 100644 --- a/registrasion/tests/test_voucher.py +++ b/registrasion/tests/test_voucher.py @@ -3,6 +3,7 @@ import pytz from decimal import Decimal from django.core.exceptions import ValidationError +from django.db import IntegrityError from registrasion import models as rego from registrasion.controllers.cart import CartController @@ -15,10 +16,10 @@ UTC = pytz.timezone('UTC') class VoucherTestCases(RegistrationCartTestCase): @classmethod - def new_voucher(self): + def new_voucher(self, code="VOUCHER"): voucher = rego.Voucher.objects.create( recipient="Voucher recipient", - code="VOUCHER", + code=code, limit=1 ) voucher.save() @@ -30,18 +31,18 @@ class VoucherTestCases(RegistrationCartTestCase): self.set_time(datetime.datetime(2015, 01, 01, tzinfo=UTC)) cart_1 = CartController.for_user(self.USER_1) - cart_1.apply_voucher(voucher) + cart_1.apply_voucher(voucher.code) self.assertIn(voucher, cart_1.cart.vouchers.all()) # Second user should not be able to apply this voucher (it's exhausted) cart_2 = CartController.for_user(self.USER_2) with self.assertRaises(ValidationError): - cart_2.apply_voucher(voucher) + cart_2.apply_voucher(voucher.code) # After the reservation duration # user 2 should be able to apply voucher self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2) - cart_2.apply_voucher(voucher) + cart_2.apply_voucher(voucher.code) cart_2.cart.active = False cart_2.cart.save() @@ -49,7 +50,7 @@ class VoucherTestCases(RegistrationCartTestCase): # voucher, as user 2 has paid for their cart. self.add_timedelta(rego.Voucher.RESERVATION_DURATION * 2) with self.assertRaises(ValidationError): - cart_1.apply_voucher(voucher) + cart_1.apply_voucher(voucher.code) def test_voucher_enables_item(self): voucher = self.new_voucher() @@ -69,7 +70,7 @@ class VoucherTestCases(RegistrationCartTestCase): current_cart.add_to_cart(self.PROD_1, 1) # Apply the voucher - current_cart.apply_voucher(voucher) + current_cart.apply_voucher(voucher.code) current_cart.add_to_cart(self.PROD_1, 1) def test_voucher_enables_discount(self): @@ -89,6 +90,20 @@ class VoucherTestCases(RegistrationCartTestCase): # Having PROD_1 in place should add a discount current_cart = CartController.for_user(self.USER_1) - current_cart.apply_voucher(voucher) + current_cart.apply_voucher(voucher.code) current_cart.add_to_cart(self.PROD_1, 1) self.assertEqual(1, len(current_cart.cart.discountitem_set.all())) + + def test_voucher_codes_unique(self): + voucher1 = self.new_voucher(code="VOUCHER") + with self.assertRaises(IntegrityError): + voucher2 = self.new_voucher(code="VOUCHER") + + def test_multiple_vouchers_work(self): + voucher1 = self.new_voucher(code="VOUCHER1") + voucher2 = self.new_voucher(code="VOUCHER2") + + def test_vouchers_case_insensitive(self): + voucher = self.new_voucher(code="VOUCHeR") + current_cart = CartController.for_user(self.USER_1) + current_cart.apply_voucher(voucher.code.lower())