Merge branch 'master' into funding
[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.generic import TemplateView, FormView, DetailView, ListView
12 import getpaid.backends.payu
13 from getpaid.models import Payment
14 from .forms import FundingForm
15 from .models import Offer, Spent, Funding
16
17
18 def mix(*streams):
19     substreams = []
20     for stream, read_date, tag in streams:
21         iterstream = iter(stream)
22         try:
23             item = next(iterstream)
24         except StopIteration:
25             pass
26         else:
27             substreams.append([read_date(item), item, iterstream, read_date, tag])
28     while substreams:
29         i, substream = max(enumerate(substreams), key=lambda x: x[1][0])
30         yield substream[4], substream[1]
31         try:
32             item = next(substream[2])
33         except StopIteration:
34             del substreams[i]
35         else:
36             substream[0:2] = [substream[3](item), item]
37
38
39 class WLFundView(TemplateView):
40     template_name = "funding/wlfund.html"
41
42     def get_context_data(self):
43         def add_total(total, it):
44             for tag, e in it:
45                 e.total = total
46                 if tag == 'spent':
47                     total += e.amount
48                 else:
49                     total -= e.wlfund
50                 yield tag, e
51
52         ctx = super(WLFundView, self).get_context_data()
53         offers = []
54         
55         for o in Offer.past():
56             if o.is_win():
57                 o.wlfund = o.sum() - o.target
58                 if o.wlfund > 0:
59                     offers.append(o)
60             else:
61                 o.wlfund = o.sum()
62                 if o.wlfund > 0:
63                     offers.append(o)
64         amount = sum(o.wlfund for o in offers) - sum(o.amount for o in Spent.objects.all())
65
66         ctx['amount'] = amount
67         ctx['log'] = add_total(amount, mix(
68             (offers, lambda x: x.end, 'offer'),
69             (Spent.objects.all().select_related(), lambda x: x.timestamp, 'spent'),
70         ))
71         return ctx
72
73
74 class OfferDetailView(FormView):
75     form_class = FundingForm
76     template_name = "funding/offer_detail.html"
77     backend = 'getpaid.backends.payu'
78
79     def dispatch(self, request, slug=None):
80         if getattr(self, 'object', None) is None:
81             if slug:
82                 self.object = get_object_or_404(Offer.public(), slug=slug)
83             else:
84                 self.object = Offer.current()
85                 if self.object is None:
86                     raise Http404
87         return super(OfferDetailView, self).dispatch(request, slug)
88
89     def get_form(self, form_class):
90         if self.request.method == 'POST':
91             return form_class(self.object, self.request.POST)
92         else:
93             return form_class(self.object, initial={'amount': settings.FUNDING_DEFAULT})
94
95     def get_context_data(self, *args, **kwargs):
96         ctx = super(OfferDetailView, self).get_context_data(*args, **kwargs)
97         ctx['object'] = self.object
98         if self.object.is_current():
99             ctx['funding_no_show_current'] = True
100         return ctx
101
102     def form_valid(self, form):
103         funding = form.save()
104         # Skip getpaid.forms.PaymentMethodForm, go directly to the broker.
105         payment = Payment.create(funding, self.backend)
106         gateway_url_tuple = payment.get_processor()(payment).get_gateway_url(self.request)
107         payment.change_status('in_progress')
108         return redirect(gateway_url_tuple[0])
109
110
111 class CurrentView(OfferDetailView):
112     def dispatch(self, request, slug=None):
113         self.object = Offer.current()
114         if self.object is None:
115             raise Http404
116         elif slug != self.object.slug:
117             return redirect(reverse('funding_current', args=[self.object.slug]))
118         return super(CurrentView, self).dispatch(request, slug)
119
120
121 class OfferListView(ListView):
122     queryset = Offer.public()
123
124     def get_context_data(self, *args, **kwargs):
125         ctx = super(OfferListView, self).get_context_data(*args, **kwargs)
126         ctx['funding_no_show_current'] = True
127         return ctx
128
129
130 class ThanksView(TemplateView):
131     template_name = "funding/thanks.html"
132
133     def get_context_data(self, *args, **kwargs):
134         ctx = super(ThanksView, self).get_context_data(*args, **kwargs)
135         ctx['offer'] = Offer.current()
136         ctx['funding_no_show_current'] = True
137         return ctx
138
139 class NoThanksView(TemplateView):
140     template_name = "funding/no_thanks.html"