Makes sure that discounts always apply to the most expensive product in the cart first. Adds test to that effect.
Fixes #88.
This commit is contained in:
parent
4026dac3a3
commit
3517bdd281
2 changed files with 27 additions and 3 deletions
|
@ -399,9 +399,11 @@ class CartController(object):
|
||||||
# Delete the existing entries.
|
# Delete the existing entries.
|
||||||
commerce.DiscountItem.objects.filter(cart=self.cart).delete()
|
commerce.DiscountItem.objects.filter(cart=self.cart).delete()
|
||||||
|
|
||||||
|
# Order the products such that the most expensive ones are
|
||||||
|
# processed first.
|
||||||
product_items = self.cart.productitem_set.all().select_related(
|
product_items = self.cart.productitem_set.all().select_related(
|
||||||
"product", "product__category", "product__price"
|
"product", "product__category", "product__price"
|
||||||
)
|
).order_by("-product__price")
|
||||||
|
|
||||||
products = [i.product for i in product_items]
|
products = [i.product for i in product_items]
|
||||||
discounts = DiscountController.available_discounts(
|
discounts = DiscountController.available_discounts(
|
||||||
|
@ -411,8 +413,7 @@ class CartController(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
# The highest-value discounts will apply to the highest-value
|
# The highest-value discounts will apply to the highest-value
|
||||||
# products first.
|
# products first, because of the order_by clause
|
||||||
product_items = reversed(product_items)
|
|
||||||
for item in product_items:
|
for item in product_items:
|
||||||
self._add_discount(item.product, item.quantity, discounts)
|
self._add_discount(item.product, item.quantity, discounts)
|
||||||
|
|
||||||
|
|
|
@ -243,6 +243,29 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
# The discount is applied.
|
# The discount is applied.
|
||||||
self.assertEqual(1, len(discount_items))
|
self.assertEqual(1, len(discount_items))
|
||||||
|
|
||||||
|
def test_discount_applies_to_most_expensive_item(self):
|
||||||
|
self.add_discount_prod_1_includes_cat_2(quantity=1)
|
||||||
|
|
||||||
|
cart = TestingCartController.for_user(self.USER_1)
|
||||||
|
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
prods = (self.PROD_3, self.PROD_4)
|
||||||
|
for first, second in itertools.permutations(prods, 2):
|
||||||
|
|
||||||
|
cart.set_quantity(first, 1)
|
||||||
|
cart.set_quantity(second, 1)
|
||||||
|
|
||||||
|
# There should only be one discount
|
||||||
|
discount_items = list(cart.cart.discountitem_set.all())
|
||||||
|
self.assertEqual(1, len(discount_items))
|
||||||
|
|
||||||
|
# It should always apply to PROD_3, as it costs more.
|
||||||
|
self.assertEqual(discount_items[0].product, self.PROD_3)
|
||||||
|
|
||||||
|
cart.set_quantity(first, 0)
|
||||||
|
cart.set_quantity(second, 0)
|
||||||
|
|
||||||
# Tests for the DiscountController.available_discounts enumerator
|
# Tests for the DiscountController.available_discounts enumerator
|
||||||
def test_enumerate_no_discounts_for_no_input(self):
|
def test_enumerate_no_discounts_for_no_input(self):
|
||||||
discounts = DiscountController.available_discounts(
|
discounts = DiscountController.available_discounts(
|
||||||
|
|
Loading…
Reference in a new issue