From 3e4e52b165b3379f6d85405e8dbc8d2463ef77dc Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer Date: Sun, 27 Mar 2016 14:41:43 +1100 Subject: [PATCH] Adds more constraints around payment and voiding of invoices --- registrasion/controllers/invoice.py | 21 ++++++++++++--- registrasion/tests/test_invoice.py | 41 +++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/registrasion/controllers/invoice.py b/registrasion/controllers/invoice.py index 47765358..19da7525 100644 --- a/registrasion/controllers/invoice.py +++ b/registrasion/controllers/invoice.py @@ -1,5 +1,6 @@ from decimal import Decimal from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ValidationError from django.db.models import Sum from registrasion import models as rego @@ -11,7 +12,7 @@ class InvoiceController(object): def __init__(self, invoice): self.invoice = invoice - self.update_validity() # Make sure this invoice is up-to-date + self.update_validity() # Make sure this invoice is up-to-date @classmethod def for_cart(cls, cart): @@ -21,13 +22,16 @@ class InvoiceController(object): try: invoice = rego.Invoice.objects.get( - cart=cart, cart_revision=cart.revision) + cart=cart, + cart_revision=cart.revision, + void=False, + ) 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) + rego.Invoice.objects.filter(cart=cart).update(void=True) invoice = cls._generate(cart) @@ -104,7 +108,10 @@ class InvoiceController(object): self.void() def void(self): - ''' Voids the invoice. ''' + ''' Voids the invoice if it is valid to do so. ''' + if self.invoice.paid: + raise ValidationError("Paid invoices cannot be voided, " + "only refunded.") self.invoice.void = True self.invoice.save() @@ -117,6 +124,12 @@ class InvoiceController(object): cart = CartController(self.invoice.cart) cart.validate_cart() # Raises ValidationError if invalid + if self.invoice.void: + raise ValidationError("Void invoices cannot be paid") + + if self.invoice.paid: + raise ValidationError("Paid invoices cannot be paid again") + ''' Adds a payment ''' payment = rego.Payment.objects.create( invoice=self.invoice, diff --git a/registrasion/tests/test_invoice.py b/registrasion/tests/test_invoice.py index b3f80314..37265a2a 100644 --- a/registrasion/tests/test_invoice.py +++ b/registrasion/tests/test_invoice.py @@ -127,8 +127,45 @@ class InvoiceTestCase(RegistrationCartTestCase): # Viewing invoice_1's invoice should show it as void invoice_1_new = InvoiceController(invoice_1.invoice) - self.assertTrue(invoice_1.invoice.void) + self.assertTrue(invoice_1_new.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) + self.assertFalse(invoice_2_new.invoice.void) + + def test_voiding_invoice_creates_new_invoice(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) + invoice_1.void() + + invoice_2 = InvoiceController.for_cart(current_cart.cart) + self.assertNotEqual(invoice_1.invoice, invoice_2.invoice) + + def test_cannot_pay_void_invoice(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) + + invoice_1.void() + + with self.assertRaises(ValidationError): + invoice_1.pay("Reference", invoice_1.invoice.value) + + def test_cannot_void_paid_invoice(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) + + invoice_1.pay("Reference", invoice_1.invoice.value) + + with self.assertRaises(ValidationError): + invoice_1.void()