# Create your views here.
+
+import datetime
+
+import django
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.contrib.auth.decorators import permission_required
+
+from models import Booking, TICKET_PRICE, SHOW_CHOICES
+
+class BookingForm(django.forms.ModelForm):
+ class Meta:
+ model=Booking
+ exclude=['payment']
+
+def confirm_booking(booking, template):
+ from django.core.mail import EmailMessage
+
+ context = {'booking' : booking}
+
+ rendered = django.template.loader.render_to_string(template, context)
+ (headers, body) = rendered.strip().split('\n\n', 1)
+
+ # Turn the headers into a dict so EmailMessage can turn them into a
+ # string again. Bit pointless, but it works.
+ # Perhaps we should just use python email stuff directly. OTOH, we
+ # still always need to parse for the From header.
+
+ headers_dict = {}
+ # If no From header is present, let EmailMessage do the default
+ # thing
+ from_email = None
+ for header in headers.split('\n'):
+ (field, value) = header.split(':')
+ if (field == 'From'):
+ from_email = value
+ elif (field == 'Subject'):
+ subject = value
+ else:
+ # Don't put From and Subject in the dict, else they'll be
+ # present twice.
+ headers_dict[field] = value
+
+ msg = EmailMessage(
+ # Only setting the From address through headers won't set the
+ # envelope address right.
+ from_email = from_email,
+ subject = subject,
+ body = body,
+ to = [booking.email],
+ headers = headers_dict
+ )
+ msg.send()
+
+def book(request):
+ if request.method == "POST":
+ f = BookingForm(request.POST)
+ else:
+ f = BookingForm()
+
+ if f.is_valid():
+ booking = f.save()
+ confirm_booking(booking, 'tickets/booked.eml')
+ return render_to_response('tickets/booked.html', {'booking' : booking}, context_instance=RequestContext(request))
+
+ return render_to_response('tickets/bookingform.html', {'form' : f, 'price' : TICKET_PRICE}, context_instance=RequestContext(request))
+
+# These two forms are used for entering payment details. They aren't
+# very different, so it should really be possible to merge them (but
+# initial attempts to add the confirm field dynamically or setting its
+# value dynamically, didn't work out all too well, so leave it at this
+# for now).
+class PaymentForm(django.forms.Form):
+ bookings = django.forms.models.ModelMultipleChoiceField(
+ queryset=Booking.objects.filter(payment__isnull=True).order_by('pk'),
+ widget=django.forms.CheckboxSelectMultiple,
+ label="Reserveringen")
+
+class PaymentConfirmForm(django.forms.Form):
+ bookings = django.forms.models.ModelMultipleChoiceField(
+ queryset=Booking.objects.filter(payment__isnull=True).order_by('pk'),
+ widget=django.forms.MultipleHiddenInput,
+ label="Reserveringen")
+ # This field is used to distinguish these two forms
+ confirm = django.forms.BooleanField(initial=True, widget=django.forms.HiddenInput)
+
+@permission_required('tickets.change_booking')
+def payments(request):
+ c = {}
+ bookings = None
+ if request.method != "POST":
+ # First step: Just show an empty form
+ f = PaymentForm()
+ elif not 'confirm' in request.POST:
+ # Second step: Process form and show a summary for confirmation
+ f = PaymentForm(request.POST)
+ if f.is_valid():
+ bookings = f.cleaned_data['bookings']
+ # Output a confirmation form
+ f = PaymentConfirmForm()
+ f.initial['bookings'] = bookings
+ c['confirm'] = True
+ else:
+ # Third step: Summary was confirmed, do the work
+ f = PaymentConfirmForm(request.POST)
+ if f.is_valid():
+ bookings = f.cleaned_data['bookings']
+
+ # Do the work
+ for b in bookings:
+ b.payment = datetime.datetime.now()
+ b.save()
+ confirm_booking(b, 'tickets/payed.eml')
+
+ # Don't show the form again
+ f = None
+ c['confirmed'] = True
+
+ # Add the form to show
+ c['form'] = f
+
+ # Add some data about the selected bookings
+ if bookings:
+ c['bookings'] = bookings
+ c['numtickets'] = sum([b.tickets for b in bookings])
+ c['amount'] = sum([b.price for b in bookings])
+
+ return render_to_response('tickets/payments.html', c, context_instance=RequestContext(request))
+
+@permission_required('tickets.change_booking')
+def bookings(request):
+ shows = []
+ for (show, show_desc) in SHOW_CHOICES:
+ bookings = Booking.objects.filter(show=show)
+ # shows is a list of (show_desc, infodict) tuples
+ shows.append((show_desc, {
+ 'bookings' : bookings,
+ 'tickets' : sum([b.tickets for b in bookings]),
+ 'payed' : sum([b.tickets for b in bookings if b.payment is not None]),
+ }))
+
+ c = { 'shows' : shows }
+ return render_to_response('tickets/bookings.html', c, context_instance=RequestContext(request))