Fundraising in PDF.
[wolnelektury.git] / src / club / views.py
1 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
3 #
4 from django.conf import settings
5 from django.contrib.auth.decorators import login_required, permission_required
6 from django.db.models import Sum
7 from django.http import HttpResponseRedirect
8 from django.shortcuts import get_object_or_404, render
9 from django.urls import reverse
10 from django.utils.decorators import method_decorator
11 from django.views.decorators.cache import never_cache
12 from django.views.generic import FormView, CreateView, TemplateView, DetailView, UpdateView
13 from django.views import View
14 from .payu import POSS
15 from .payu import views as payu_views
16 from .forms import PayUCardTokenForm
17 from . import forms
18 from . import models
19 from .helpers import get_active_schedule
20 from .payment_methods import recurring_payment_method
21
22
23 class ClubView(TemplateView):
24     template_name = 'club/index.html'
25
26     def get_context_data(self, *args, **kwargs):
27         ctx = super().get_context_data(*args, **kwargs)
28         ctx['active_menu_item'] = 'club'
29         return ctx
30
31
32
33 class DonationStep1(UpdateView):
34     queryset = models.Schedule.objects.filter(payed_at=None)
35     form_class = forms.DonationStep1Form
36     slug_field = slug_url_kwarg = 'key'
37     template_name = 'club/donation_step1.html'
38     step = 1
39
40     def get_context_data(self, **kwargs):
41         c = super().get_context_data(**kwargs)
42         c['club'] = models.Club.objects.first()
43         return c
44
45     def get_success_url(self):
46         return reverse('donation_step2', args=[self.object.key])
47
48
49 class DonationStep2(UpdateView):
50     queryset = models.Schedule.objects.filter(payed_at=None)
51     form_class = forms.DonationStep2Form
52     slug_field = slug_url_kwarg = 'key'
53     template_name = 'club/donation_step2.html'
54     step = 2
55
56     def get_context_data(self, **kwargs):
57         c = super().get_context_data(**kwargs)
58         c['club'] = models.Club.objects.first()
59         return c
60
61
62 class JoinView(CreateView):
63     form_class = forms.DonationStep1Form
64     template_name = 'club/donation_step1.html'
65
66     @property
67     def club(self):
68         return models.Club.objects.first()
69
70     def is_app(self):
71         return self.request.GET.get('app')
72
73     def get(self, request):
74         if settings.CLUB_APP_HOST and self.is_app() and request.META['HTTP_HOST'] != settings.CLUB_APP_HOST:
75             return HttpResponseRedirect("https://" + settings.CLUB_APP_HOST + request.get_full_path())
76
77         if self.is_app():
78             request.session['from_app'] = True
79         elif request.session and 'from_app' in request.session:
80             del request.session['from_app']
81
82         return super().get(request)
83
84     def get_context_data(self, **kwargs):
85         c = super(JoinView, self).get_context_data(**kwargs)
86         c['membership'] = getattr(self.request.user, 'membership', None)
87         c['active_menu_item'] = 'club'
88         c['club'] = models.Club.objects.first()
89
90         c['ambassador'] = models.Ambassador.objects.all().order_by('?').first()
91         return c
92
93     def get_initial(self):
94         # referer?
95         if self.request.user.is_authenticated and self.request.user.email:
96             return {
97                 'email': self.request.user.email
98             }
99
100     def get_form_kwargs(self):
101         kwargs = super().get_form_kwargs()
102         #kwargs['referer'] = self.request.META.get('HTTP_REFERER', '')
103         return kwargs
104
105     def form_valid(self, form):
106         retval = super(JoinView, self).form_valid(form)
107         if self.request.user.is_authenticated:
108             form.instance.membership, created = models.Membership.objects.get_or_create(user=self.request.user)
109             form.instance.save()
110         return retval
111
112     def get_success_url(self):
113         return reverse('donation_step2', args=[self.object.key])
114
115
116 @method_decorator(never_cache, name='dispatch')
117 class ScheduleView(DetailView):
118     queryset = models.Schedule.objects.exclude(email='')
119     slug_field = slug_url_kwarg = 'key'
120     template_name = 'club/schedule.html'
121     step = 3
122     
123     def get_template_names(self):
124         if not self.object.payed_at:
125             return 'club/donation_step3.html'
126         return 'club/schedule.html'
127         
128     def get_context_data(self, *args, **kwargs):
129         ctx = super().get_context_data(*args, **kwargs)
130         ctx['active_menu_item'] = 'club'
131         return ctx
132
133     def post(self, request, key):
134         schedule = self.get_object()
135         return HttpResponseRedirect(schedule.initiate_payment(request))
136
137
138 @login_required
139 def claim(request, key):
140     schedule = models.Schedule.objects.get(key=key, membership=None)
141     schedule.membership, created = models.Membership.objects.get_or_create(user=request.user)
142     schedule.save()
143     return HttpResponseRedirect(schedule.get_absolute_url())
144
145
146 def cancel(request, key):
147     schedule = models.Schedule.objects.get(key=key)
148     schedule.is_cancelled = True
149     schedule.save()
150     return HttpResponseRedirect(schedule.get_absolute_url())
151
152
153 class PayUPayment(DetailView):
154     model = models.Schedule
155     slug_field = slug_url_kwarg = 'key'
156
157     def get(self, request, key):
158         schedule = self.get_object()
159         schedule.method = 'payu'
160         schedule.save(update_fields=['method'])
161         return HttpResponseRedirect(schedule.initiate_payment(request))
162
163
164
165 class PayURecPayment(payu_views.RecPayment):
166     form_class = PayUCardTokenForm
167
168     def get_schedule(self):
169         return get_object_or_404(models.Schedule, key=self.kwargs['key'])
170
171     def get_pos(self):
172         pos_id = recurring_payment_method.pos_id
173         return POSS[pos_id]
174
175     def get_success_url(self):
176         schedule = self.get_schedule()
177         schedule.method = 'payu-re'
178         schedule.save(update_fields=['method'])
179         return schedule.pay(self.request)
180
181
182 class PayUNotifyView(payu_views.NotifyView):
183     order_model = models.PayUOrder
184
185
186 class ScheduleThanksView(DetailView):
187     model = models.Schedule
188     template_name = 'club/donation_step4.html'
189     slug_field = slug_url_kwarg = 'key'
190     step = 4
191
192     def get_context_data(self, *args, **kwargs):
193         ctx = super().get_context_data(*args, **kwargs)
194         ctx['active_menu_item'] = 'club'
195         return ctx
196
197
198 class YearSummaryView(DetailView):
199     model = models.Schedule
200     slug_field = slug_url_kwarg = 'key'
201     template_name = 'club/year_summary.html'
202
203     def get_context_data(self, *args, **kwargs):
204         ctx = super().get_context_data(*args, **kwargs)
205         ctx['payments'] = models.PayUOrder.objects.filter(
206             status='COMPLETED',
207             completed_at__year=self.kwargs['year'],
208             schedule__email=self.object.email,
209         ).order_by('completed_at')
210         ctx['total_amount'] = ctx['payments'].aggregate(s=Sum('schedule__amount'))['s']
211         return ctx
212
213
214 @permission_required('club.schedule_view')
215 def member_verify(request):
216     if request.method == 'POST':
217         emails = request.POST.get('emails').strip().split('\n')
218         rows = ['email;członek;nazwa użytkownika;aktywny;co najmniej do']
219         for email in emails:
220             email = email.strip()
221             row = [email]
222             schedules = models.Schedule.objects.filter(email=email).exclude(payed_at=None)
223             if schedules.exists():
224                 row.append('tak')
225                 akt = False
226                 unames = set()
227                 exp = None
228                 for s in schedules:
229                     if s.is_active():
230                         akt = True
231                     if s.membership:
232                         unames.add(s.membership.user.username) 
233                     if exp is None or s.expires_at > exp:
234                         exp = s.expires_at
235                 row.append(','.join(sorted(unames)))
236                 row.append('tak' if akt else 'nie')
237                 row.append(exp.date().isoformat())
238             else:
239                 row.append('nie')
240             rows.append(';'.join(row))
241         rows = '\n'.join(rows)
242     else:
243         rows = ''
244
245     return render(
246         request,
247         'club/member_verify.html',
248         {
249             'result': rows
250         }
251     )