From 00476498a8f4faac682224a897795dae2862579a Mon Sep 17 00:00:00 2001 From: Christopher Neugebauer Date: Thu, 25 Aug 2016 20:33:19 +1000 Subject: [PATCH] Very first attempt at a staff-facing report (items sold) --- registrasion/forms.py | 13 +++++ registrasion/staff_views.py | 101 ++++++++++++++++++++++++++++++++++++ registrasion/urls.py | 2 + 3 files changed, 116 insertions(+) create mode 100644 registrasion/staff_views.py diff --git a/registrasion/forms.py b/registrasion/forms.py index 552ea991..7e7ddc16 100644 --- a/registrasion/forms.py +++ b/registrasion/forms.py @@ -345,3 +345,16 @@ class VoucherForm(forms.Form): help_text="If you have a voucher code, enter it here", required=False, ) + + +# Staff-facing forms. + +class ProductAndCategoryForm(forms.Form): + product = forms.ModelMultipleChoiceField( + queryset=inventory.Product.objects.all(), + required=False, + ) + category = forms.ModelMultipleChoiceField( + queryset=inventory.Category.objects.all(), + required=False, + ) diff --git a/registrasion/staff_views.py b/registrasion/staff_views.py new file mode 100644 index 00000000..d0debd78 --- /dev/null +++ b/registrasion/staff_views.py @@ -0,0 +1,101 @@ +import forms + +from django.db.models import Q +from django.shortcuts import render +from functools import wraps + +from models import commerce + + +''' + +All reports must be viewable by staff only (permissions?) + +Reports can have: + +A form + * Reports are all *gettable* - you can save a URL and get back to the same + report + * Fetching a report *cannot* break the underlying data. +A table + * Headings + * Data lines + * Formats are pluggable + +''' + + +class Report(object): + + def __init__(self, form, headings, data): + self._form = form + self._headings = headings + self._data = data + + @property + def form(self): + ''' Returns the form. ''' + return self._form + + @property + def headings(self): + ''' Returns the headings for the table. ''' + return self._headings + + @property + def data(self): + ''' Returns the data rows for the table. ''' + return self._data + + +def report(view): + ''' Decorator that converts a report view function into something that + displays a Report. + + ''' + print "hello" + + @wraps(view) + def inner_view(request, *a, **k): + print "lol" + report = view(request, *a, **k) + + ctx = { + "form": report.form, + "report": report, + } + + return render(request, "registrasion/report.html", ctx) + + return inner_view + + +@report +def items_sold(request): + ''' Summarises the items sold and discounts granted for a given set of + products, or products from categories. ''' + + print "beep" + + form = forms.ProductAndCategoryForm(request.GET) + + data = None + headings = None + + if form.is_valid() and form.has_changed(): + products = form.cleaned_data["product"] + categories = form.cleaned_data["category"] + + # TODO augment the form to allow us to filter by invoice status. + line_items = commerce.LineItem.objects.filter( + Q(product=products) | Q(product__category=categories), + invoice__status=commerce.Invoice.STATUS_PAID, + ).select_related("invoice") + + headings = ["invoice_id", "description", "quantity", "price"] + + data = [] + for line in line_items: + data.append([line.invoice.id, line.description, line.quantity, line.price]) + + return Report(form, headings, data) diff --git a/registrasion/urls.py b/registrasion/urls.py index 412e7f7c..89c2aac8 100644 --- a/registrasion/urls.py +++ b/registrasion/urls.py @@ -1,4 +1,5 @@ import views +import staff_views from django.conf.urls import url, patterns @@ -30,4 +31,5 @@ urlpatterns = [ url(r"^register$", guided_registration, name="guided_registration"), url(r"^register/([0-9]+)$", guided_registration, name="guided_registration"), + url(r"^report$", staff_views.items_sold, name="items_sold"), # TODO: rm ]