diff --git a/registrasion/forms.py b/registrasion/forms.py index 25a54768..fb429b55 100644 --- a/registrasion/forms.py +++ b/registrasion/forms.py @@ -413,31 +413,11 @@ def staff_products_formset_factory(user): return forms.formset_factory(form_type) -class InvoiceEmailForm(forms.Form): - - ACTION_PREVIEW = 1 - ACTION_SEND = 2 - - ACTION_CHOICES = ( - (ACTION_PREVIEW, "Preview"), - (ACTION_SEND, "Send emails"), - ) - +class InvoicesWithProductAndStatusForm(forms.Form): invoice = forms.ModelMultipleChoiceField( widget=forms.CheckboxSelectMultiple, queryset=commerce.Invoice.objects.all(), ) - from_email = forms.CharField() - subject = forms.CharField() - body = forms.CharField( - widget=forms.Textarea, - ) - action = forms.TypedChoiceField( - widget=forms.RadioSelect, - coerce=int, - choices=ACTION_CHOICES, - initial=ACTION_PREVIEW, - ) def __init__(self, *a, **k): category = k.pop('category', None) or [] @@ -447,7 +427,7 @@ class InvoiceEmailForm(forms.Form): category = [int(i) for i in category] product = [int(i) for i in product] - super(InvoiceEmailForm, self).__init__(*a, **k) + super(InvoicesWithProductAndStatusForm, self).__init__(*a, **k) print status qs = commerce.Invoice.objects.filter( @@ -462,5 +442,30 @@ class InvoiceEmailForm(forms.Form): id__in=qs, ) + qs = qs.select_related("user__attendee__attendeeprofilebase") + self.fields['invoice'].queryset = qs self.fields['invoice'].initial = [i.id for i in qs] + + +class InvoiceEmailForm(InvoicesWithProductAndStatusForm): + + ACTION_PREVIEW = 1 + ACTION_SEND = 2 + + ACTION_CHOICES = ( + (ACTION_PREVIEW, "Preview"), + (ACTION_SEND, "Send emails"), + ) + + from_email = forms.CharField() + subject = forms.CharField() + body = forms.CharField( + widget=forms.Textarea, + ) + action = forms.TypedChoiceField( + widget=forms.RadioSelect, + coerce=int, + choices=ACTION_CHOICES, + initial=ACTION_PREVIEW, + ) diff --git a/registrasion/templatetags/registrasion_tags.py b/registrasion/templatetags/registrasion_tags.py index 02cda54e..62315919 100644 --- a/registrasion/templatetags/registrasion_tags.py +++ b/registrasion/templatetags/registrasion_tags.py @@ -95,6 +95,17 @@ def items_purchased(context, category=None): ) +@register.assignment_tag(takes_context=True) +def total_items_purchased(context, category=None): + ''' Returns the number of items purchased for this user (sum of quantities). + + The user will be either `context.user`, and `context.request.user` if + the former is not defined. + ''' + + return sum(i.quantity for i in items_purchased(context, category)) + + @register.assignment_tag(takes_context=True) def report_as_csv(context, section): diff --git a/registrasion/urls.py b/registrasion/urls.py index 8f2e1663..91195864 100644 --- a/registrasion/urls.py +++ b/registrasion/urls.py @@ -5,6 +5,8 @@ from django.conf.urls import url from .views import ( amend_registration, + badge, + badges, checkout, credit_note, edit_profile, @@ -22,6 +24,8 @@ from .views import ( public = [ url(r"^amend/([0-9]+)$", amend_registration, name="amend_registration"), + url(r"^badge/([0-9]+)$", badge, name="badge"), + url(r"^badges$", badges, name="badges"), url(r"^category/([0-9]+)$", product_category, name="product_category"), url(r"^checkout$", checkout, name="checkout"), url(r"^checkout/([0-9]+)$", checkout, name="checkout"), diff --git a/registrasion/views.py b/registrasion/views.py index 24e5ebf1..40fde1c9 100644 --- a/registrasion/views.py +++ b/registrasion/views.py @@ -1,6 +1,7 @@ import datetime import sys import util +import zipfile from registrasion import forms from registrasion import util @@ -27,10 +28,10 @@ from django.contrib import messages from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ValidationError from django.core.mail import send_mass_mail -from django.http import Http404 +from django.http import Http404, HttpResponse from django.shortcuts import redirect from django.shortcuts import render -from django.template import Context, Template +from django.template import Context, Template, loader _GuidedRegistrationSection = namedtuple( @@ -968,3 +969,65 @@ def invoice_mailout(request): } return render(request, "registrasion/invoice_mailout.html", data) + + +@user_passes_test(_staff_only) +def badge(request, user_id): + ''' Renders a single user's badge (SVG). ''' + + user_id = int(user_id) + user = User.objects.get(pk=user_id) + + rendered = render_badge(user) + response = HttpResponse(rendered) + + response["Content-Type"] = "image/svg+xml" + response["Content-Disposition"] = 'inline; filename="badge.svg"' + return response + + +def badges(request): + ''' Either displays a form containing a list of users with badges to + render, or returns a .zip file containing their badges. ''' + + category = request.GET.getlist("category", []) + product = request.GET.getlist("product", []) + status = request.GET.get("status") + + form = forms.InvoicesWithProductAndStatusForm( + request.POST or None, + category=category, + product=product, + status=status, + ) + + if form.is_valid(): + response = HttpResponse() + response["Content-Type"] = "application.zip" + response["Content-Disposition"] = 'attachment; filename="badges.zip"' + + z = zipfile.ZipFile(response, "w") + + for invoice in form.cleaned_data["invoice"]: + user = invoice.user + badge = render_badge(user) + z.writestr("badge_%d.svg" % user.id, badge.encode("utf-8")) + + return response + + data = { + "form": form, + } + + return render(request, "registrasion/badges.html", data) + + +def render_badge(user): + ''' Renders a single user's badge. ''' + + data = { + "user": user, + } + + t = loader.get_template('registrasion/badge.svg') + return t.render(data)