source: remit/vouchers/views.py @ 6054f18

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

Limit DB->LaTeX to appropriate users

  • Property mode set to 100644
File size: 9.4 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
213@user_passes_test(lambda u: u.has_perm('vouchers.generate_vouchers'))
214def generate_vouchers(http_request, *args):
215    unprocessed = True
216    if 'unprocessed' in http_request.REQUEST:
217        if http_request.REQUEST['unprocessed'].upper() == 'TRUE':
218            unprocessed = True
219        else:
220            unprocessed = False
221    mark = True
222    if 'mark' in http_request.REQUEST:
223        if http_request.REQUEST['mark'].upper() == 'TRUE':
224            mark = True
225        else:
226            mark = False
227
228    lst = vouchers.models.Voucher.objects.all()
229    if unprocessed:
230        lst = lst.filter(processed=False)
231
232    context = {'vouchers': lst }
233    response = render_to_response('vouchers/vouchers.tex', context, context_instance=RequestContext(http_request), )
234
235    # Send mail
236    tmpl = get_template('vouchers/vouchers_tex_email.txt')
237    ctx = Context({
238        'converter': http_request.user,
239        'vouchers': lst,
240        'mark': mark,
241        'unprocessed': unprocessed,
242    })
243    body = tmpl.render(ctx)
244    mail_admins(
245        'Voucher rendering: %d by %s' % (
246            len(lst),
247            http_request.user,
248        ),
249        body,
250    )
251
252    if mark:
253        for voucher in lst:
254            voucher.processed = True
255            voucher.save()
256
257    return response
Note: See TracBrowser for help on using the repository browser.