approve.py 4.98 KB
Newer Older
1
2
3
4
5
6
7
"""
This file implements the door/committee/admin facing membership approval (and payment) interface
See ../../README.md for details
"""
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
frekk's avatar
frekk committed
8
9
from django.views.generic.edit import UpdateView
from django.utils import timezone
10
11
12
13
14
15
from django import forms

from memberdb.models import Member, Membership, MEMBERSHIP_TYPES_

def get_membership_type(member):
    best = None
frekk's avatar
frekk committed
16
    is_fresh = member.memberships.all().count() == 0
17
    for t in MEMBERSHIP_TYPES_:
frekk's avatar
frekk committed
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        if (t['must_be_fresh'] == is_fresh):
            best = t
            break
        elif (t['is_student'] == member.is_student and t['is_guild'] == member.is_guild):
            best = t
            break
    if (best is None):
        return MEMBERSHIP_TYPES_[0]['dispense']
    else:
        return best['dispense']

def make_pending_membership(member):
    ms = Membership(member=member, approved=False)
    ms.date_submitted = timezone.now()
    ms.membership_type = get_membership_type(member)
    return ms
34
35
36
37
38
39
40

"""
inline admin change list action buttons
see https://medium.com/@hakibenita/how-to-add-custom-action-buttons-to-django-admin-8d266f5b0d41
and have a look at .admin.MembershipAdmin
"""
class MembershipApprovalForm(forms.ModelForm):
frekk's avatar
frekk committed
41
    payment_confirm = forms.BooleanField(label='Confirm payment', required=False)
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    
    # this must be passed by kwargs upon instantiating the form
    request = None

    class Meta:
        model = Membership
        fields = ['membership_type', 'payment_method']
        widgets = {
            'membership_type': forms.RadioSelect(),
            'payment_method': forms.RadioSelect(),
        }

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super().__init__(*args, **kwargs)

    """
    Called to validate the data on the form.
    here we fill out some fields automatically (ie. approver, date paid / approved, etc.)
    TODO: deal with account activation/creation, etc.
    """
    def clean(self):
        # get the cleaned data from the form API and do something with it
        data = super().clean()
frekk's avatar
frekk committed
66
67
        now = timezone.now()
        #breakpoint()
68
        # find a Member matching our current username
frekk's avatar
frekk committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
        approver = Member.objects.filter(username__exact=self.request.user.username).first()
        if (approver == None):
            self.add_error(None, 'Cannot set approver: no Member record with username %s' % self.request.user.username)
        data['approver'] = approver
        data['approved'] = True
        data['date_approved'] = now

        if (data['payment_confirm'] == True):
            data['date_paid'] = now
        
        # make sure "no payment" is recorded for Life Members.
        # XXX this might not actually be the case, since some life members may want to also be financial members (ie. for constitutional voting rights)
        #     and so this is probably more annoying than helpful
        if (data['membership_type'] == ''):
            if (data['payment_method'] != ''):
                self.add_error('payment_method', 'Life members shall not pay membership fees!')
            data['payment_method'] = ''
86
87
88
89
90
91
92
93

        return data

    """
    do the stuff, approve the things
    """
    def save(self, commit=True):
        ms = super().save(commit=False)
frekk's avatar
frekk committed
94
95
96
97
98
99
100
101

        # copy attributes not specified in fields
        ms.approver = self.cleaned_data['approver']
        ms.approved = self.cleaned_data['approved']
        ms.date_approved = self.cleaned_data['date_approved']
        ms.date_paid = self.cleaned_data['date_paid']

        # do something
102
103
104
105
106
107
108
109
110
111
112
113
114
115
        if (commit):
            ms.save()
        return ms

class MembershipApprovalAdminView(UpdateView):
    template_name = 'admin/memberdb/membership_approve.html'
    form_class = MembershipApprovalForm
    model = Membership
    pk_url_kwarg = 'object_id'
    # override with the instance of ModelAdmin
    admin = None
    object = None

    def get_context_data(self, **kwargs):
frekk's avatar
frekk committed
116
        ms = self.get_object()
117
118
119
120
        context = super().get_context_data(**kwargs)
        context.update(self.admin.admin_site.each_context(self.request))
        context.update({
            'opts': self.admin.model._meta,
frekk's avatar
frekk committed
121
122
123
            'ms': ms,
            'member': ms.member,
            'show_member_summary': True,
124
125
126
127
128
129
130
131
132
133
134
135
        })
        return context

    def get_form_kwargs(self, **kwargs):
        kwargs.update(super().get_form_kwargs())
        kwargs.update({'request': self.request})
        return kwargs

    """
    called when the approval form is submitted and valid data (according to the form's field types and defined validators) is given
    """
    def form_valid(self, form):
frekk's avatar
frekk committed
136
        breakpoint()
137
138
139
140
141
142
143
144
145
146
147
        ms = form.save()
        
        self.admin.message_user(self.request, 'Approve success')
        url = reverse(
            'admin:memberdb_membership_change',
            args=[ms.pk],
            current_app=self.admin.admin_site.name,
        )
        return HttpResponseRedirect(url)