From 68aa9b067bdb2d25c2ed50fa19ff95e816312724 Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer Date: Fri, 2 Sep 2016 15:57:20 +1000 Subject: [PATCH] Factors items_pending and items_purchased into ItemController --- registrasion/controllers/item.py | 95 +++++++++++++++++++ .../templatetags/registrasion_tags.py | 84 ++-------------- 2 files changed, 101 insertions(+), 78 deletions(-) create mode 100644 registrasion/controllers/item.py diff --git a/registrasion/controllers/item.py b/registrasion/controllers/item.py new file mode 100644 index 00000000..a36604e5 --- /dev/null +++ b/registrasion/controllers/item.py @@ -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 diff --git a/registrasion/templatetags/registrasion_tags.py b/registrasion/templatetags/registrasion_tags.py index 9074781c..2d6f51a4 100644 --- a/registrasion/templatetags/registrasion_tags.py +++ b/registrasion/templatetags/registrasion_tags.py @@ -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):