Status update emails.
[wolnelektury.git] / apps / funding / views.py
1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 #
5 from datetime import date
6 from django.views.decorators.cache import never_cache
7 from django.conf import settings
8 from django.core.urlresolvers import reverse
9 from django.http import Http404
10 from django.shortcuts import redirect, get_object_or_404
11 from django.views.decorators.csrf import csrf_exempt
12 from django.views.generic import TemplateView, FormView, DetailView, ListView
13 import getpaid.backends.payu
14 from getpaid.models import Payment
15 from .forms import FundingForm
16 from .models import Offer, Spent, Funding
17
18
19 def mix(*streams):
20     substreams = []
21     for stream, read_date, tag in streams:
22         iterstream = iter(stream)
23         try:
24             item = next(iterstream)
25         except StopIteration:
26             pass
27         else:
28             substreams.append([read_date(item), item, iterstream, read_date, tag])
29     while substreams:
30         i, substream = max(enumerate(substreams), key=lambda x: x[1][0])
31         yield substream[4], substream[1]
32         try:
33             item = next(substream[2])
34         except StopIteration:
35             del substreams[i]
36         else:
37             substream[0:2] = [substream[3](item), item]
38
39
40 class WLFundView(TemplateView):
41     template_name = "funding/wlfund.html"
42
43     def get_context_data(self):
44         def add_total(total, it):
45             for tag, e in it:
46                 e.total = total
47                 if tag == 'spent':
48                     total += e.amount
49                 else:
50                     total -= e.wlfund
51                 yield tag, e
52
53         ctx = super(WLFundView, self).get_context_data()
54         offers = []
55         
56         for o in Offer.past():
57             if o.is_win():
58                 o.wlfund = o.sum() - o.target
59                 if o.wlfund > 0:
60                     offers.append(o)
61             else:
62                 o.wlfund = o.sum()
63                 if o.wlfund > 0:
64                     offers.append(o)
65         amount = sum(o.wlfund for o in offers) - sum(o.amount for o in Spent.objects.all())
66
67         ctx['amount'] = amount
68         ctx['log'] = add_total(amount, mix(
69             (offers, lambda x: x.end, 'offer'),
70             (Spent.objects.all().select_related(), lambda x: x.timestamp, 'spent'),
71         ))
72         return ctx
73
74
75 class OfferDetailView(FormView):
76     form_class = FundingForm
77     template_name = "funding/offer_detail.html"
78     backend = 'getpaid.backends.payu'
79
80     @csrf_exempt
81     def dispatch(self, request, slug=None):
82         if getattr(self, 'object', None) is None:
83             if slug:
84                 self.object = get_object_or_404(Offer.public(), slug=slug)
85             else:
86                 self.object = Offer.current()
87                 if self.object is None:
88                     raise Http404
89         return super(OfferDetailView, self).dispatch(request, slug)
90
91     def get_form(self, form_class):
92         if self.request.method == 'POST':
93             return form_class(self.object, self.request.POST)
94         else:
95             return form_class(self.object, initial={'amount': settings.FUNDING_DEFAULT})
96
97     def get_context_data(self, *args, **kwargs):
98         ctx = super(OfferDetailView, self).get_context_data(*args, **kwargs)
99         ctx['object'] = self.object
100         if self.object.is_current():
101             ctx['funding_no_show_current'] = True
102         return ctx
103
104     def form_valid(self, form):
105         funding = form.save()
106         # Skip getpaid.forms.PaymentMethodForm, go directly to the broker.
107         payment = Payment.create(funding, self.backend)
108         gateway_url_tuple = payment.get_processor()(payment).get_gateway_url(self.request)
109         payment.change_status('in_progress')
110         return redirect(gateway_url_tuple[0])
111
112
113 class CurrentView(OfferDetailView):
114     @csrf_exempt
115     def dispatch(self, request, slug=None):
116         self.object = Offer.current()
117         if self.object is None:
118             raise Http404
119         elif slug != self.object.slug:
120             return redirect(reverse('funding_current', args=[self.object.slug]))
121         return super(CurrentView, self).dispatch(request, slug)
122
123
124 class OfferListView(ListView):
125     queryset = Offer.public()
126
127     def get_context_data(self, *args, **kwargs):
128         ctx = super(OfferListView, self).get_context_data(*args, **kwargs)
129         ctx['funding_no_show_current'] = True
130         return ctx
131
132
133 class ThanksView(TemplateView):
134     template_name = "funding/thanks.html"
135
136     def get_context_data(self, *args, **kwargs):
137         ctx = super(ThanksView, self).get_context_data(*args, **kwargs)
138         ctx['offer'] = Offer.current()
139         ctx['funding_no_show_current'] = True
140         return ctx
141
142
143 class NoThanksView(TemplateView):
144     template_name = "funding/no_thanks.html"
145
146
147 class DisableNotifications(TemplateView):
148     template_name = "funding/disable_notifications.html"
149
150     @csrf_exempt
151     def dispatch(self, request):
152         self.object = get_object_or_404(Funding, 
153             email=request.GET.get('email'), notify_key=request.GET.get('key'))
154         return super(DisableNotifications, self).dispatch(request)
155
156     def post(self, *args, **kwargs):
157         self.object.disable_notifications()
158         return redirect(self.request.get_full_path())