Factors limits testing in set_quantities into _test_limits()

This commit is contained in:
Christopher Neugebauer 2016-04-02 18:10:33 +11:00
parent 194f98bcc4
commit e3ec128147
2 changed files with 20 additions and 61 deletions

View file

@ -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):

View file

@ -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