diff --git a/registrasion/controllers/invoice.py b/registrasion/controllers/invoice.py index 3b675e17..7b35ea58 100644 --- a/registrasion/controllers/invoice.py +++ b/registrasion/controllers/invoice.py @@ -331,10 +331,7 @@ class InvoiceController(ForId, object): def _mark_refunded(self): ''' Marks the invoice as refunded, and updates the attached cart if necessary. ''' - cart = self.invoice.cart - if cart: - cart.status = commerce.Cart.STATUS_RELEASED - cart.save() + self._release_cart() self.invoice.status = commerce.Invoice.STATUS_REFUNDED self.invoice.save() @@ -356,6 +353,12 @@ class InvoiceController(ForId, object): return cart.revision == self.invoice.cart_revision + def _release_cart(self): + cart = self.invoice.cart + if cart: + cart.status = commerce.Cart.STATUS_RELEASED + cart.save() + def update_validity(self): ''' Voids this invoice if the attached cart is no longer valid because the cart revision has changed, or the reservations have expired. ''' @@ -381,6 +384,9 @@ class InvoiceController(ForId, object): raise ValidationError("Invoices with payments must be refunded.") elif self.invoice.is_refunded: raise ValidationError("Refunded invoices may not be voided.") + if self.invoice.is_paid: + self._release_cart() + self._mark_void() @transaction.atomic diff --git a/registrasion/tests/test_invoice.py b/registrasion/tests/test_invoice.py index 50790874..61e1abc9 100644 --- a/registrasion/tests/test_invoice.py +++ b/registrasion/tests/test_invoice.py @@ -142,7 +142,7 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase): self.PROD_1.price * Decimal("0.5"), invoice_1.invoice.value) - def test_zero_value_invoice_is_automatically_paid(self): + def _make_zero_value_invoice(self): voucher = inventory.Voucher.objects.create( recipient="Voucher recipient", code="VOUCHER", @@ -164,10 +164,21 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase): # Should be able to create an invoice after the product is added current_cart.add_to_cart(self.PROD_1, 1) - invoice_1 = TestingInvoiceController.for_cart(current_cart.cart) + return TestingInvoiceController.for_cart(current_cart.cart) + + def test_zero_value_invoice_is_automatically_paid(self): + invoice_1 = self._make_zero_value_invoice() self.assertTrue(invoice_1.invoice.is_paid) + def test_refunding_zero_value_invoice_releases_cart(self): + invoice_1 = self._make_zero_value_invoice() + cart = invoice_1.invoice.cart + invoice_1.refund() + + cart.refresh_from_db() + self.assertEquals(commerce.Cart.STATUS_RELEASED, cart.status) + def test_invoice_voids_self_if_cart_changes(self): current_cart = TestingCartController.for_user(self.USER_1)