From 8080d7851bda44796c644bf4e6f5930826a4f8a1 Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer <chrisjrn@gmail.com> Date: Sun, 27 Mar 2016 14:04:47 +1100 Subject: [PATCH] Invoices now automatically void themselves if their cart is out of date --- registrasion/controllers/invoice.py | 17 ++++++++------- registrasion/tests/test_invoice.py | 32 +++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/registrasion/controllers/invoice.py b/registrasion/controllers/invoice.py index b8087c98..47765358 100644 --- a/registrasion/controllers/invoice.py +++ b/registrasion/controllers/invoice.py @@ -11,6 +11,7 @@ class InvoiceController(object): def __init__(self, invoice): self.invoice = invoice + self.update_validity() # Make sure this invoice is up-to-date @classmethod def for_cart(cls, cart): @@ -24,6 +25,10 @@ class InvoiceController(object): except ObjectDoesNotExist: cart_controller = CartController(cart) cart_controller.validate_cart() # Raises ValidationError on fail. + + # Void past invoices for this cart + invoices = rego.Invoice.objects.filter(cart=cart).update(void=True) + invoice = cls._generate(cart) return InvoiceController(invoice) @@ -91,19 +96,17 @@ class InvoiceController(object): return invoice - def is_valid(self): - ''' Returns true if the attached invoice is not void and it represents - a valid cart. ''' - if self.invoice.void: - return False + def update_validity(self): + ''' Updates the validity of this invoice if the cart it is attached to + has updated. ''' if self.invoice.cart is not None: if self.invoice.cart.revision != self.invoice.cart_revision: - return False - return True + self.void() def void(self): ''' Voids the invoice. ''' self.invoice.void = True + self.invoice.save() def pay(self, reference, amount): ''' Pays the invoice by the given amount. If the payment diff --git a/registrasion/tests/test_invoice.py b/registrasion/tests/test_invoice.py index 637e82db..b3f80314 100644 --- a/registrasion/tests/test_invoice.py +++ b/registrasion/tests/test_invoice.py @@ -27,11 +27,17 @@ class InvoiceTestCase(RegistrationCartTestCase): # That invoice should have a value equal to cost of PROD_1 self.assertEqual(self.PROD_1.price, invoice_1.invoice.value) - # Adding item to cart should void all active invoices and produce - # a new invoice + # Adding item to cart should produce a new invoice current_cart.add_to_cart(self.PROD_2, 1) invoice_2 = InvoiceController.for_cart(current_cart.cart) self.assertNotEqual(invoice_1.invoice, invoice_2.invoice) + + # The old invoice should automatically be voided + invoice_1_new = rego.Invoice.objects.get(pk=invoice_1.invoice.id) + invoice_2_new = rego.Invoice.objects.get(pk=invoice_2.invoice.id) + self.assertTrue(invoice_1_new.void) + self.assertFalse(invoice_2_new.void) + # Invoice should have two line items line_items = rego.LineItem.objects.filter(invoice=invoice_2.invoice) self.assertEqual(2, len(line_items)) @@ -104,3 +110,25 @@ class InvoiceTestCase(RegistrationCartTestCase): self.assertEqual( self.PROD_1.price * Decimal("0.5"), invoice_1.invoice.value) + + def test_invoice_voids_self_if_cart_is_invalid(self): + current_cart = CartController.for_user(self.USER_1) + + # Should be able to create an invoice after the product is added + current_cart.add_to_cart(self.PROD_1, 1) + invoice_1 = InvoiceController.for_cart(current_cart.cart) + + self.assertFalse(invoice_1.invoice.void) + + # Adding item to cart should produce a new invoice + current_cart.add_to_cart(self.PROD_2, 1) + invoice_2 = InvoiceController.for_cart(current_cart.cart) + self.assertNotEqual(invoice_1.invoice, invoice_2.invoice) + + # Viewing invoice_1's invoice should show it as void + invoice_1_new = InvoiceController(invoice_1.invoice) + self.assertTrue(invoice_1.invoice.void) + + # Viewing invoice_2's invoice should *not* show it as void + invoice_2_new = InvoiceController(invoice_2.invoice) + self.assertFalse(invoice_2.invoice.void)