source: remit/vouchers/views.py @ a9d44e0

client
Last change on this file since a9d44e0 was a9d44e0, checked in by Alex Dehnert <adehnert@…>, 15 years ago

Send emails when requests are approved

  • Property mode set to 100644
File size: 8.9 KB
Line 
1import vouchers.models
2from vouchers.models import ReimbursementRequest
3from finance_core.models import BudgetTerm, BudgetArea
4
5from django.contrib.auth.decorators import user_passes_test
6from django.shortcuts import render_to_response, get_object_or_404
7from django.template import RequestContext
8from django.http import Http404, HttpResponseRedirect
9import django.forms
10from django.forms import Form
11from django.forms import ModelForm
12from django.forms import ModelChoiceField
13from django.core.urlresolvers import reverse
14from django.core.mail import mail_admins
15from django.template import Context, Template
16from django.template.loader import get_template
17
18import settings
19
20class RequestForm(ModelForm):
21    class Meta:
22        model = ReimbursementRequest
23        fields = (
24            'name',
25            'description',
26            'amount',
27            'budget_area',
28            'expense_area',
29            'check_to_first_name',
30            'check_to_last_name',
31            'check_to_email',
32            'check_to_addr',
33        )
34
35class CommitteesField(ModelChoiceField):
36    def __init__(self, *args, **kargs):
37        base_area = BudgetArea.get_by_path(['Accounts', 'Assets', 'Budget', ])
38        self.strip_levels = base_area.depth
39        areas = (base_area.get_descendants()
40            .filter(depth__lte=base_area.depth+2)
41            .exclude(name='Holding')
42        )
43        ModelChoiceField.__init__(self, queryset=areas,
44            help_text='Select the appropriate committe or other budget area',
45            *args, **kargs)
46
47    def label_from_instance(self, obj,):
48        return obj.indented_name(strip_levels=self.strip_levels)
49
50class SelectRequestBasicsForm(Form):
51    area = CommitteesField()
52    term = ModelChoiceField(queryset = BudgetTerm.objects.all())
53
54@user_passes_test(lambda u: u.is_authenticated())
55def select_request_basics(http_request, ):
56    if http_request.method == 'POST': # If the form has been submitted...
57        form = SelectRequestBasicsForm(http_request.POST) # A form bound to the POST data
58        if form.is_valid(): # All validation rules pass
59            term = form.cleaned_data['term'].slug
60            area = form.cleaned_data['area'].id
61            return HttpResponseRedirect(reverse(submit_request, args=[term, area],)) # Redirect after POST
62    else:
63        form = SelectRequestBasicsForm() # An unbound form
64
65    context = {
66        'form':form,
67        'pagename':'request_reimbursement',
68    }
69    return render_to_response('vouchers/select.html', context, context_instance=RequestContext(http_request), )
70
71class CommitteeBudgetAreasField(ModelChoiceField):
72    def __init__(self, base_area, *args, **kargs):
73        self.strip_levels = base_area.depth
74        areas = base_area.get_descendants()
75        ModelChoiceField.__init__(self, queryset=areas,
76            help_text='In general, this should be a fully indented budget area, not one with children',
77            *args, **kargs)
78
79    def label_from_instance(self, obj,):
80        return obj.indented_name(strip_levels=self.strip_levels)
81
82class ExpenseAreasField(ModelChoiceField):
83    def __init__(self, *args, **kargs):
84        base_area = vouchers.models.BudgetArea.get_by_path(['Accounts', 'Expenses'])
85        self.strip_levels = base_area.depth
86        areas = base_area.get_descendants()
87        ModelChoiceField.__init__(self, queryset=areas,
88            help_text='In general, this should be a fully indented budget area, not one with children',
89            *args, **kargs)
90
91    def label_from_instance(self, obj,):
92        return obj.indented_name(strip_levels=self.strip_levels)
93
94@user_passes_test(lambda u: u.is_authenticated())
95def submit_request(http_request, term, committee):
96    term_obj = get_object_or_404(BudgetTerm, slug=term)
97    comm_obj = get_object_or_404(BudgetArea, pk=committee)
98
99    new_request = ReimbursementRequest()
100    new_request.submitter = http_request.user.username
101    new_request.budget_term = term_obj
102
103    # Prefill from certs
104    initial = {}
105    try:
106        name = http_request.META['SSL_CLIENT_S_DN_CN']
107        names = name.split(' ')
108        initial['check_to_first_name'] = names[0]
109        initial['check_to_last_name'] = names[-1]
110    except KeyError:
111        pass
112    try:
113        initial['check_to_email'] = http_request.META['SSL_CLIENT_S_DN_Email']
114    except KeyError:
115        pass
116
117    if http_request.method == 'POST': # If the form has been submitted...
118        form = RequestForm(http_request.POST, instance=new_request) # A form bound to the POST data
119        form.fields['budget_area'] = CommitteeBudgetAreasField(comm_obj)
120        form.fields['expense_area'] = ExpenseAreasField()
121        if form.is_valid(): # All validation rules pass
122            form.save()
123            return HttpResponseRedirect(reverse(review_request, args=[new_request.pk],) + '?new=true') # Redirect after POST
124    else:
125        form = RequestForm(instance=new_request, initial=initial, ) # An unbound form
126        form.fields['budget_area'] = CommitteeBudgetAreasField(comm_obj)
127        form.fields['expense_area'] = ExpenseAreasField()
128
129    context = {
130        'term':term_obj,
131        'comm':comm_obj,
132        'form':form,
133        'pagename':'request_reimbursement',
134    }
135    return render_to_response('vouchers/submit.html', context, context_instance=RequestContext(http_request), )
136
137class VoucherizeForm(Form):
138    name = django.forms.CharField(max_length=100, help_text='Signatory name for voucher',)
139    email = django.forms.EmailField(max_length=100, help_text='Signatory email for voucher')
140
141
142@user_passes_test(lambda u: u.is_authenticated())
143def review_request(http_request, object_id):
144    request_obj = get_object_or_404(ReimbursementRequest, pk=object_id)
145    new = False
146    if 'new' in http_request.REQUEST:
147        if http_request.REQUEST['new'].upper() == 'TRUE':
148            new = True
149        else:
150            new = False
151
152    show_approve = (http_request.user.has_perm('vouchers.can_approve')
153        and request_obj.approval_status == vouchers.models.APPROVAL_STATE_PENDING)
154    if show_approve:
155        # Voucherize form
156        # Prefill from certs / config
157        initial = {}
158        try:
159            name = http_request.META['SSL_CLIENT_S_DN_CN']
160            initial['name'] = name
161        except KeyError:
162            pass
163        if settings.SIGNATORY_EMAIL:
164            initial['email'] = settings.SIGNATORY_EMAIL
165        else:
166            try:
167                initial['email'] = http_request.META['SSL_CLIENT_S_DN_Email']
168            except KeyError:
169                pass
170
171        approve_message = ''
172        if http_request.method == 'POST' and 'approve' in http_request.REQUEST:
173            approve_form = VoucherizeForm(http_request.POST)
174            if approve_form.is_valid():
175                voucher = request_obj.convert(
176                    approve_form.cleaned_data['name'],
177                    signatory_email=approve_form.cleaned_data['email'],)
178                tmpl = get_template('vouchers/request_approval_email.txt')
179                ctx = Context({
180                    'approver': http_request.user,
181                    'request': request_obj,
182                })
183                body = tmpl.render(ctx)
184                mail_admins(
185                    'Request approval: %s approved $%s' % (
186                        http_request.user,
187                        request_obj.amount,
188                    ),
189                    body,
190                )
191                approve_message = 'Created new voucher from request'
192        else:
193            approve_form = VoucherizeForm(initial=initial)
194
195    # Display the content
196    if not (http_request.user.has_perm('vouchers.view_requests')
197        or http_request.user.username == request_obj.submitter):
198        # I'd probably use a 403, but that requires like writing
199        # a new template and stuff
200        # So I'm going to call this "don't leak information"
201        # and let it be
202        raise Http404
203    context = {
204        'rr':request_obj,
205        'pagename':'request_reimbursement',
206        'new': new,
207    }
208    if show_approve:
209        context['approve_form'] = approve_form
210        context['approve_message'] = approve_message
211    return render_to_response('vouchers/ReimbursementRequest_review.html', context, context_instance=RequestContext(http_request), )
212
213def generate_vouchers(http_request, *args):
214    unprocessed = True
215    if 'unprocessed' in http_request.REQUEST:
216        if http_request.REQUEST['unprocessed'].upper() == 'TRUE':
217            unprocessed = True
218        else:
219            unprocessed = False
220    mark = True
221    if 'mark' in http_request.REQUEST:
222        if http_request.REQUEST['mark'].upper() == 'TRUE':
223            mark = True
224        else:
225            mark = False
226
227    lst = vouchers.models.Voucher.objects.all()
228    if unprocessed:
229        lst = lst.filter(processed=False)
230
231    context = {'vouchers': lst }
232    response = render_to_response('vouchers/vouchers.tex', context, context_instance=RequestContext(http_request), )
233
234    if mark:
235        for voucher in lst:
236            voucher.processed = True
237            voucher.save()
238
239    return response
Note: See TracBrowser for help on using the repository browser.