Factors items_pending and items_purchased into ItemController

This commit is contained in:
Christopher Neugebauer 2016-09-02 15:57:20 +10:00
parent 17fc874212
commit 68aa9b067b
2 changed files with 101 additions and 78 deletions

View file

@ -0,0 +1,95 @@
''' NEEDS TESTS '''
from registrasion.models import commerce
from registrasion.models import inventory
from collections import namedtuple
from django.db.models import Case
from django.db.models import Q
from django.db.models import Sum
from django.db.models import When
from django.db.models import Value
_ProductAndQuantity = namedtuple("ProductAndQuantity", ["product", "quantity"])
class ProductAndQuantity(_ProductAndQuantity):
''' Class that holds a product and a quantity.
Attributes:
product (models.inventory.Product)
quantity (int)
'''
pass
class ItemController(object):
def __init__(self, user):
self.user = user
def items_purchased(self, category=None):
''' Aggregates the items that this user has purchased.
Arguments:
category (Optional[models.inventory.Category]): the category
of items to restrict to.
Returns:
[ProductAndQuantity, ...]: A list of product-quantity pairs,
aggregating like products from across multiple invoices.
'''
in_cart = (
Q(productitem__cart__user=self.user) &
Q(productitem__cart__status=commerce.Cart.STATUS_PAID)
)
quantities_in_cart = When(
in_cart,
then="productitem__quantity",
)
quantities_or_zero = Case(
quantities_in_cart,
default=Value(0),
)
products = inventory.Product.objects
if category:
products = products.filter(category=category)
products = products.select_related("category")
products = products.annotate(quantity=Sum(quantities_or_zero))
products = products.filter(quantity__gt=0)
out = []
for prod in products:
out.append(ProductAndQuantity(prod, prod.quantity))
return out
def items_pending(self):
''' Gets all of the items that the user has reserved, but has not yet
paid for.
Returns:
[ProductAndQuantity, ...]: A list of product-quantity pairs for the
items that the user has not yet paid for.
'''
all_items = commerce.ProductItem.objects.filter(
cart__user=self.user,
cart__status=commerce.Cart.STATUS_ACTIVE,
).select_related(
"product",
"product__category",
).order_by(
"product__category__order",
"product__order",
)
return all_items

View file

@ -1,31 +1,12 @@
from registrasion.models import commerce
from registrasion.models import inventory
from registrasion.controllers.category import CategoryController
from registrasion.controllers.item import ItemController
from collections import namedtuple
from django import template
from django.db.models import Case
from django.db.models import Q
from django.db.models import Sum
from django.db.models import When
from django.db.models import Value
register = template.Library()
_ProductAndQuantity = namedtuple("ProductAndQuantity", ["product", "quantity"])
class ProductAndQuantity(_ProductAndQuantity):
''' Class that holds a product and a quantity.
Attributes:
product (models.inventory.Product)
quantity (int)
'''
pass
@register.assignment_tag(takes_context=True)
def available_categories(context):
@ -67,71 +48,18 @@ def invoices(context):
@register.assignment_tag(takes_context=True)
def items_pending(context):
''' Gets all of the items that the user has reserved, but has not yet
paid for.
Returns:
[ProductAndQuantity, ...]: A list of product-quantity pairs for the
items that the user has not yet paid for.
'''
all_items = commerce.ProductItem.objects.filter(
cart__user=context.request.user,
cart__status=commerce.Cart.STATUS_ACTIVE,
).select_related(
"product",
"product__category",
).order_by(
"product__category__order",
"product__order",
)
return all_items
''' Gets all of the items that the user from this context has reserved.'''
return ItemController(context.request.user).items_pending()
@register.assignment_tag(takes_context=True)
def items_purchased(context, category=None):
''' Aggregates the items that this user has purchased.
''' Returns the items purchased for this user. '''
Arguments:
category (Optional[models.inventory.Category]): the category of items
to restrict to.
Returns:
[ProductAndQuantity, ...]: A list of product-quantity pairs,
aggregating like products from across multiple invoices.
'''
in_cart = (
Q(productitem__cart__user=context.request.user) &
Q(productitem__cart__status=commerce.Cart.STATUS_PAID)
return ItemController(context.request.user).items_purchased(
category=category
)
quantities_in_cart = When(
in_cart,
then="productitem__quantity",
)
quantities_or_zero = Case(
quantities_in_cart,
default=Value(0),
)
products = inventory.Product.objects
if category:
products = products.filter(category=category)
products = products.select_related("category")
products = products.annotate(quantity=Sum(quantities_or_zero))
products = products.filter(quantity__gt=0)
out = []
for prod in products:
out.append(ProductAndQuantity(prod, prod.quantity))
return out
@register.filter
def multiply(value, arg):