diff --git a/registrasion/controllers/cart.py b/registrasion/controllers/cart.py index 76c3adef..6fef142f 100644 --- a/registrasion/controllers/cart.py +++ b/registrasion/controllers/cart.py @@ -210,7 +210,6 @@ class CartController(object): # TODO: validate vouchers items = rego.ProductItem.objects.filter(cart=cart) - products = set(i.product for i in items) available = set(ProductController.available_products( user, @@ -251,6 +250,28 @@ class CartController(object): if errors: raise ValidationError(errors) + def fix_simple_errors(self): + ''' This attempts to fix the easy errors raised by ValidationError. + This includes removing items from the cart that are no longer + available, recalculating all of the discounts, and removing voucher + codes that are no longer available. ''' + + # TODO: fix vouchers first (this affects available discounts) + + # Fix products and discounts + items = rego.ProductItem.objects.filter(cart=self.cart) + products = set(i.product for i in items) + available = set(ProductController.available_products( + self.cart.user, + products=products, + )) + + not_available = products - available + zeros = [(product, 0) for product in not_available] + + self.set_quantities(zeros) + + @transaction.atomic def recalculate_discounts(self): ''' Calculates all of the discounts available for this product. diff --git a/registrasion/tests/test_enabling_condition.py b/registrasion/tests/test_enabling_condition.py index 2e992d7a..6dd3d102 100644 --- a/registrasion/tests/test_enabling_condition.py +++ b/registrasion/tests/test_enabling_condition.py @@ -309,3 +309,32 @@ class EnablingConditionTestCases(RegistrationCartTestCase): # Should fail with self.assertRaises(ValidationError): cart.validate_cart() + + def test_fix_simple_errors_resolves_unavailable_products(self): + self.test_validate_cart_when_enabling_conditions_become_unmet() + cart = TestingCartController.for_user(self.USER_1) + + # Should just remove all of the unavailable products + cart.fix_simple_errors() + # Should now succeed + cart.validate_cart() + + # Should keep PROD_2 in the cart + items = rego.ProductItem.objects.filter(cart=cart.cart) + self.assertFalse([i for i in items if i.product == self.PROD_1]) + + def test_fix_simple_errors_does_not_remove_limited_items(self): + cart = TestingCartController.for_user(self.USER_1) + + cart.add_to_cart(self.PROD_2, 1) + cart.add_to_cart(self.PROD_1, 10) + + # Should just remove all of the unavailable products + cart.fix_simple_errors() + # Should now succeed + cart.validate_cart() + + # Should keep PROD_2 in the cart + # and also PROD_1, which is now exhausted for user. + items = rego.ProductItem.objects.filter(cart=cart.cart) + self.assertTrue([i for i in items if i.product == self.PROD_1])