Adds user_quantity_remaining to CategoryController

This commit is contained in:
Christopher Neugebauer 2016-04-02 14:03:25 +11:00
parent 39021cd3dd
commit 576dddcaad
3 changed files with 76 additions and 17 deletions

View file

@ -1,14 +1,16 @@
import collections
import datetime
import discount
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.models import Max
from django.db.models import Max, Sum
from django.utils import timezone
from registrasion import models as rego
from category import CategoryController
from conditions import ConditionController
from product import ProductController
@ -71,12 +73,40 @@ class CartController(object):
@transaction.atomic
def set_quantities(self, product_quantities):
items_in_cart = rego.ProductItem.objects.filter(cart=self.cart)
# Remove all items that we're updating
rego.ProductItem.objects.filter(
cart=self.cart,
items_in_cart.filter(
product__in=(i[0] for i in product_quantities),
).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:
self._set_quantity_old(product, quantity)

View file

@ -1,7 +1,7 @@
from .product import ProductController
from registrasion import models as rego
from django.db.models import Sum
class AllProducts(object):
pass
@ -9,12 +9,18 @@ class AllProducts(object):
class CategoryController(object):
def __init__(self, category):
self.category = category
@classmethod
def available_categories(cls, user, products=AllProducts):
''' Returns the categories available to the user. Specify `products` if
you want to restrict to just the categories that hold the specified
products, otherwise it'll do all. '''
# STOPGAP -- this needs to be elsewhere tbqh
from product import ProductController
if products is AllProducts:
products = rego.Product.objects.all()
@ -24,3 +30,33 @@ class CategoryController(object):
)
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

View file

@ -4,6 +4,7 @@ from django.db.models import Q
from django.db.models import Sum
from registrasion import models as rego
from category import CategoryController
from conditions import ConditionController
@ -32,6 +33,7 @@ class ProductController(object):
out = [
product
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).can_add_with_enabling_conditions(user, 0)
]
@ -54,23 +56,14 @@ class ProductController(object):
)
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"]
cat_count = cat_items.aggregate(Sum("quantity"))["quantity__sum"]
if prod_count is None:
prod_count = 0
if cat_count is None:
cat_count = 0
prod_count = prod_count or 0
prod_limit = self.product.limit_per_user
prod_met = prod_limit is None or quantity + prod_count <= prod_limit
cat_limit = self.product.category.limit_per_user
cat_met = cat_limit is None or quantity + cat_count <= cat_limit
if prod_met and cat_met:
if prod_met:
return True
else:
return False