From 6a5e4ff92db8b863ae0d2f8468296c0749b47803 2016-10-13 16:37:26 From: Christopher Neugebauer Date: 2016-10-13 16:37:26 Subject: [PATCH] Merge branch 'chrisjrn/20161013' --- diff --git a/registrasion/controllers/invoice.py b/registrasion/controllers/invoice.py index 84af2a87cf3c4f32c60ef48af19ea5a86452bebf..3b675e17c4c0868db3c82434ecff79377cb4bdea 100644 --- a/registrasion/controllers/invoice.py +++ b/registrasion/controllers/invoice.py @@ -357,8 +357,18 @@ class InvoiceController(ForId, object): return cart.revision == self.invoice.cart_revision def update_validity(self): - ''' Voids this invoice if the cart it is attached to has updated. ''' - if not self._invoice_matches_cart(): + ''' Voids this invoice if the attached cart is no longer valid because + the cart revision has changed, or the reservations have expired. ''' + + is_valid = self._invoice_matches_cart() + cart = self.invoice.cart + if self.invoice.is_unpaid and is_valid and cart: + try: + CartController(cart).validate_cart() + except ValidationError: + is_valid = False + + if not is_valid: if self.invoice.total_payments() > 0: # Free up the payments made to this invoice self.refund() diff --git a/registrasion/reporting/views.py b/registrasion/reporting/views.py index c29d8cb9487591d0ce65faba9ca8237e0df5bd61..a5784014f030f3f9bd50ca005e65bef3c7bec4f7 100644 --- a/registrasion/reporting/views.py +++ b/registrasion/reporting/views.py @@ -382,6 +382,21 @@ def credit_notes(request, form): ) +@report_view("Invoices") +def invoices(request,form): + ''' Shows all of the invoices in the system. ''' + + invoices = commerce.Invoice.objects.all().order_by("status") + + return QuerysetReport( + "Invoices", + ["id", "recipient", "value", "get_status_display"], + invoices, + headings=["id", "Recipient", "Value", "Status"], + link_view=views.invoice, + ) + + class AttendeeListReport(ListReport): def get_link(self, argument): diff --git a/registrasion/tests/test_invoice.py b/registrasion/tests/test_invoice.py index a1769fe0b18376e7ea3ae0cffce83fc6b8dd47e4..5079087482ae4bcdc62d1b1310c4645527c4677e 100644 --- a/registrasion/tests/test_invoice.py +++ b/registrasion/tests/test_invoice.py @@ -168,7 +168,7 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase): self.assertTrue(invoice_1.invoice.is_paid) - def test_invoice_voids_self_if_cart_is_invalid(self): + def test_invoice_voids_self_if_cart_changes(self): current_cart = TestingCartController.for_user(self.USER_1) # Should be able to create an invoice after the product is added @@ -190,6 +190,31 @@ class InvoiceTestCase(TestHelperMixin, RegistrationCartTestCase): invoice_2_new = TestingInvoiceController(invoice_2.invoice) self.assertFalse(invoice_2_new.invoice.is_void) + def test_invoice_voids_self_if_cart_becomes_invalid(self): + ''' Invoices should be void if cart becomes invalid over time ''' + + self.make_ceiling("Limit ceiling", limit=1) + self.set_time(datetime.datetime( + year=2015, month=1, day=1, hour=0, minute=0, tzinfo=UTC, + )) + + cart1 = TestingCartController.for_user(self.USER_1) + cart2 = TestingCartController.for_user(self.USER_2) + + # Create a valid invoice for USER_1 + cart1.add_to_cart(self.PROD_1, 1) + inv1 = TestingInvoiceController.for_cart(cart1.cart) + + # Expire the reservations, and have USER_2 take up PROD_1's ceiling + # generate an invoice + self.add_timedelta(self.RESERVATION * 2) + cart2.add_to_cart(self.PROD_2, 1) + inv2 = TestingInvoiceController.for_cart(cart2.cart) + + # Re-get inv1's invoice; it should void itself on loading. + inv1 = TestingInvoiceController(inv1.invoice) + self.assertTrue(inv1.invoice.is_void) + def test_voiding_invoice_creates_new_invoice(self): invoice_1 = self._invoice_containing_prod_1(1) diff --git a/registrasion/urls.py b/registrasion/urls.py index 05b10aab8d0cac7ee5aec74ffcb06d072ec62afe..0d21854c2646fbaec9e68a7e25a23d32cf722cb9 100644 --- a/registrasion/urls.py +++ b/registrasion/urls.py @@ -49,6 +49,7 @@ reports = [ url(r"^attendee/([0-9]*)$", rv.attendee, name="attendee"), url(r"^credit_notes/?$", rv.credit_notes, name="credit_notes"), url(r"^discount_status/?$", rv.discount_status, name="discount_status"), + url(r"^invoices/?$", rv.invoices, name="invoices"), url( r"^paid_invoices_by_date/?$", rv.paid_invoices_by_date,