Adds user_quantity_remaining to CategoryController
This commit is contained in:
parent
39021cd3dd
commit
576dddcaad
3 changed files with 76 additions and 17 deletions
|
@ -1,14 +1,16 @@
|
||||||
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
import discount
|
import discount
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Max
|
from django.db.models import Max, Sum
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from registrasion import models as rego
|
from registrasion import models as rego
|
||||||
|
|
||||||
|
from category import CategoryController
|
||||||
from conditions import ConditionController
|
from conditions import ConditionController
|
||||||
from product import ProductController
|
from product import ProductController
|
||||||
|
|
||||||
|
@ -71,12 +73,40 @@ class CartController(object):
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def set_quantities(self, product_quantities):
|
def set_quantities(self, product_quantities):
|
||||||
|
|
||||||
|
items_in_cart = rego.ProductItem.objects.filter(cart=self.cart)
|
||||||
|
|
||||||
# Remove all items that we're updating
|
# Remove all items that we're updating
|
||||||
rego.ProductItem.objects.filter(
|
items_in_cart.filter(
|
||||||
cart=self.cart,
|
|
||||||
product__in=(i[0] for i in product_quantities),
|
product__in=(i[0] for i in product_quantities),
|
||||||
).delete()
|
).delete()
|
||||||
|
|
||||||
|
# Collect by category
|
||||||
|
by_cat = collections.defaultdict(list)
|
||||||
|
for product, quantity in product_quantities:
|
||||||
|
by_cat[product.category].append((product, quantity))
|
||||||
|
|
||||||
|
# Test each category limit here
|
||||||
|
for cat in by_cat:
|
||||||
|
ctrl = CategoryController(cat)
|
||||||
|
limit = ctrl.user_quantity_remaining(self.cart.user)
|
||||||
|
|
||||||
|
# Get the amount so far in the cart
|
||||||
|
cat_items = items_in_cart.filter(product__category=cat)
|
||||||
|
so_far = cat_items.aggregate(Sum("quantity"))["quantity__sum"] or 0
|
||||||
|
to_add = sum(i[1] for i in by_cat[cat])
|
||||||
|
|
||||||
|
if so_far + to_add > limit:
|
||||||
|
# TODO: batch errors
|
||||||
|
raise ValidationError(
|
||||||
|
"You may only have %d items in category: %s" % (
|
||||||
|
limit, cat.name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test each product limit here
|
||||||
|
|
||||||
|
# Test each enabling condition here
|
||||||
|
|
||||||
for product, quantity in product_quantities:
|
for product, quantity in product_quantities:
|
||||||
self._set_quantity_old(product, quantity)
|
self._set_quantity_old(product, quantity)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from .product import ProductController
|
|
||||||
|
|
||||||
from registrasion import models as rego
|
from registrasion import models as rego
|
||||||
|
|
||||||
|
from django.db.models import Sum
|
||||||
|
|
||||||
|
|
||||||
class AllProducts(object):
|
class AllProducts(object):
|
||||||
pass
|
pass
|
||||||
|
@ -9,12 +9,18 @@ class AllProducts(object):
|
||||||
|
|
||||||
class CategoryController(object):
|
class CategoryController(object):
|
||||||
|
|
||||||
|
def __init__(self, category):
|
||||||
|
self.category = category
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def available_categories(cls, user, products=AllProducts):
|
def available_categories(cls, user, products=AllProducts):
|
||||||
''' Returns the categories available to the user. Specify `products` if
|
''' Returns the categories available to the user. Specify `products` if
|
||||||
you want to restrict to just the categories that hold the specified
|
you want to restrict to just the categories that hold the specified
|
||||||
products, otherwise it'll do all. '''
|
products, otherwise it'll do all. '''
|
||||||
|
|
||||||
|
# STOPGAP -- this needs to be elsewhere tbqh
|
||||||
|
from product import ProductController
|
||||||
|
|
||||||
if products is AllProducts:
|
if products is AllProducts:
|
||||||
products = rego.Product.objects.all()
|
products = rego.Product.objects.all()
|
||||||
|
|
||||||
|
@ -24,3 +30,33 @@ class CategoryController(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
return set(i.category for i in available)
|
return set(i.category for i in available)
|
||||||
|
|
||||||
|
def user_quantity_remaining(self, user):
|
||||||
|
''' Returns the number of items from this category that the user may
|
||||||
|
add in the current cart. '''
|
||||||
|
|
||||||
|
cat_limit = self.category.limit_per_user
|
||||||
|
|
||||||
|
if cat_limit is None:
|
||||||
|
# We don't need to waste the following queries
|
||||||
|
return 99999999
|
||||||
|
|
||||||
|
carts = rego.Cart.objects.filter(
|
||||||
|
user=user,
|
||||||
|
active=False,
|
||||||
|
released=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
items = rego.ProductItem.objects.filter(
|
||||||
|
cart__in=carts,
|
||||||
|
product__category=self.category,
|
||||||
|
)
|
||||||
|
|
||||||
|
cat_count = items.aggregate(Sum("quantity"))["quantity__sum"] or 0
|
||||||
|
|
||||||
|
cat_limit = self.category.limit_per_user
|
||||||
|
|
||||||
|
if cat_limit is None:
|
||||||
|
return 999999 # We should probably work on this.
|
||||||
|
else:
|
||||||
|
return cat_limit - cat_count
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.db.models import Q
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from registrasion import models as rego
|
from registrasion import models as rego
|
||||||
|
|
||||||
|
from category import CategoryController
|
||||||
from conditions import ConditionController
|
from conditions import ConditionController
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ class ProductController(object):
|
||||||
out = [
|
out = [
|
||||||
product
|
product
|
||||||
for product in all_products
|
for product in all_products
|
||||||
|
if CategoryController(product.category).user_quantity_remaining(user) > 0
|
||||||
if cls(product).user_can_add_within_limit(user, 1, past_carts=True)
|
if cls(product).user_can_add_within_limit(user, 1, past_carts=True)
|
||||||
if cls(product).can_add_with_enabling_conditions(user, 0)
|
if cls(product).can_add_with_enabling_conditions(user, 0)
|
||||||
]
|
]
|
||||||
|
@ -54,23 +56,14 @@ class ProductController(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
prod_items = items.filter(product=self.product)
|
prod_items = items.filter(product=self.product)
|
||||||
cat_items = items.filter(product__category=self.product.category)
|
|
||||||
|
|
||||||
prod_count = prod_items.aggregate(Sum("quantity"))["quantity__sum"]
|
prod_count = prod_items.aggregate(Sum("quantity"))["quantity__sum"]
|
||||||
cat_count = cat_items.aggregate(Sum("quantity"))["quantity__sum"]
|
prod_count = prod_count or 0
|
||||||
|
|
||||||
if prod_count is None:
|
|
||||||
prod_count = 0
|
|
||||||
if cat_count is None:
|
|
||||||
cat_count = 0
|
|
||||||
|
|
||||||
prod_limit = self.product.limit_per_user
|
prod_limit = self.product.limit_per_user
|
||||||
prod_met = prod_limit is None or quantity + prod_count <= prod_limit
|
prod_met = prod_limit is None or quantity + prod_count <= prod_limit
|
||||||
|
|
||||||
cat_limit = self.product.category.limit_per_user
|
if prod_met:
|
||||||
cat_met = cat_limit is None or quantity + cat_count <= cat_limit
|
|
||||||
|
|
||||||
if prod_met and cat_met:
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
Loading…
Reference in a new issue