source: remit/vouchers/views.py @ 0e58ad0

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

Send email on submitted requests

  • Property mode set to 100644
File size: 10.1 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 send_mail, 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            request_obj = form.save()
123
124            # Send email
125            tmpl = get_template('vouchers/request_submit_email.txt')
126            ctx = Context({
127                'submitter': http_request.user,
128                'request': request_obj,
129            })
130            body = tmpl.render(ctx)
131            recipients = []
132            for name, addr in settings.ADMINS:
133                recipients.append(addr)
134            recipients.append(request_obj.budget_area.owner_address())
135            send_mail(
136                'Request submittal: %s requested $%s' % (
137                    http_request.user,
138                    request_obj.amount,
139                ),
140                body,
141                settings.SERVER_EMAIL,
142                recipients,
143            )
144
145            return HttpResponseRedirect(reverse(review_request, args=[new_request.pk],) + '?new=true') # Redirect after POST
146    else:
147        form = RequestForm(instance=new_request, initial=initial, ) # An unbound form
148        form.fields['budget_area'] = CommitteeBudgetAreasField(comm_obj)
149        form.fields['expense_area'] = ExpenseAreasField()
150
151    context = {
152        'term':term_obj,
153        'comm':comm_obj,
154        'form':form,
155        'pagename':'request_reimbursement',
156    }
157    return render_to_response('vouchers/submit.html', context, context_instance=RequestContext(http_request), )
158
159class VoucherizeForm(Form):
160    name = django.forms.CharField(max_length=100, help_text='Signatory name for voucher',)
161    email = django.forms.EmailField(max_length=100, help_text='Signatory email for voucher')
162
163
164@user_passes_test(lambda u: u.is_authenticated())
165def review_request(http_request, object_id):
166    request_obj = get_object_or_404(ReimbursementRequest, pk=object_id)
167    new = False
168    if 'new' in http_request.REQUEST:
169        if http_request.REQUEST['new'].upper() == 'TRUE':
170            new = True
171        else:
172            new = False
173
174    show_approve = (http_request.user.has_perm('vouchers.can_approve')
175        and request_obj.approval_status == vouchers.models.APPROVAL_STATE_PENDING)
176    if show_approve:
177        # Voucherize form
178        # Prefill from certs / config
179        initial = {}
180        try:
181            name = http_request.META['SSL_CLIENT_S_DN_CN']
182            initial['name'] = name
183        except KeyError:
184            pass
185        if settings.SIGNATORY_EMAIL:
186            initial['email'] = settings.SIGNATORY_EMAIL
187        else:
188            try:
189                initial['email'] = http_request.META['SSL_CLIENT_S_DN_Email']
190            except KeyError:
191                pass
192
193        approve_message = ''
194        if http_request.method == 'POST' and 'approve' in http_request.REQUEST:
195            approve_form = VoucherizeForm(http_request.POST)
196            if approve_form.is_valid():
197                voucher = request_obj.convert(
198                    approve_form.cleaned_data['name'],
199                    signatory_email=approve_form.cleaned_data['email'],)
200                tmpl = get_template('vouchers/request_approval_email.txt')
201                ctx = Context({
202                    'approver': http_request.user,
203                    'request': request_obj,
204                })
205                body = tmpl.render(ctx)
206                mail_admins(
207                    'Request approval: %s approved $%s' % (
208                        http_request.user,
209                        request_obj.amount,
210                    ),
211                    body,
212                )
213                approve_message = 'Created new voucher from request'
214        else:
215            approve_form = VoucherizeForm(initial=initial)
216
217    # Display the content
218    if not (http_request.user.has_perm('vouchers.view_requests')
219        or http_request.user.username == request_obj.submitter):
220        # I'd probably use a 403, but that requires like writing
221        # a new template and stuff
222        # So I'm going to call this "don't leak information"
223        # and let it be
224        raise Http404
225    context = {
226        'rr':request_obj,
227        'pagename':'request_reimbursement',
228        'new': new,
229    }
230    if show_approve:
231        context['approve_form'] = approve_form
232        context['approve_message'] = approve_message
233    return render_to_response('vouchers/ReimbursementRequest_review.html', context, context_instance=RequestContext(http_request), )
234
235@user_passes_test(lambda u: u.has_perm('vouchers.generate_vouchers'))
236def generate_vouchers(http_request, *args):
237    unprocessed = True
238    if 'unprocessed' in http_request.REQUEST:
239        if http_request.REQUEST['unprocessed'].upper() == 'TRUE':
240            unprocessed = True
241        else:
242            unprocessed = False
243    mark = True
244    if 'mark' in http_request.REQUEST:
245        if http_request.REQUEST['mark'].upper() == 'TRUE':
246            mark = True
247        else:
248            mark = False
249
250    lst = vouchers.models.Voucher.objects.all()
251    if unprocessed:
252        lst = lst.filter(processed=False)
253
254    context = {'vouchers': lst }
255    response = render_to_response('vouchers/vouchers.tex', context, context_instance=RequestContext(http_request), )
256
257    # Send mail
258    tmpl = get_template('vouchers/vouchers_tex_email.txt')
259    ctx = Context({
260        'converter': http_request.user,
261        'vouchers': lst,
262        'mark': mark,
263        'unprocessed': unprocessed,
264    })
265    body = tmpl.render(ctx)
266    mail_admins(
267        'Voucher rendering: %d by %s' % (
268            len(lst),
269            http_request.user,
270        ),
271        body,
272    )
273
274    if mark:
275        for voucher in lst:
276            voucher.processed = True
277            voucher.save()
278
279    return response
Note: See TracBrowser for help on using the repository browser.