Fixes various errors in discount calculation, and adds tests for these

This commit is contained in:
Christopher Neugebauer 2016-03-04 13:07:45 -08:00
parent 99f4b8dfe0
commit 0182a32f03
3 changed files with 51 additions and 6 deletions

View file

@ -183,7 +183,12 @@ class CartController(object):
# Delete the existing entries. # Delete the existing entries.
rego.DiscountItem.objects.filter(cart=self.cart).delete() rego.DiscountItem.objects.filter(cart=self.cart).delete()
for item in self.cart.productitem_set.all(): # The highest-value discounts will apply to the highest-value
# products first.
product_items = self.cart.productitem_set.all()
product_items = product_items.order_by('product__price')
product_items = reversed(product_items)
for item in product_items:
self._add_discount(item.product, item.quantity) self._add_discount(item.product, item.quantity)
def _add_discount(self, product, quantity): def _add_discount(self, product, quantity):
@ -202,9 +207,7 @@ class CartController(object):
# Get the count of past uses of this discount condition # Get the count of past uses of this discount condition
# as this affects the total amount we're allowed to use now. # as this affects the total amount we're allowed to use now.
past_uses = rego.DiscountItem.objects.filter( past_uses = rego.DiscountItem.objects.filter(
cart__active=False,
discount=discount.discount, discount=discount.discount,
product=product,
) )
agg = past_uses.aggregate(Sum("quantity")) agg = past_uses.aggregate(Sum("quantity"))
past_uses = agg["quantity__sum"] past_uses = agg["quantity__sum"]

View file

@ -82,7 +82,18 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
limit_per_user=10, limit_per_user=10,
order=10, order=10,
) )
cls.PROD_2.save() cls.PROD_3.save()
cls.PROD_4 = rego.Product.objects.create(
name="Product 4",
description="This is a test product. It costs $5. "
"A user may have 10 of them.",
category=cls.CAT_2,
price=Decimal("5.00"),
limit_per_user=10,
order=10,
)
cls.PROD_4.save()
@classmethod @classmethod
def make_ceiling(cls, name, limit=None, start_time=None, end_time=None): def make_ceiling(cls, name, limit=None, start_time=None, end_time=None):

View file

@ -29,7 +29,10 @@ class DiscountTestCase(RegistrationCartTestCase):
return discount return discount
@classmethod @classmethod
def add_discount_prod_1_includes_cat_2(cls, amount=Decimal(100)): def add_discount_prod_1_includes_cat_2(
cls,
amount=Decimal(100),
quantity=2):
discount = rego.IncludedProductDiscount.objects.create( discount = rego.IncludedProductDiscount.objects.create(
description="PROD_1 includes CAT_2 " + str(amount) + "%", description="PROD_1 includes CAT_2 " + str(amount) + "%",
) )
@ -40,7 +43,7 @@ class DiscountTestCase(RegistrationCartTestCase):
discount=discount, discount=discount,
category=cls.CAT_2, category=cls.CAT_2,
percentage=amount, percentage=amount,
quantity=2 quantity=quantity,
).save() ).save()
return discount return discount
@ -169,3 +172,31 @@ class DiscountTestCase(RegistrationCartTestCase):
discount_items = list(cart.cart.discountitem_set.all()) discount_items = list(cart.cart.discountitem_set.all())
self.assertEqual(2, discount_items[0].quantity) self.assertEqual(2, discount_items[0].quantity)
def test_category_discount_applies_once_per_category(self):
self.add_discount_prod_1_includes_cat_2(quantity=1)
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
# Add two items from category 2
cart.add_to_cart(self.PROD_3, 1)
cart.add_to_cart(self.PROD_4, 1)
discount_items = list(cart.cart.discountitem_set.all())
# There is one discount, and it should apply to one item.
self.assertEqual(1, len(discount_items))
self.assertEqual(1, discount_items[0].quantity)
def test_category_discount_applies_to_highest_value(self):
self.add_discount_prod_1_includes_cat_2(quantity=1)
cart = CartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
# Add two items from category 2, add the less expensive one first
cart.add_to_cart(self.PROD_4, 1)
cart.add_to_cart(self.PROD_3, 1)
discount_items = list(cart.cart.discountitem_set.all())
# There is one discount, and it should apply to the more expensive.
self.assertEqual(1, len(discount_items))
self.assertEqual(self.PROD_3, discount_items[0].product)