source: remit/vouchers/views.py @ 13e7c01

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

Pull defaults from user object not certificate

In order to make Remit work better on a Django
test server or possibly with non-MIT group
members, pull data like name and email from the
user object instead of certificate, since as
of Trac #7 getting resolved we have that data.

Closes #11

  • Property mode set to 100644
File size: 10.8 KB
RevLine 
[269db50]1import vouchers.models
[6b8d891]2from vouchers.models import ReimbursementRequest
[3e79308]3from finance_core.models import BudgetTerm, BudgetArea
[269db50]4
[6b8d891]5from django.contrib.auth.decorators import user_passes_test
6from django.shortcuts import render_to_response, get_object_or_404
[fedcbcf]7from django.template import RequestContext
[6b8d891]8from django.http import Http404, HttpResponseRedirect
[587bb95]9import django.forms
[70ce03a]10from django.forms import Form
[6b8d891]11from django.forms import ModelForm
12from django.forms import ModelChoiceField
13from django.core.urlresolvers import reverse
[0e58ad0]14from django.core.mail import send_mail, mail_admins
[a9d44e0]15from django.template import Context, Template
16from django.template.loader import get_template
[269db50]17
[587bb95]18import settings
19
[6b8d891]20class RequestForm(ModelForm):
21    class Meta:
22        model = ReimbursementRequest
23        fields = (
24            'name',
25            'description',
26            'amount',
27            'budget_area',
[f6c7295]28            'expense_area',
[248b30b]29            'check_to_first_name',
30            'check_to_last_name',
[6b8d891]31            'check_to_email',
32            'check_to_addr',
33        )
34
[70ce03a]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):
[17193ee]51    area = CommitteesField()
[70ce03a]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,
[3a0c51b]67        'pagename':'request_reimbursement',
[70ce03a]68    }
[fedcbcf]69    return render_to_response('vouchers/select.html', context, context_instance=RequestContext(http_request), )
[70ce03a]70
71class CommitteeBudgetAreasField(ModelChoiceField):
[6b8d891]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
[f6c7295]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
[6b8d891]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
[37c15c4]103    # Prefill from user information (itself prefilled from LDAP now)
[e2f2aa9]104    initial = {}
[37c15c4]105    initial['check_to_first_name'] = http_request.user.first_name
106    initial['check_to_last_name']  = http_request.user.last_name
107    initial['check_to_email']      = http_request.user.email
[e2f2aa9]108
[6b8d891]109    if http_request.method == 'POST': # If the form has been submitted...
110        form = RequestForm(http_request.POST, instance=new_request) # A form bound to the POST data
[70ce03a]111        form.fields['budget_area'] = CommitteeBudgetAreasField(comm_obj)
[f6c7295]112        form.fields['expense_area'] = ExpenseAreasField()
[6b8d891]113        if form.is_valid(): # All validation rules pass
[0e58ad0]114            request_obj = form.save()
115
116            # Send email
[3bf063c]117            tmpl = get_template('vouchers/emails/request_submit_admin.txt')
[0e58ad0]118            ctx = Context({
119                'submitter': http_request.user,
120                'request': request_obj,
121            })
122            body = tmpl.render(ctx)
123            recipients = []
124            for name, addr in settings.ADMINS:
125                recipients.append(addr)
126            recipients.append(request_obj.budget_area.owner_address())
127            send_mail(
[14adb6b]128                '%sRequest submittal: %s requested $%s' % (
129                    settings.EMAIL_SUBJECT_PREFIX,
[0e58ad0]130                    http_request.user,
131                    request_obj.amount,
132                ),
133                body,
134                settings.SERVER_EMAIL,
135                recipients,
136            )
137
[856aac8]138            return HttpResponseRedirect(reverse(review_request, args=[new_request.pk],) + '?new=true') # Redirect after POST
[6b8d891]139    else:
[e2f2aa9]140        form = RequestForm(instance=new_request, initial=initial, ) # An unbound form
[70ce03a]141        form.fields['budget_area'] = CommitteeBudgetAreasField(comm_obj)
[f6c7295]142        form.fields['expense_area'] = ExpenseAreasField()
[269db50]143
144    context = {
145        'term':term_obj,
146        'comm':comm_obj,
[6b8d891]147        'form':form,
[3a0c51b]148        'pagename':'request_reimbursement',
[269db50]149    }
[fedcbcf]150    return render_to_response('vouchers/submit.html', context, context_instance=RequestContext(http_request), )
[6b8d891]151
[587bb95]152class VoucherizeForm(Form):
[e601d3b]153    name = django.forms.CharField(max_length=100, help_text='Signatory name for voucher',)
154    email = django.forms.EmailField(max_length=100, help_text='Signatory email for voucher')
[587bb95]155
156
[6b8d891]157@user_passes_test(lambda u: u.is_authenticated())
158def review_request(http_request, object_id):
159    request_obj = get_object_or_404(ReimbursementRequest, pk=object_id)
[856aac8]160    new = False
161    if 'new' in http_request.REQUEST:
162        if http_request.REQUEST['new'].upper() == 'TRUE':
163            new = True
164        else:
165            new = False
[587bb95]166
[e8550be]167    show_email = http_request.user.has_perm('vouchers.can_email')
168    if show_email:
169        email_message = ''
170        if http_request.method == 'POST' and 'send_email' in http_request.REQUEST:
171            mail = vouchers.models.stock_emails[http_request.REQUEST['email_name']]
172            assert mail.context == 'request'
173            mail.send_email_request(request_obj)
174            email_message = 'Sent email "%s".' % (mail.label, )
175        email_options = []
176        for mail in vouchers.models.stock_emails.values():
177            if mail.context == 'request':
178                email_options.append({
179                    'label': mail.label,
180                    'name' : mail.name,
181                })
182
[3e79308]183    show_approve = (http_request.user.has_perm('vouchers.can_approve')
184        and request_obj.approval_status == vouchers.models.APPROVAL_STATE_PENDING)
185    if show_approve:
[587bb95]186        # Voucherize form
187        # Prefill from certs / config
188        initial = {}
[37c15c4]189        initial['name'] = '%s %s' % (http_request.user.first_name, http_request.user.last_name, )
[587bb95]190        if settings.SIGNATORY_EMAIL:
191            initial['email'] = settings.SIGNATORY_EMAIL
192        else:
[37c15c4]193            initial['email'] = http_request.user.email
[587bb95]194
195        approve_message = ''
196        if http_request.method == 'POST' and 'approve' in http_request.REQUEST:
197            approve_form = VoucherizeForm(http_request.POST)
198            if approve_form.is_valid():
199                voucher = request_obj.convert(
200                    approve_form.cleaned_data['name'],
201                    signatory_email=approve_form.cleaned_data['email'],)
[3bf063c]202                tmpl = get_template('vouchers/emails/request_approval_admin.txt')
[a9d44e0]203                ctx = Context({
204                    'approver': http_request.user,
205                    'request': request_obj,
206                })
207                body = tmpl.render(ctx)
208                mail_admins(
209                    'Request approval: %s approved $%s' % (
210                        http_request.user,
211                        request_obj.amount,
212                    ),
213                    body,
214                )
[587bb95]215                approve_message = 'Created new voucher from request'
216        else:
217            approve_form = VoucherizeForm(initial=initial)
218
219    # Display the content
[6b8d891]220    if not (http_request.user.has_perm('vouchers.view_requests')
221        or http_request.user.username == request_obj.submitter):
222        # I'd probably use a 403, but that requires like writing
223        # a new template and stuff
224        # So I'm going to call this "don't leak information"
225        # and let it be
226        raise Http404
227    context = {
228        'rr':request_obj,
[3a0c51b]229        'pagename':'request_reimbursement',
[856aac8]230        'new': new,
[6b8d891]231    }
[3e79308]232    if show_approve:
[587bb95]233        context['approve_form'] = approve_form
234        context['approve_message'] = approve_message
[e8550be]235    if show_email:
236        context['email_options'] = email_options
237        context['email_message'] = email_message
[fedcbcf]238    return render_to_response('vouchers/ReimbursementRequest_review.html', context, context_instance=RequestContext(http_request), )
[6b8d891]239
[6054f18]240@user_passes_test(lambda u: u.has_perm('vouchers.generate_vouchers'))
[dcaa9c0]241def generate_vouchers(http_request, *args):
242    unprocessed = True
243    if 'unprocessed' in http_request.REQUEST:
244        if http_request.REQUEST['unprocessed'].upper() == 'TRUE':
245            unprocessed = True
246        else:
247            unprocessed = False
248    mark = True
249    if 'mark' in http_request.REQUEST:
250        if http_request.REQUEST['mark'].upper() == 'TRUE':
251            mark = True
252        else:
253            mark = False
254
255    lst = vouchers.models.Voucher.objects.all()
256    if unprocessed:
257        lst = lst.filter(processed=False)
258
259    context = {'vouchers': lst }
260    response = render_to_response('vouchers/vouchers.tex', context, context_instance=RequestContext(http_request), )
261
[524b81e]262    # Send mail
[3bf063c]263    tmpl = get_template('vouchers/emails/vouchers_tex.txt')
[524b81e]264    ctx = Context({
265        'converter': http_request.user,
266        'vouchers': lst,
267        'mark': mark,
268        'unprocessed': unprocessed,
269    })
270    body = tmpl.render(ctx)
271    mail_admins(
272        'Voucher rendering: %d by %s' % (
273            len(lst),
274            http_request.user,
275        ),
276        body,
277    )
278
[dcaa9c0]279    if mark:
280        for voucher in lst:
281            voucher.processed = True
282            voucher.save()
283
284    return response
Note: See TracBrowser for help on using the repository browser.