Flake8 fixes
This commit is contained in:
parent
71de0df5dc
commit
162db24817
9 changed files with 86 additions and 35 deletions
|
@ -1,6 +1,5 @@
|
||||||
import collections
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
import discount
|
|
||||||
import functools
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
@ -378,7 +377,11 @@ class CartController(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
products = [i.product for i in product_items]
|
products = [i.product for i in product_items]
|
||||||
discounts = DiscountController.available_discounts(self.cart.user, [], products)
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.cart.user,
|
||||||
|
[],
|
||||||
|
products,
|
||||||
|
)
|
||||||
|
|
||||||
# The highest-value discounts will apply to the highest-value
|
# The highest-value discounts will apply to the highest-value
|
||||||
# products first.
|
# products first.
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
import itertools
|
import itertools
|
||||||
import operator
|
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
from django.db.models import Case
|
from django.db.models import Case
|
||||||
from django.db.models import Count
|
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from django.db.models import Value
|
from django.db.models import Value
|
||||||
|
@ -234,9 +229,9 @@ class TimeOrStockLimitFlagController(
|
||||||
reserved_carts = cls._relevant_carts(user)
|
reserved_carts = cls._relevant_carts(user)
|
||||||
|
|
||||||
# Calculate category lines
|
# Calculate category lines
|
||||||
cat_items = F('categories__product__productitem__product__category')
|
item_cats = F('categories__product__productitem__product__category')
|
||||||
reserved_category_products = (
|
reserved_category_products = (
|
||||||
Q(categories=F('categories__product__productitem__product__category')) &
|
Q(categories=item_cats) &
|
||||||
Q(categories__product__productitem__cart__in=reserved_carts)
|
Q(categories__product__productitem__cart__in=reserved_carts)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -46,16 +46,17 @@ class DiscountController(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def available_discounts(cls, user, categories, products):
|
def available_discounts(cls, user, categories, products):
|
||||||
''' Returns all discounts available to this user for the given categories
|
''' Returns all discounts available to this user for the given
|
||||||
and products. The discounts also list the available quantity for this user,
|
categories and products. The discounts also list the available quantity
|
||||||
not including products that are pending purchase. '''
|
for this user, not including products that are pending purchase. '''
|
||||||
|
|
||||||
|
|
||||||
filtered_clauses = cls._filtered_discounts(user, categories, products)
|
filtered_clauses = cls._filtered_discounts(user, categories, products)
|
||||||
|
|
||||||
discounts = []
|
discounts = []
|
||||||
|
|
||||||
# Markers so that we don't need to evaluate given conditions more than once
|
# Markers so that we don't need to evaluate given conditions
|
||||||
|
# more than once
|
||||||
accepted_discounts = set()
|
accepted_discounts = set()
|
||||||
failed_discounts = set()
|
failed_discounts = set()
|
||||||
|
|
||||||
|
@ -71,7 +72,8 @@ class DiscountController(object):
|
||||||
pass
|
pass
|
||||||
elif discount not in failed_discounts:
|
elif discount not in failed_discounts:
|
||||||
# This clause is still available
|
# This clause is still available
|
||||||
if discount in accepted_discounts or cond.is_met(user, filtered=True):
|
is_accepted = discount in accepted_discounts
|
||||||
|
if is_accepted or cond.is_met(user, filtered=True):
|
||||||
# This clause is valid for this user
|
# This clause is valid for this user
|
||||||
discounts.append(DiscountAndQuantity(
|
discounts.append(DiscountAndQuantity(
|
||||||
discount=discount,
|
discount=discount,
|
||||||
|
@ -89,12 +91,15 @@ class DiscountController(object):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Sequence[discountbase]: All discounts that passed the filter function.
|
Sequence[discountbase]: All discounts that passed the filter
|
||||||
|
function.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
types = list(ConditionController._controllers())
|
types = list(ConditionController._controllers())
|
||||||
discounttypes = [i for i in types if issubclass(i, conditions.DiscountBase)]
|
discounttypes = [
|
||||||
|
i for i in types if issubclass(i, conditions.DiscountBase)
|
||||||
|
]
|
||||||
|
|
||||||
# discounts that match provided categories
|
# discounts that match provided categories
|
||||||
category_discounts = conditions.DiscountForCategory.objects.filter(
|
category_discounts = conditions.DiscountForCategory.objects.filter(
|
||||||
|
@ -105,7 +110,8 @@ class DiscountController(object):
|
||||||
product__in=products
|
product__in=products
|
||||||
)
|
)
|
||||||
# discounts that match categories for provided products
|
# discounts that match categories for provided products
|
||||||
product_category_discounts = conditions.DiscountForCategory.objects.filter(
|
product_category_discounts = conditions.DiscountForCategory.objects
|
||||||
|
product_category_discounts = product_category_discounts.filter(
|
||||||
category__in=(product.category for product in products)
|
category__in=(product.category for product in products)
|
||||||
)
|
)
|
||||||
# (Not relevant: discounts that match products in provided categories)
|
# (Not relevant: discounts that match products in provided categories)
|
||||||
|
@ -115,7 +121,9 @@ class DiscountController(object):
|
||||||
"product__category",
|
"product__category",
|
||||||
)
|
)
|
||||||
|
|
||||||
all_category_discounts = category_discounts | product_category_discounts
|
all_category_discounts = (
|
||||||
|
category_discounts | product_category_discounts
|
||||||
|
)
|
||||||
all_category_discounts = all_category_discounts.select_related(
|
all_category_discounts = all_category_discounts.select_related(
|
||||||
"category",
|
"category",
|
||||||
)
|
)
|
||||||
|
@ -136,7 +144,8 @@ class DiscountController(object):
|
||||||
|
|
||||||
filtered_discounts = list(itertools.chain(*all_subsets))
|
filtered_discounts = list(itertools.chain(*all_subsets))
|
||||||
|
|
||||||
# Map from discount key to itself (contains annotations added by filter)
|
# Map from discount key to itself
|
||||||
|
# (contains annotations needed in the future)
|
||||||
from_filter = dict((i.id, i) for i in filtered_discounts)
|
from_filter = dict((i.id, i) for i in filtered_discounts)
|
||||||
|
|
||||||
# The set of all potential discounts
|
# The set of all potential discounts
|
||||||
|
@ -171,5 +180,7 @@ class DiscountController(object):
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
)
|
)
|
||||||
|
|
||||||
queryset = queryset.annotate(past_use_count=Sum(past_use_quantity_or_zero))
|
queryset = queryset.annotate(
|
||||||
|
past_use_count=Sum(past_use_quantity_or_zero)
|
||||||
|
)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
|
@ -228,12 +228,19 @@ class FlagCounter(_FlagCounter):
|
||||||
# Get the count of how many conditions should exist per product
|
# Get the count of how many conditions should exist per product
|
||||||
flagbases = conditions.FlagBase.objects
|
flagbases = conditions.FlagBase.objects
|
||||||
|
|
||||||
types = (conditions.FlagBase.ENABLE_IF_TRUE, conditions.FlagBase.DISABLE_IF_FALSE)
|
types = (
|
||||||
|
conditions.FlagBase.ENABLE_IF_TRUE,
|
||||||
|
conditions.FlagBase.DISABLE_IF_FALSE,
|
||||||
|
)
|
||||||
keys = ("eit", "dif")
|
keys = ("eit", "dif")
|
||||||
flags = [
|
flags = [
|
||||||
flagbases.filter(condition=condition_type
|
flagbases.filter(
|
||||||
).values('products', 'categories'
|
condition=condition_type
|
||||||
).annotate(count=Count('id'))
|
).values(
|
||||||
|
'products', 'categories'
|
||||||
|
).annotate(
|
||||||
|
count=Count('id')
|
||||||
|
)
|
||||||
for condition_type in types
|
for condition_type in types
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ from registrasion.models import commerce
|
||||||
from registrasion.models import inventory
|
from registrasion.models import inventory
|
||||||
|
|
||||||
from .category import CategoryController
|
from .category import CategoryController
|
||||||
from .conditions import ConditionController
|
|
||||||
from .flag import FlagController
|
from .flag import FlagController
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase):
|
||||||
super(RegistrationCartTestCase, self).setUp()
|
super(RegistrationCartTestCase, self).setUp()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if False:
|
if True:
|
||||||
# If you're seeing segfaults in tests, enable this.
|
# If you're seeing segfaults in tests, enable this.
|
||||||
call_command(
|
call_command(
|
||||||
'flush',
|
'flush',
|
||||||
|
|
|
@ -149,7 +149,11 @@ class CeilingsTestCases(RegistrationCartTestCase):
|
||||||
cart.add_to_cart(self.PROD_1, 1)
|
cart.add_to_cart(self.PROD_1, 1)
|
||||||
cart.next_cart()
|
cart.next_cart()
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [], [self.PROD_1])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[],
|
||||||
|
[self.PROD_1],
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(0, len(discounts))
|
self.assertEqual(0, len(discounts))
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,11 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
|
|
||||||
# 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(self.USER_1, [], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(0, len(discounts))
|
self.assertEqual(0, len(discounts))
|
||||||
|
|
||||||
def test_enumerate_no_discounts_if_condition_not_met(self):
|
def test_enumerate_no_discounts_if_condition_not_met(self):
|
||||||
|
@ -258,7 +262,11 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(0, len(discounts))
|
self.assertEqual(0, len(discounts))
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [self.CAT_2], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[self.CAT_2],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(0, len(discounts))
|
self.assertEqual(0, len(discounts))
|
||||||
|
|
||||||
def test_category_discount_appears_once_if_met_twice(self):
|
def test_category_discount_appears_once_if_met_twice(self):
|
||||||
|
@ -280,7 +288,11 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
cart = TestingCartController.for_user(self.USER_1)
|
cart = TestingCartController.for_user(self.USER_1)
|
||||||
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [self.CAT_2], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[self.CAT_2],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(1, len(discounts))
|
self.assertEqual(1, len(discounts))
|
||||||
|
|
||||||
def test_category_discount_appears_with_product(self):
|
def test_category_discount_appears_with_product(self):
|
||||||
|
@ -328,7 +340,11 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
cart = TestingCartController.for_user(self.USER_1)
|
cart = TestingCartController.for_user(self.USER_1)
|
||||||
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [self.CAT_1], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[self.CAT_1],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(0, len(discounts))
|
self.assertEqual(0, len(discounts))
|
||||||
|
|
||||||
def test_discount_quantity_is_correct_before_first_purchase(self):
|
def test_discount_quantity_is_correct_before_first_purchase(self):
|
||||||
|
@ -338,7 +354,11 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
cart.add_to_cart(self.PROD_1, 1) # Enable the discount
|
||||||
cart.add_to_cart(self.PROD_3, 1) # Exhaust the quantity
|
cart.add_to_cart(self.PROD_3, 1) # Exhaust the quantity
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [self.CAT_2], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[self.CAT_2],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(2, discounts[0].quantity)
|
self.assertEqual(2, discounts[0].quantity)
|
||||||
|
|
||||||
cart.next_cart()
|
cart.next_cart()
|
||||||
|
@ -349,14 +369,22 @@ class DiscountTestCase(RegistrationCartTestCase):
|
||||||
cart = TestingCartController.for_user(self.USER_1)
|
cart = TestingCartController.for_user(self.USER_1)
|
||||||
cart.add_to_cart(self.PROD_3, 1) # Exhaust the quantity
|
cart.add_to_cart(self.PROD_3, 1) # Exhaust the quantity
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [self.CAT_2], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[self.CAT_2],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(1, discounts[0].quantity)
|
self.assertEqual(1, discounts[0].quantity)
|
||||||
|
|
||||||
cart.next_cart()
|
cart.next_cart()
|
||||||
|
|
||||||
def test_discount_is_gone_after_quantity_exhausted(self):
|
def test_discount_is_gone_after_quantity_exhausted(self):
|
||||||
self.test_discount_quantity_is_correct_after_first_purchase()
|
self.test_discount_quantity_is_correct_after_first_purchase()
|
||||||
discounts = DiscountController.available_discounts(self.USER_1, [self.CAT_2], [])
|
discounts = DiscountController.available_discounts(
|
||||||
|
self.USER_1,
|
||||||
|
[self.CAT_2],
|
||||||
|
[],
|
||||||
|
)
|
||||||
self.assertEqual(0, len(discounts))
|
self.assertEqual(0, len(discounts))
|
||||||
|
|
||||||
def test_product_discount_enabled_twice_appears_twice(self):
|
def test_product_discount_enabled_twice_appears_twice(self):
|
||||||
|
|
|
@ -427,7 +427,11 @@ def _handle_products(request, category, products, prefix):
|
||||||
)
|
)
|
||||||
handled = False if products_form.errors else True
|
handled = False if products_form.errors else True
|
||||||
|
|
||||||
discounts = DiscountController.available_discounts(request.user, [], products)
|
discounts = DiscountController.available_discounts(
|
||||||
|
request.user,
|
||||||
|
[],
|
||||||
|
products,
|
||||||
|
)
|
||||||
|
|
||||||
return products_form, discounts, handled
|
return products_form, discounts, handled
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue