diff --git a/registrasion/controllers/cart.py b/registrasion/controllers/cart.py index 597dd47b..47340c15 100644 --- a/registrasion/controllers/cart.py +++ b/registrasion/controllers/cart.py @@ -1,6 +1,5 @@ import collections import datetime -import discount import functools import itertools @@ -378,7 +377,11 @@ class CartController(object): ) 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 # products first. diff --git a/registrasion/controllers/conditions.py b/registrasion/controllers/conditions.py index c0847b10..0a2b3c4a 100644 --- a/registrasion/controllers/conditions.py +++ b/registrasion/controllers/conditions.py @@ -1,11 +1,6 @@ import itertools -import operator - -from collections import defaultdict -from collections import namedtuple from django.db.models import Case -from django.db.models import Count from django.db.models import F, Q from django.db.models import Sum from django.db.models import Value @@ -234,9 +229,9 @@ class TimeOrStockLimitFlagController( reserved_carts = cls._relevant_carts(user) # Calculate category lines - cat_items = F('categories__product__productitem__product__category') + item_cats = F('categories__product__productitem__product__category') reserved_category_products = ( - Q(categories=F('categories__product__productitem__product__category')) & + Q(categories=item_cats) & Q(categories__product__productitem__cart__in=reserved_carts) ) diff --git a/registrasion/controllers/discount.py b/registrasion/controllers/discount.py index c04ed42d..1c7fa59f 100644 --- a/registrasion/controllers/discount.py +++ b/registrasion/controllers/discount.py @@ -46,16 +46,17 @@ class DiscountController(object): @classmethod def available_discounts(cls, user, categories, products): - ''' Returns all discounts available to this user for the given categories - and products. The discounts also list the available quantity for this user, - not including products that are pending purchase. ''' + ''' Returns all discounts available to this user for the given + categories and products. The discounts also list the available quantity + for this user, not including products that are pending purchase. ''' filtered_clauses = cls._filtered_discounts(user, categories, products) 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() failed_discounts = set() @@ -71,7 +72,8 @@ class DiscountController(object): pass elif discount not in failed_discounts: # 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 discounts.append(DiscountAndQuantity( discount=discount, @@ -89,12 +91,15 @@ class DiscountController(object): ''' Returns: - Sequence[discountbase]: All discounts that passed the filter function. + Sequence[discountbase]: All discounts that passed the filter + function. ''' 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 category_discounts = conditions.DiscountForCategory.objects.filter( @@ -105,7 +110,8 @@ class DiscountController(object): product__in=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) ) # (Not relevant: discounts that match products in provided categories) @@ -115,7 +121,9 @@ class DiscountController(object): "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( "category", ) @@ -136,7 +144,8 @@ class DiscountController(object): 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) # The set of all potential discounts @@ -171,5 +180,7 @@ class DiscountController(object): 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 diff --git a/registrasion/controllers/flag.py b/registrasion/controllers/flag.py index 40901931..a67a0b94 100644 --- a/registrasion/controllers/flag.py +++ b/registrasion/controllers/flag.py @@ -228,12 +228,19 @@ class FlagCounter(_FlagCounter): # Get the count of how many conditions should exist per product 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") flags = [ - flagbases.filter(condition=condition_type - ).values('products', 'categories' - ).annotate(count=Count('id')) + flagbases.filter( + condition=condition_type + ).values( + 'products', 'categories' + ).annotate( + count=Count('id') + ) for condition_type in types ] diff --git a/registrasion/controllers/product.py b/registrasion/controllers/product.py index 09f66bb3..e1ad9ef7 100644 --- a/registrasion/controllers/product.py +++ b/registrasion/controllers/product.py @@ -5,7 +5,6 @@ from registrasion.models import commerce from registrasion.models import inventory from .category import CategoryController -from .conditions import ConditionController from .flag import FlagController diff --git a/registrasion/tests/test_cart.py b/registrasion/tests/test_cart.py index 507d5cf7..790c1df9 100644 --- a/registrasion/tests/test_cart.py +++ b/registrasion/tests/test_cart.py @@ -26,7 +26,7 @@ class RegistrationCartTestCase(SetTimeMixin, TestCase): super(RegistrationCartTestCase, self).setUp() def tearDown(self): - if False: + if True: # If you're seeing segfaults in tests, enable this. call_command( 'flush', diff --git a/registrasion/tests/test_ceilings.py b/registrasion/tests/test_ceilings.py index bd28b598..87b54946 100644 --- a/registrasion/tests/test_ceilings.py +++ b/registrasion/tests/test_ceilings.py @@ -149,7 +149,11 @@ class CeilingsTestCases(RegistrationCartTestCase): cart.add_to_cart(self.PROD_1, 1) 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)) diff --git a/registrasion/tests/test_discount.py b/registrasion/tests/test_discount.py index fd8302de..4b92c81b 100644 --- a/registrasion/tests/test_discount.py +++ b/registrasion/tests/test_discount.py @@ -245,7 +245,11 @@ class DiscountTestCase(RegistrationCartTestCase): # Tests for the DiscountController.available_discounts enumerator 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)) def test_enumerate_no_discounts_if_condition_not_met(self): @@ -258,7 +262,11 @@ class DiscountTestCase(RegistrationCartTestCase): ) 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)) 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.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)) def test_category_discount_appears_with_product(self): @@ -328,7 +340,11 @@ class DiscountTestCase(RegistrationCartTestCase): cart = TestingCartController.for_user(self.USER_1) 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)) 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_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) cart.next_cart() @@ -349,14 +369,22 @@ class DiscountTestCase(RegistrationCartTestCase): cart = TestingCartController.for_user(self.USER_1) 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) cart.next_cart() def test_discount_is_gone_after_quantity_exhausted(self): 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)) def test_product_discount_enabled_twice_appears_twice(self): diff --git a/registrasion/views.py b/registrasion/views.py index bdfcf551..416afe0a 100644 --- a/registrasion/views.py +++ b/registrasion/views.py @@ -427,7 +427,11 @@ def _handle_products(request, category, products, prefix): ) 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