Factors limits testing in set_quantities into _test_limits()
This commit is contained in:
parent
194f98bcc4
commit
e3ec128147
2 changed files with 20 additions and 61 deletions
|
@ -81,6 +81,17 @@ class CartController(object):
|
||||||
product__in=(i[0] for i in product_quantities),
|
product__in=(i[0] for i in product_quantities),
|
||||||
).delete()
|
).delete()
|
||||||
|
|
||||||
|
all_product_quantities = list(product_quantities) + [
|
||||||
|
(i.product, i.quantity) for i in items_in_cart.all()
|
||||||
|
]
|
||||||
|
self._test_limits(all_product_quantities)
|
||||||
|
|
||||||
|
for product, quantity in product_quantities:
|
||||||
|
self._set_quantity_old(product, quantity)
|
||||||
|
|
||||||
|
self.end_batch()
|
||||||
|
|
||||||
|
def _test_limits(self, product_quantities):
|
||||||
# Collect by category
|
# Collect by category
|
||||||
by_cat = collections.defaultdict(list)
|
by_cat = collections.defaultdict(list)
|
||||||
for product, quantity in product_quantities:
|
for product, quantity in product_quantities:
|
||||||
|
@ -92,11 +103,9 @@ class CartController(object):
|
||||||
limit = ctrl.user_quantity_remaining(self.cart.user)
|
limit = ctrl.user_quantity_remaining(self.cart.user)
|
||||||
|
|
||||||
# Get the amount so far in the cart
|
# Get the amount so far in the cart
|
||||||
cat_items = items_in_cart.filter(product__category=cat)
|
|
||||||
so_far = cat_items.aggregate(Sum("quantity"))["quantity__sum"] or 0
|
|
||||||
to_add = sum(i[1] for i in by_cat[cat])
|
to_add = sum(i[1] for i in by_cat[cat])
|
||||||
|
|
||||||
if so_far + to_add > limit:
|
if to_add > limit:
|
||||||
# TODO: batch errors
|
# TODO: batch errors
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
"You may only have %d items in category: %s" % (
|
"You may only have %d items in category: %s" % (
|
||||||
|
@ -117,23 +126,15 @@ class CartController(object):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
product_quantities_all = list(product_quantities) + [
|
# Test the enabling conditions
|
||||||
(i.product, i.quantity) for i in items_in_cart.all()
|
|
||||||
]
|
|
||||||
|
|
||||||
# Test each enabling condition here
|
|
||||||
errs = ConditionController.test_enabling_conditions(
|
errs = ConditionController.test_enabling_conditions(
|
||||||
self.cart.user,
|
self.cart.user,
|
||||||
product_quantities=product_quantities_all,
|
product_quantities=product_quantities,
|
||||||
)
|
)
|
||||||
|
|
||||||
if errs:
|
if errs:
|
||||||
raise ValidationError("Whoops")
|
# TODO: batch errors
|
||||||
|
raise ValidationError("An enabling condition failed")
|
||||||
for product, quantity in product_quantities:
|
|
||||||
self._set_quantity_old(product, quantity)
|
|
||||||
|
|
||||||
self.end_batch()
|
|
||||||
|
|
||||||
def set_quantity(self, product, quantity, batched=False):
|
def set_quantity(self, product, quantity, batched=False):
|
||||||
''' Sets the _quantity_ of the given _product_ in the cart to the given
|
''' Sets the _quantity_ of the given _product_ in the cart to the given
|
||||||
|
@ -225,17 +226,9 @@ class CartController(object):
|
||||||
# TODO: validate vouchers
|
# TODO: validate vouchers
|
||||||
|
|
||||||
items = rego.ProductItem.objects.filter(cart=self.cart)
|
items = rego.ProductItem.objects.filter(cart=self.cart)
|
||||||
for item in items:
|
|
||||||
# NOTE: per-user limits are tested at add time
|
|
||||||
# and are unliklely to change
|
|
||||||
prod = ProductController(item.product)
|
|
||||||
|
|
||||||
# If the cart is not reserved, we need to see if we can re-reserve
|
product_quantities = list((i.product, i.quantity) for i in items)
|
||||||
quantity = 0 if is_reserved else item.quantity
|
self._test_limits(product_quantities)
|
||||||
|
|
||||||
if not prod.can_add_with_enabling_conditions(
|
|
||||||
self.cart.user, quantity):
|
|
||||||
raise ValidationError("Products are no longer available")
|
|
||||||
|
|
||||||
# Validate the discounts
|
# Validate the discounts
|
||||||
discount_items = rego.DiscountItem.objects.filter(cart=self.cart)
|
discount_items = rego.DiscountItem.objects.filter(cart=self.cart)
|
||||||
|
@ -250,9 +243,7 @@ class CartController(object):
|
||||||
pk=discount.pk)
|
pk=discount.pk)
|
||||||
cond = ConditionController.for_condition(real_discount)
|
cond = ConditionController.for_condition(real_discount)
|
||||||
|
|
||||||
quantity = 0 if is_reserved else discount_item.quantity
|
if not cond.is_met(self.cart.user):
|
||||||
|
|
||||||
if not cond.is_met(self.cart.user): # TODO: REPLACE WITH QUANTITY CHECKER WHEN FIXING CEILINGS
|
|
||||||
raise ValidationError("Discounts are no longer available")
|
raise ValidationError("Discounts are no longer available")
|
||||||
|
|
||||||
def recalculate_discounts(self):
|
def recalculate_discounts(self):
|
||||||
|
|
|
@ -43,7 +43,7 @@ class ProductController(object):
|
||||||
|
|
||||||
out = list(passed_limits - failed_conditions)
|
out = list(passed_limits - failed_conditions)
|
||||||
out.sort(key=lambda product: product.order)
|
out.sort(key=lambda product: product.order)
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def user_quantity_remaining(self, user):
|
def user_quantity_remaining(self, user):
|
||||||
|
@ -70,35 +70,3 @@ class ProductController(object):
|
||||||
prod_count = items.aggregate(Sum("quantity"))["quantity__sum"] or 0
|
prod_count = items.aggregate(Sum("quantity"))["quantity__sum"] or 0
|
||||||
|
|
||||||
return prod_limit - prod_count
|
return prod_limit - prod_count
|
||||||
|
|
||||||
def can_add_with_enabling_conditions(self, user, quantity):
|
|
||||||
''' Returns true if the user is able to add _quantity_ to their count
|
|
||||||
of this Product without exceeding the ceilings the product is attached
|
|
||||||
to. '''
|
|
||||||
|
|
||||||
conditions = rego.EnablingConditionBase.objects.filter(
|
|
||||||
Q(products=self.product) | Q(categories=self.product.category)
|
|
||||||
).select_subclasses()
|
|
||||||
|
|
||||||
mandatory_violated = False
|
|
||||||
non_mandatory_met = False
|
|
||||||
|
|
||||||
for condition in conditions:
|
|
||||||
cond = ConditionController.for_condition(condition)
|
|
||||||
met = cond.is_met(user)
|
|
||||||
|
|
||||||
if condition.mandatory and not met:
|
|
||||||
mandatory_violated = True
|
|
||||||
break
|
|
||||||
if met:
|
|
||||||
non_mandatory_met = True
|
|
||||||
|
|
||||||
if mandatory_violated:
|
|
||||||
# All mandatory conditions must be met
|
|
||||||
return False
|
|
||||||
|
|
||||||
if len(conditions) > 0 and not non_mandatory_met:
|
|
||||||
# If there's any non-mandatory conditions, one must be met
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
Loading…
Reference in a new issue