Adds ability to group by category instead of by product

Fixes #98.
This commit is contained in:
Christopher Neugebauer 2016-10-05 11:08:58 -07:00
parent f0ab1f944f
commit bf21d478a8
2 changed files with 56 additions and 18 deletions

View file

@ -8,6 +8,13 @@ from django import forms
# Reporting forms. # Reporting forms.
def mix_form(*a):
''' Creates a new form class out of all the supplied forms '''
bases = tuple(a)
return type("MixForm", bases, {})
class DiscountForm(forms.Form): class DiscountForm(forms.Form):
discount = forms.ModelMultipleChoiceField( discount = forms.ModelMultipleChoiceField(
queryset=conditions.DiscountBase.objects.all(), queryset=conditions.DiscountBase.objects.all(),
@ -40,6 +47,21 @@ class ProposalKindForm(forms.Form):
) )
class GroupByForm(forms.Form):
GROUP_BY_CATEGORY = "category"
GROUP_BY_PRODUCT = "product"
choices = (
(GROUP_BY_CATEGORY, "Category"),
(GROUP_BY_PRODUCT, "Product"),
)
group_by = forms.ChoiceField(
label="Group by",
choices=choices,
)
def model_fields_form_factory(model): def model_fields_form_factory(model):
''' Creates a form for specifying fields from a model to display. ''' ''' Creates a form for specifying fields from a model to display. '''

View file

@ -511,13 +511,12 @@ def attendee_list(request):
ProfileForm = forms.model_fields_form_factory(AttendeeProfile) ProfileForm = forms.model_fields_form_factory(AttendeeProfile)
class ProductCategoryProfileForm(forms.ProductAndCategoryForm, ProfileForm):
pass
@report_view( @report_view(
"Attendees By Product/Category", "Attendees By Product/Category",
form_type=ProductCategoryProfileForm, form_type=forms.mix_form(
forms.ProductAndCategoryForm, ProfileForm, forms.GroupByForm
),
) )
def attendee_data(request, form, user_id=None): def attendee_data(request, form, user_id=None):
''' Lists attendees for a given product/category selection along with ''' Lists attendees for a given product/category selection along with
@ -531,6 +530,9 @@ def attendee_data(request, form, user_id=None):
output = [] output = []
by_category = form.cleaned_data["group_by"] == forms.GroupByForm.GROUP_BY_CATEGORY
print by_category
products = form.cleaned_data["product"] products = form.cleaned_data["product"]
categories = form.cleaned_data["category"] categories = form.cleaned_data["category"]
fields = form.cleaned_data["fields"] fields = form.cleaned_data["fields"]
@ -552,16 +554,28 @@ def attendee_data(request, form, user_id=None):
for profile in profiles: for profile in profiles:
by_user[profile.attendee.user] = profile by_user[profile.attendee.user] = profile
cart = "attendee__user__cart"
cart_status = cart + "__status"
product = cart + "__productitem__product"
product_name = product + "__name"
category = product + "__category"
category_name = category + "__name"
if by_category:
grouping_fields = (category, category_name)
order_by = (category, )
first_column = "Category"
group_name = lambda i: "%s" % (i[category_name], )
else:
grouping_fields = (product, product_name, category_name)
order_by = (category, )
first_column = "Product"
group_name = lambda i: "%s - %s" % (i[category_name], i[product_name])
# Group the responses per-field. # Group the responses per-field.
for field in fields: for field in fields:
field_verbose = AttendeeProfile._meta.get_field(field).verbose_name field_verbose = AttendeeProfile._meta.get_field(field).verbose_name
cart = "attendee__user__cart"
cart_status = cart + "__status"
product = cart + "__productitem__product"
product_name = product + "__name"
category_name = product + "__category__name"
status_count = lambda status: Case(When( status_count = lambda status: Case(When(
attendee__user__cart__status=status, attendee__user__cart__status=status,
then=Value(1), then=Value(1),
@ -572,23 +586,25 @@ def attendee_data(request, form, user_id=None):
paid_count = status_count(commerce.Cart.STATUS_PAID) paid_count = status_count(commerce.Cart.STATUS_PAID)
unpaid_count = status_count(commerce.Cart.STATUS_ACTIVE) unpaid_count = status_count(commerce.Cart.STATUS_ACTIVE)
p = profiles.order_by(product, field).values( groups = profiles.order_by(
product, product_name, category_name, field *(order_by + (field, ))
).values(
*(grouping_fields + (field, ))
).annotate( ).annotate(
paid_count=Sum(paid_count), paid_count=Sum(paid_count),
unpaid_count=Sum(unpaid_count), unpaid_count=Sum(unpaid_count),
) )
output.append(ListReport( output.append(ListReport(
"Grouped by %s" % field_verbose, "Grouped by %s" % field_verbose,
["Product", field_verbose, "paid", "unpaid"], [first_column, field_verbose, "paid", "unpaid"],
[ [
( (
"%s - %s" % (i[category_name], i[product_name]), group_name(group),
i[field], group[field],
i["paid_count"] or 0, group["paid_count"] or 0,
i["unpaid_count"] or 0, group["unpaid_count"] or 0,
) )
for i in p for group in groups
], ],
)) ))