diff --git a/registrasion/controllers/cart.py b/registrasion/controllers/cart.py index 95a2b92173ea5afc7a149fac60031a922fcd6656..a643863f757dd5e2728d7380f847996d12e0b078 100644 --- a/registrasion/controllers/cart.py +++ b/registrasion/controllers/cart.py @@ -10,6 +10,7 @@ from django.db.models import Max from django.utils import timezone from registrasion import models as rego +from registrasion.exceptions import CartValidationError from category import CategoryController from conditions import ConditionController @@ -114,22 +115,25 @@ class CartController(object): ''' Tests that the quantity changes we intend to make do not violate the limits and enabling conditions imposed on the products. ''' + errors = [] + # Test each product limit here for product, quantity in product_quantities: if quantity < 0: # TODO: batch errors - raise ValidationError("Value must be zero or greater.") + errors.append((product, "Value must be zero or greater.")) prod = ProductController(product) limit = prod.user_quantity_remaining(self.cart.user) if quantity > limit: # TODO: batch errors - raise ValidationError( + errors.append(( + product, "You may only have %d of product: %s" % ( - limit, product.name, + limit, product, ) - ) + )) # Collect by category by_cat = collections.defaultdict(list) @@ -137,20 +141,21 @@ class CartController(object): by_cat[product.category].append((product, quantity)) # Test each category limit here - for cat in by_cat: - ctrl = CategoryController(cat) + for category in by_cat: + ctrl = CategoryController(category) limit = ctrl.user_quantity_remaining(self.cart.user) # Get the amount so far in the cart - to_add = sum(i[1] for i in by_cat[cat]) + to_add = sum(i[1] for i in by_cat[category]) if to_add > limit: # TODO: batch errors - raise ValidationError( + errors.append(( + category, "You may only have %d items in category: %s" % ( - limit, cat.name, + limit, category.name, ) - ) + )) # Test the enabling conditions errs = ConditionController.test_enabling_conditions( @@ -160,7 +165,12 @@ class CartController(object): if errs: # TODO: batch errors - raise ValidationError("An enabling condition failed") + errors.append( + ("enabling_conditions", "An enabling condition failed") + ) + + if errors: + raise CartValidationError(errors) def apply_voucher(self, voucher_code): ''' Applies the voucher with the given code to this cart. ''' diff --git a/registrasion/controllers/category.py b/registrasion/controllers/category.py index 9ab9dd3be9bb44b2f3ca36eed272cda12db4cc46..04f502db1ff67d9e1eeec98c4aa04048a3fb7575 100644 --- a/registrasion/controllers/category.py +++ b/registrasion/controllers/category.py @@ -53,4 +53,4 @@ class CategoryController(object): ) cat_count = items.aggregate(Sum("quantity"))["quantity__sum"] or 0 - cat_limit - cat_count + return cat_limit - cat_count diff --git a/registrasion/exceptions.py b/registrasion/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..ac6624d9aab7b65e17db73eceda69e44c87550f6 --- /dev/null +++ b/registrasion/exceptions.py @@ -0,0 +1,4 @@ +from django.core.exceptions import ValidationError + +class CartValidationError(ValidationError): + pass diff --git a/registrasion/views.py b/registrasion/views.py index 192f401d2fa0c63c1abc207ca2c972dfb7038697..77c00bb3f4b1231f6cdeb6d37e8c075f52adf962 100644 --- a/registrasion/views.py +++ b/registrasion/views.py @@ -6,6 +6,7 @@ from registrasion.controllers import discount from registrasion.controllers.cart import CartController from registrasion.controllers.invoice import InvoiceController from registrasion.controllers.product import ProductController +from registrasion.exceptions import CartValidationError from collections import namedtuple @@ -321,15 +322,24 @@ def handle_products(request, category, products, prefix): def set_quantities_from_products_form(products_form, current_cart): - quantities = products_form.product_quantities() + quantities = list(products_form.product_quantities()) product_quantities = [ (rego.Product.objects.get(pk=i[0]), i[1]) for i in quantities ] + field_names = dict( + (i[0][0], i[1][2]) for i in zip(product_quantities, quantities) + ) try: current_cart.set_quantities(product_quantities) - except ValidationError as ve: - products_form.add_error(None, ve) + except CartValidationError as ve: + for ve_field in ve.error_list: + product, message = ve_field.message + if product in field_names: + field = field_names[product] + else: + field = None + products_form.add_error(field, message) def handle_voucher(request, prefix):