Refactors discount ceiling testing to make sure that the discount ceiling only considers items where the discount was applied in determining if the discount was reached.

This commit is contained in:
Christopher Neugebauer 2016-04-03 12:53:36 +10:00
parent eab1deff77
commit 4d134e95d7
4 changed files with 78 additions and 39 deletions

View file

@ -33,9 +33,9 @@ class ConditionController(object):
rego.IncludedProductDiscount: ProductConditionController,
rego.ProductEnablingCondition: ProductConditionController,
rego.TimeOrStockLimitDiscount:
TimeOrStockLimitConditionController,
TimeOrStockLimitDiscountController,
rego.TimeOrStockLimitEnablingCondition:
TimeOrStockLimitConditionController,
TimeOrStockLimitEnablingConditionController,
rego.VoucherDiscount: VoucherConditionController,
rego.VoucherEnablingCondition: VoucherConditionController,
}
@ -184,7 +184,7 @@ class ProductConditionController(ConditionController):
class TimeOrStockLimitConditionController(ConditionController):
''' Condition tests for TimeOrStockLimit EnablingCondition and
''' Common condition tests for TimeOrStockLimit EnablingCondition and
Discount.'''
def __init__(self, ceiling):
@ -213,23 +213,6 @@ class TimeOrStockLimitConditionController(ConditionController):
return True
def _products(self):
''' Abstracts away the product list, becuase enabling conditions
list products differently to discounts. '''
if isinstance(self.ceiling, rego.TimeOrStockLimitEnablingCondition):
category_products = rego.Product.objects.filter(
category__in=self.ceiling.categories.all(),
)
return self.ceiling.products.all() | category_products
else:
categories = rego.Category.objects.filter(
discountforcategory__discount=self.ceiling,
)
return rego.Product.objects.filter(
Q(discountforproduct__discount=self.ceiling) |
Q(category__in=categories.all())
)
def _get_remaining_stock(self, user):
''' Returns the stock that remains under this ceiling, excluding the
user's current cart. '''
@ -244,15 +227,35 @@ class TimeOrStockLimitConditionController(ConditionController):
active=True,
)
product_items = rego.ProductItem.objects.filter(
product__in=self._products().all(),
)
product_items = product_items.filter(cart__in=reserved_carts)
count = product_items.aggregate(Sum("quantity"))["quantity__sum"] or 0
items = self._items()
items = items.filter(cart__in=reserved_carts)
count = items.aggregate(Sum("quantity"))["quantity__sum"] or 0
return self.ceiling.limit - count
class TimeOrStockLimitEnablingConditionController(
TimeOrStockLimitConditionController):
def _items(self):
category_products = rego.Product.objects.filter(
category__in=self.ceiling.categories.all(),
)
products = self.ceiling.products.all() | category_products
product_items = rego.ProductItem.objects.filter(
product__in=products.all(),
)
return product_items
class TimeOrStockLimitDiscountController(TimeOrStockLimitConditionController):
def _items(self):
discount_items = rego.DiscountItem.objects.filter(
discount=self.ceiling,
)
return discount_items
class VoucherConditionController(ConditionController):
''' Condition test for VoucherEnablingCondition and VoucherDiscount.'''

View file

@ -110,7 +110,8 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
@classmethod
def make_discount_ceiling(
cls, name, limit=None, start_time=None, end_time=None):
cls, name, limit=None, start_time=None, end_time=None,
percentage=100):
limit_ceiling = rego.TimeOrStockLimitDiscount.objects.create(
description=name,
start_time=start_time,
@ -121,11 +122,22 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
rego.DiscountForProduct.objects.create(
discount=limit_ceiling,
product=cls.PROD_1,
percentage=100,
percentage=percentage,
quantity=10,
).save()
@classmethod
def new_voucher(self, code="VOUCHER", limit=1):
voucher = rego.Voucher.objects.create(
recipient="Voucher recipient",
code=code,
limit=limit,
)
voucher.save()
return voucher
class BasicCartTests(RegistrationCartTestCase):
def test_get_cart(self):

View file

@ -4,9 +4,10 @@ import pytz
from django.core.exceptions import ValidationError
from cart_controller_helper import TestingCartController
from test_cart import RegistrationCartTestCase
from registrasion import models as rego
UTC = pytz.timezone('UTC')
@ -150,3 +151,36 @@ class CeilingsTestCases(RegistrationCartTestCase):
first_cart.cart.save()
second_cart.add_to_cart(self.PROD_1, 1)
def test_discount_ceiling_only_counts_items_covered_by_ceiling(self):
self.make_discount_ceiling("Limit ceiling", limit=1, percentage=50)
voucher = self.new_voucher(code="VOUCHER")
discount = rego.VoucherDiscount.objects.create(
description="VOUCHER RECIPIENT",
voucher=voucher,
)
discount.save()
rego.DiscountForProduct.objects.create(
discount=discount,
product=self.PROD_1,
percentage=100,
quantity=1
).save()
# Buy two of PROD_1, in separate carts:
cart = TestingCartController.for_user(self.USER_1)
# the 100% discount from the voucher should apply to the first item
# and not the ceiling discount.
cart.apply_voucher("VOUCHER")
cart.add_to_cart(self.PROD_1, 1)
self.assertEqual(1, len(cart.cart.discountitem_set.all()))
cart.cart.active = False
cart.cart.save()
# The second cart has no voucher attached, so should apply the
# ceiling discount
cart = TestingCartController.for_user(self.USER_1)
cart.add_to_cart(self.PROD_1, 1)
self.assertEqual(1, len(cart.cart.discountitem_set.all()))

View file

@ -16,16 +16,6 @@ UTC = pytz.timezone('UTC')
class VoucherTestCases(RegistrationCartTestCase):
@classmethod
def new_voucher(self, code="VOUCHER", limit=1):
voucher = rego.Voucher.objects.create(
recipient="Voucher recipient",
code=code,
limit=limit,
)
voucher.save()
return voucher
def test_apply_voucher(self):
voucher = self.new_voucher()