From c9c9d2a2b22092bfaa5f07325829e325f94b02ca Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer Date: Thu, 13 Oct 2016 10:50:48 -0700 Subject: [PATCH 1/2] Cancelled presentations no longer enable SpeakerCondition. Fixes #94 --- registrasion/controllers/conditions.py | 7 +++++- registrasion/tests/test_speaker.py | 30 +++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/registrasion/controllers/conditions.py b/registrasion/controllers/conditions.py index 01f53e7e..87fb9cfb 100644 --- a/registrasion/controllers/conditions.py +++ b/registrasion/controllers/conditions.py @@ -310,7 +310,12 @@ class SpeakerConditionController(IsMetByFilter, ConditionController): @classmethod def pre_filter(self, queryset, user): ''' Returns all of the items from queryset which are enabled by a user - being a presenter or copresenter of a proposal. ''' + being a presenter or copresenter of a non-cancelled proposal. ''' + + # Filter out cancelled proposals + queryset = queryset.filter( + proposal_kind__proposalbase__presentation__cancelled=False + ) u = user # User is a presenter diff --git a/registrasion/tests/test_speaker.py b/registrasion/tests/test_speaker.py index e3b14ed0..5fe80d76 100644 --- a/registrasion/tests/test_speaker.py +++ b/registrasion/tests/test_speaker.py @@ -11,8 +11,10 @@ from registrasion.controllers.product import ProductController from symposion.conference import models as conference_models from symposion.proposals import models as proposal_models -from symposion.speakers import models as speaker_models from symposion.reviews.models import promote_proposal +from symposion.schedule import models as schedule_models +from symposion.speakers import models as speaker_models + from test_cart import RegistrationCartTestCase @@ -207,3 +209,29 @@ class SpeakerTestCase(RegistrationCartTestCase): products=[self.PROD_1], ) self.assertNotIn(self.PROD_1, available_1) + + def test_proposal_cancelled_disables_condition(self): + self._create_proposals() + self._create_flag_for_primary_speaker() + + # USER_1 cannot see PROD_1 until proposal is promoted. + available = ProductController.available_products( + self.USER_1, + products=[self.PROD_1], + ) + self.assertNotIn(self.PROD_1, available) + + # promote proposal_1 so that USER_1 becomes a speaker + promote_proposal(self.PROPOSAL_1) + presentation = schedule_models.Presentation.objects.get( + proposal_base=self.PROPOSAL_1 + ) + presentation.cancelled = True + presentation.save() + + # USER_1 can *NOT* see PROD_1 because proposal_1 has been cancelled + available_after_cancelled = ProductController.available_products( + self.USER_1, + products=[self.PROD_1], + ) + self.assertNotIn(self.PROD_1, available_after_cancelled) From 3f192c2626da9d53fc3a431f486935c80ba78fb2 Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer Date: Thu, 13 Oct 2016 11:23:41 -0700 Subject: [PATCH 2/2] Zeroed & paid invoices that are voided now release the cart. Fixes #95. --- registrasion/controllers/invoice.py | 14 ++++++++++---- registrasion/tests/test_invoice.py | 15 +++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) 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)