tickets: Generalize the confirm_booking function.
[matthijs/projects/dorestad-bookings.git] / tickets / views.py
1 # Create your views here.
2
3 import datetime
4
5 import django
6 from django.shortcuts import render_to_response
7 from django.template import RequestContext
8
9 from models import Booking
10
11 class BookingForm(django.forms.ModelForm):
12     class Meta:
13         model=Booking
14         exclude=['payment']
15
16 def confirm_booking(booking, template):
17     from django.core.mail import EmailMessage
18
19     context = {'booking' : booking}
20
21     rendered = django.template.loader.render_to_string(template, context)
22     (headers, body) = rendered.strip().split('\n\n', 1)
23
24     # Turn the headers into a dict so EmailMessage can turn them into a
25     # string again. Bit pointless, but it works. 
26     # Perhaps we should just use python email stuff directly. OTOH, we
27     # still always need to parse for the From header.
28
29     headers_dict = {}
30     # If no From header is present, let EmailMessage do the default
31     # thing
32     from_email = None
33     for header in headers.split('\n'):
34         (field, value) = header.split(':')
35         if (field == 'From'):
36             from_email = value
37         elif (field == 'Subject'):
38             subject = value
39         else:
40             # Don't put From and Subject in the dict, else they'll be
41             # present twice.
42             headers_dict[field] = value
43
44     msg = EmailMessage(
45         # Only setting the From address through headers won't set the
46         # envelope address right.
47         from_email = from_email,
48         subject    = subject,
49         body       = body,
50         to         = [booking.email],
51         headers    = headers_dict
52     )
53     msg.send()
54
55 def book(request):
56     if request.method == "POST":
57         f = BookingForm(request.POST)
58     else:
59         f = BookingForm()
60
61     if f.is_valid():
62         booking = f.save()
63         confirm_booking(booking, 'tickets/booked.eml')
64         return render_to_response('tickets/booked.html', {'booking' : booking}, context_instance=RequestContext(request))
65
66     return render_to_response('tickets/bookingform.html', {'form' : f}, context_instance=RequestContext(request))
67
68 # These two forms are used for entering payment details. They aren't
69 # very different, so it should really be possible to merge them (but
70 # initial attempts to add the confirm field dynamically or setting its
71 # value dynamically, didn't work out all too well, so leave it at this
72 # for now).
73 class PaymentForm(django.forms.Form):
74     bookings = django.forms.models.ModelMultipleChoiceField(
75         queryset=Booking.objects.filter(payment__isnull=True).order_by('pk'),
76         widget=django.forms.CheckboxSelectMultiple,
77         label="Reserveringen")
78
79 class PaymentConfirmForm(django.forms.Form):
80     bookings = django.forms.models.ModelMultipleChoiceField(
81         queryset=Booking.objects.filter(payment__isnull=True).order_by('pk'),
82         widget=django.forms.MultipleHiddenInput,
83         label="Reserveringen")
84     # This field is used to distinguish these two forms
85     confirm = django.forms.BooleanField(initial=True, widget=django.forms.HiddenInput)
86
87 def payments(request):
88     c = {}
89     bookings = None
90     if request.method != "POST":
91         # First step: Just show an empty form
92         f = PaymentForm()
93     elif not 'confirm' in request.POST:
94         # Second step: Process form and show a summary for confirmation
95         f = PaymentForm(request.POST)
96         if f.is_valid():
97             bookings = f.cleaned_data['bookings']
98             # Output a confirmation form
99             f = PaymentConfirmForm()
100             f.initial['bookings'] = bookings
101             c['confirm'] = True
102     else:
103         # Third step: Summary was confirmed, do the work
104         f = PaymentConfirmForm(request.POST)
105         if f.is_valid():
106             bookings = f.cleaned_data['bookings']
107
108             # Do the work
109             for b in bookings:
110                 b.payment = datetime.datetime.now()
111                 b.save()
112
113             # Don't show the form again
114             f = None
115             c['confirmed'] = True
116
117     # Add the form to show
118     c['form'] = f
119
120     # Add some data about the selected bookings
121     if bookings:
122         c['bookings'] = bookings
123         c['numtickets'] = sum([b.tickets for b in bookings])
124         c['amount'] = sum([b.price for b in bookings])
125
126     return render_to_response('tickets/payments.html', c, context_instance=RequestContext(request))