Propagates the error messages up from enabling condition testing
This commit is contained in:
parent
0340b6da20
commit
40bc5985f4
3 changed files with 40 additions and 8 deletions
|
@ -120,14 +120,12 @@ class CartController(object):
|
||||||
# Test each product limit here
|
# Test each product limit here
|
||||||
for product, quantity in product_quantities:
|
for product, quantity in product_quantities:
|
||||||
if quantity < 0:
|
if quantity < 0:
|
||||||
# TODO: batch errors
|
|
||||||
errors.append((product, "Value must be zero or greater."))
|
errors.append((product, "Value must be zero or greater."))
|
||||||
|
|
||||||
prod = ProductController(product)
|
prod = ProductController(product)
|
||||||
limit = prod.user_quantity_remaining(self.cart.user)
|
limit = prod.user_quantity_remaining(self.cart.user)
|
||||||
|
|
||||||
if quantity > limit:
|
if quantity > limit:
|
||||||
# TODO: batch errors
|
|
||||||
errors.append((
|
errors.append((
|
||||||
product,
|
product,
|
||||||
"You may only have %d of product: %s" % (
|
"You may only have %d of product: %s" % (
|
||||||
|
@ -149,7 +147,6 @@ class CartController(object):
|
||||||
to_add = sum(i[1] for i in by_cat[category])
|
to_add = sum(i[1] for i in by_cat[category])
|
||||||
|
|
||||||
if to_add > limit:
|
if to_add > limit:
|
||||||
# TODO: batch errors
|
|
||||||
errors.append((
|
errors.append((
|
||||||
category,
|
category,
|
||||||
"You may only have %d items in category: %s" % (
|
"You may only have %d items in category: %s" % (
|
||||||
|
@ -164,10 +161,8 @@ class CartController(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
if errs:
|
if errs:
|
||||||
# TODO: batch errors
|
for error in errs:
|
||||||
errors.append(
|
errors.append(error)
|
||||||
("enabling_conditions", "An enabling condition failed")
|
|
||||||
)
|
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
raise CartValidationError(errors)
|
raise CartValidationError(errors)
|
||||||
|
|
|
@ -44,6 +44,26 @@ class ConditionController(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return ConditionController()
|
return ConditionController()
|
||||||
|
|
||||||
|
|
||||||
|
SINGLE = True
|
||||||
|
PLURAL = False
|
||||||
|
NONE = True
|
||||||
|
SOME = False
|
||||||
|
MESSAGE = {
|
||||||
|
NONE: {
|
||||||
|
SINGLE:
|
||||||
|
"%(items)s is no longer available to you",
|
||||||
|
PLURAL:
|
||||||
|
"%(items)s are no longer available to you",
|
||||||
|
},
|
||||||
|
SOME: {
|
||||||
|
SINGLE:
|
||||||
|
"Only %(remainder)d of the following item remains: %(items)s",
|
||||||
|
PLURAL:
|
||||||
|
"Only %(remainder)d of the following items remain: %(items)s"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def test_enabling_conditions(
|
def test_enabling_conditions(
|
||||||
cls, user, products=None, product_quantities=None):
|
cls, user, products=None, product_quantities=None):
|
||||||
|
@ -83,6 +103,8 @@ class ConditionController(object):
|
||||||
# if there are no mandatory conditions
|
# if there are no mandatory conditions
|
||||||
non_mandatory = defaultdict(lambda: False)
|
non_mandatory = defaultdict(lambda: False)
|
||||||
|
|
||||||
|
messages = {}
|
||||||
|
|
||||||
for condition in all_conditions:
|
for condition in all_conditions:
|
||||||
cond = cls.for_condition(condition)
|
cond = cls.for_condition(condition)
|
||||||
remainder = cond.user_quantity_remaining(user)
|
remainder = cond.user_quantity_remaining(user)
|
||||||
|
@ -104,12 +126,21 @@ class ConditionController(object):
|
||||||
consumed = 1
|
consumed = 1
|
||||||
met = consumed <= remainder
|
met = consumed <= remainder
|
||||||
|
|
||||||
|
if not met:
|
||||||
|
items = ", ".join(str(product) for product in all_products)
|
||||||
|
base = cls.MESSAGE[remainder == 0][len(all_products) == 1]
|
||||||
|
message = base % {"items": items, "remainder": remainder}
|
||||||
|
|
||||||
for product in all_products:
|
for product in all_products:
|
||||||
if condition.mandatory:
|
if condition.mandatory:
|
||||||
mandatory[product] &= met
|
mandatory[product] &= met
|
||||||
else:
|
else:
|
||||||
non_mandatory[product] |= met
|
non_mandatory[product] |= met
|
||||||
|
|
||||||
|
if not met and product not in messages:
|
||||||
|
messages[product] = message
|
||||||
|
|
||||||
|
|
||||||
valid = defaultdict(lambda: True)
|
valid = defaultdict(lambda: True)
|
||||||
for product in itertools.chain(mandatory, non_mandatory):
|
for product in itertools.chain(mandatory, non_mandatory):
|
||||||
if product in mandatory:
|
if product in mandatory:
|
||||||
|
@ -119,7 +150,11 @@ class ConditionController(object):
|
||||||
# Otherwise, we need just one non-mandatory condition met
|
# Otherwise, we need just one non-mandatory condition met
|
||||||
valid[product] = non_mandatory[product]
|
valid[product] = non_mandatory[product]
|
||||||
|
|
||||||
error_fields = [product for product in valid if not valid[product]]
|
error_fields = [
|
||||||
|
(product, messages[product])
|
||||||
|
for product in valid if not valid[product]
|
||||||
|
]
|
||||||
|
|
||||||
return error_fields
|
return error_fields
|
||||||
|
|
||||||
def user_quantity_remaining(self, user):
|
def user_quantity_remaining(self, user):
|
||||||
|
|
|
@ -337,6 +337,8 @@ def set_quantities_from_products_form(products_form, current_cart):
|
||||||
product, message = ve_field.message
|
product, message = ve_field.message
|
||||||
if product in field_names:
|
if product in field_names:
|
||||||
field = field_names[product]
|
field = field_names[product]
|
||||||
|
elif isinstance(product, rego.Product):
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
field = None
|
field = None
|
||||||
products_form.add_error(field, message)
|
products_form.add_error(field, message)
|
||||||
|
|
Loading…
Reference in a new issue