Makes the reporting framework a bit more DRY.
This commit is contained in:
parent
3607fb19b8
commit
32b887fed3
1 changed files with 97 additions and 107 deletions
|
@ -31,22 +31,15 @@ A table
|
||||||
|
|
||||||
class Report(object):
|
class Report(object):
|
||||||
|
|
||||||
def __init__(self, title, form, headings, data):
|
def __init__(self, title, headings, data):
|
||||||
self._title = title
|
|
||||||
self._form = form
|
|
||||||
self._headings = headings
|
self._headings = headings
|
||||||
self._data = data
|
self._data = data
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
''' Returns the form. '''
|
''' Returns the title for this report. '''
|
||||||
return self._title
|
return self._title
|
||||||
|
|
||||||
@property
|
|
||||||
def form(self):
|
|
||||||
''' Returns the form. '''
|
|
||||||
return self._form
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def headings(self):
|
def headings(self):
|
||||||
''' Returns the headings for the table. '''
|
''' Returns the headings for the table. '''
|
||||||
|
@ -58,139 +51,136 @@ class Report(object):
|
||||||
return self._data
|
return self._data
|
||||||
|
|
||||||
|
|
||||||
def report(view):
|
def report(title, form_type):
|
||||||
''' Decorator that converts a report view function into something that
|
''' Decorator that converts a report view function into something that
|
||||||
displays a Report.
|
displays a Report.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
form_type: A form class that can make this report display things.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@wraps(view)
|
def _report(view):
|
||||||
def inner_view(request, *a, **k):
|
|
||||||
report = view(request, *a, **k)
|
|
||||||
|
|
||||||
ctx = {
|
@wraps(view)
|
||||||
"title": report.title,
|
def inner_view(request, *a, **k):
|
||||||
"form": report.form,
|
|
||||||
"report": report,
|
|
||||||
}
|
|
||||||
|
|
||||||
return render(request, "registrasion/report.html", ctx)
|
form = form_type(request.GET)
|
||||||
|
if form.is_valid() and form.has_changed():
|
||||||
|
report = view(request, form, *a, **k)
|
||||||
|
else:
|
||||||
|
report = None
|
||||||
|
|
||||||
return inner_view
|
ctx = {
|
||||||
|
"title": title,
|
||||||
|
"form": form,
|
||||||
|
"report": report,
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, "registrasion/report.html", ctx)
|
||||||
|
|
||||||
|
return inner_view
|
||||||
|
return _report
|
||||||
|
|
||||||
|
|
||||||
@report
|
@report("Paid items", forms.ProductAndCategoryForm)
|
||||||
def items_sold(request):
|
def items_sold(request, form):
|
||||||
''' Summarises the items sold and discounts granted for a given set of
|
''' Summarises the items sold and discounts granted for a given set of
|
||||||
products, or products from categories. '''
|
products, or products from categories. '''
|
||||||
|
|
||||||
title = "Paid items"
|
|
||||||
|
|
||||||
form = forms.ProductAndCategoryForm(request.GET)
|
|
||||||
|
|
||||||
data = None
|
data = None
|
||||||
headings = None
|
headings = None
|
||||||
|
|
||||||
if form.is_valid() and form.has_changed():
|
products = form.cleaned_data["product"]
|
||||||
products = form.cleaned_data["product"]
|
categories = form.cleaned_data["category"]
|
||||||
categories = form.cleaned_data["category"]
|
|
||||||
|
|
||||||
line_items = commerce.LineItem.objects.filter(
|
line_items = commerce.LineItem.objects.filter(
|
||||||
Q(product__in=products) | Q(product__category__in=categories),
|
Q(product__in=products) | Q(product__category__in=categories),
|
||||||
invoice__status=commerce.Invoice.STATUS_PAID,
|
invoice__status=commerce.Invoice.STATUS_PAID,
|
||||||
).select_related("invoice")
|
).select_related("invoice")
|
||||||
|
|
||||||
line_items = line_items.order_by(
|
line_items = line_items.order_by(
|
||||||
# sqlite requires an order_by for .values() to work
|
# sqlite requires an order_by for .values() to work
|
||||||
"-price", "description",
|
"-price", "description",
|
||||||
).values(
|
).values(
|
||||||
"price", "description",
|
"price", "description",
|
||||||
).annotate(
|
).annotate(
|
||||||
total_quantity=Sum("quantity"),
|
total_quantity=Sum("quantity"),
|
||||||
)
|
)
|
||||||
|
|
||||||
print line_items
|
print line_items
|
||||||
|
|
||||||
headings = ["Description", "Quantity", "Price", "Total"]
|
headings = ["Description", "Quantity", "Price", "Total"]
|
||||||
|
|
||||||
data = []
|
|
||||||
total_income = 0
|
|
||||||
for line in line_items:
|
|
||||||
cost = line["total_quantity"] * line["price"]
|
|
||||||
data.append([
|
|
||||||
line["description"], line["total_quantity"],
|
|
||||||
line["price"], cost,
|
|
||||||
])
|
|
||||||
total_income += cost
|
|
||||||
|
|
||||||
|
data = []
|
||||||
|
total_income = 0
|
||||||
|
for line in line_items:
|
||||||
|
cost = line["total_quantity"] * line["price"]
|
||||||
data.append([
|
data.append([
|
||||||
"(TOTAL)", "--", "--", total_income,
|
line["description"], line["total_quantity"],
|
||||||
|
line["price"], cost,
|
||||||
])
|
])
|
||||||
|
total_income += cost
|
||||||
|
|
||||||
return Report(title, form, headings, data)
|
data.append([
|
||||||
|
"(TOTAL)", "--", "--", total_income,
|
||||||
|
])
|
||||||
|
|
||||||
|
return Report("Paid items", headings, data)
|
||||||
|
|
||||||
|
|
||||||
@report
|
@report("Inventory", forms.ProductAndCategoryForm)
|
||||||
def inventory(request):
|
def inventory(request, form):
|
||||||
''' Summarises the inventory status of the given items, grouping by
|
''' Summarises the inventory status of the given items, grouping by
|
||||||
invoice status. '''
|
invoice status. '''
|
||||||
|
|
||||||
title = "Inventory"
|
products = form.cleaned_data["product"]
|
||||||
|
categories = form.cleaned_data["category"]
|
||||||
|
|
||||||
form = forms.ProductAndCategoryForm(request.GET)
|
items = commerce.ProductItem.objects.filter(
|
||||||
|
Q(product__in=products) | Q(product__category__in=categories),
|
||||||
|
).select_related("cart", "product")
|
||||||
|
|
||||||
data = None
|
# TODO annotate with whether the item is reserved or not.
|
||||||
headings = None
|
|
||||||
|
|
||||||
if form.is_valid() and form.has_changed():
|
items = items.annotate(is_reserved=Case(
|
||||||
products = form.cleaned_data["product"]
|
When(cart__in=commerce.Cart.reserved_carts(), then=Value(1)),
|
||||||
categories = form.cleaned_data["category"]
|
default=Value(0),
|
||||||
|
output_field=models.BooleanField(),
|
||||||
|
))
|
||||||
|
|
||||||
items = commerce.ProductItem.objects.filter(
|
items = items.order_by(
|
||||||
Q(product__in=products) | Q(product__category__in=categories),
|
"cart__status",
|
||||||
).select_related("cart", "product")
|
"product__category__order",
|
||||||
|
"product__order",
|
||||||
|
).values(
|
||||||
|
"product",
|
||||||
|
"product__category__name",
|
||||||
|
"product__name",
|
||||||
|
"cart__status",
|
||||||
|
"is_reserved",
|
||||||
|
).annotate(
|
||||||
|
total_quantity=Sum("quantity"),
|
||||||
|
)
|
||||||
|
|
||||||
# TODO annotate with whether the item is reserved or not.
|
headings = ["Product", "Status", "Quantity"]
|
||||||
|
data = []
|
||||||
|
|
||||||
items = items.annotate(is_reserved=Case(
|
def status(reserved, status):
|
||||||
When(cart__in=commerce.Cart.reserved_carts(), then=Value(1)),
|
r = "Reserved" if reserved else "Unreserved"
|
||||||
default=Value(0),
|
# This is a bit weird -- can we simplify?
|
||||||
output_field=models.BooleanField(),
|
s = "".join(
|
||||||
))
|
"%s" % i[1] for i in commerce.Cart.STATUS_TYPES if i[0]==status
|
||||||
|
|
||||||
items = items.order_by(
|
|
||||||
"cart__status",
|
|
||||||
"product__category__order",
|
|
||||||
"product__order",
|
|
||||||
).values(
|
|
||||||
"product",
|
|
||||||
"product__category__name",
|
|
||||||
"product__name",
|
|
||||||
"cart__status",
|
|
||||||
"is_reserved",
|
|
||||||
).annotate(
|
|
||||||
total_quantity=Sum("quantity"),
|
|
||||||
)
|
)
|
||||||
|
return "%s - %s" % (r, s)
|
||||||
|
|
||||||
headings = ["Product", "Status", "Quantity"]
|
for item in items:
|
||||||
data = []
|
data.append([
|
||||||
|
"%s - %s" % (
|
||||||
|
item["product__category__name"], item["product__name"]
|
||||||
|
),
|
||||||
|
status(item["is_reserved"], item["cart__status"]),
|
||||||
|
item["total_quantity"],
|
||||||
|
])
|
||||||
|
|
||||||
def status(reserved, status):
|
return Report("Inventory", headings, data)
|
||||||
r = "Reserved" if reserved else "Unreserved"
|
|
||||||
s = "".join(
|
|
||||||
"%s" % i[1]
|
|
||||||
for i in commerce.Cart.STATUS_TYPES if i[0]==status
|
|
||||||
)
|
|
||||||
return "%s - %s" % (r, s)
|
|
||||||
|
|
||||||
for item in items:
|
|
||||||
print commerce.Cart.STATUS_TYPES
|
|
||||||
data.append([
|
|
||||||
"%s - %s" % (
|
|
||||||
item["product__category__name"], item["product__name"]
|
|
||||||
),
|
|
||||||
status(item["is_reserved"], item["cart__status"]),
|
|
||||||
item["total_quantity"],
|
|
||||||
])
|
|
||||||
|
|
||||||
return Report(title, form, headings, data)
|
|
||||||
|
|
Loading…
Reference in a new issue