diff --git a/registrasion/controllers/cart.py b/registrasion/controllers/cart.py index a643863f..76c3adef 100644 --- a/registrasion/controllers/cart.py +++ b/registrasion/controllers/cart.py @@ -203,15 +203,35 @@ class CartController(object): ''' Determines whether the status of the current cart is valid; this is normally called before generating or paying an invoice ''' + cart = self.cart + user = self.cart.user + errors = [] + # TODO: validate vouchers - items = rego.ProductItem.objects.filter(cart=self.cart) + items = rego.ProductItem.objects.filter(cart=cart) + + products = set(i.product for i in items) + available = set(ProductController.available_products( + user, + products=products, + )) + + if products != available: + # Then we have products that aren't available any more. + for product in products: + if product not in available: + message = "%s is no longer available to you." % product + errors.append(ValidationError(message)) product_quantities = list((i.product, i.quantity) for i in items) - self._test_limits(product_quantities) + try: + self._test_limits(product_quantities) + except ValidationError as ve: + errors.append(ve) # Validate the discounts - discount_items = rego.DiscountItem.objects.filter(cart=self.cart) + discount_items = rego.DiscountItem.objects.filter(cart=cart) seen_discounts = set() for discount_item in discount_items: @@ -223,12 +243,17 @@ class CartController(object): pk=discount.pk) cond = ConditionController.for_condition(real_discount) - if not cond.is_met(self.cart.user): - raise ValidationError("Discounts are no longer available") + if not cond.is_met(user): + errors.append( + ValidationError("Discounts are no longer available") + ) + if errors: + raise ValidationError(errors) + + @transaction.atomic def recalculate_discounts(self): ''' Calculates all of the discounts available for this product. - NB should be transactional, and it's terribly inefficient. ''' # Delete the existing entries. diff --git a/registrasion/tests/test_enabling_condition.py b/registrasion/tests/test_enabling_condition.py index e6c090dd..2e992d7a 100644 --- a/registrasion/tests/test_enabling_condition.py +++ b/registrasion/tests/test_enabling_condition.py @@ -293,3 +293,19 @@ class EnablingConditionTestCases(RegistrationCartTestCase): self.assertTrue(self.CAT_1 in cats) self.assertTrue(self.CAT_2 in cats) + + def test_validate_cart_when_enabling_conditions_become_unmet(self): + self.add_product_enabling_condition(mandatory=False) + + cart = TestingCartController.for_user(self.USER_1) + cart.add_to_cart(self.PROD_2, 1) + cart.add_to_cart(self.PROD_1, 1) + + # Should pass + cart.validate_cart() + + cart.set_quantity(self.PROD_2, 0) + + # Should fail + with self.assertRaises(ValidationError): + cart.validate_cart()