source: remit/vouchers/models.py @ ee82431

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

Use 30 character usernames to match Django

Originally, we limited submitter to 10 characters, because it was populated
from MIT certificates, so it only needed to be long enough for an Athena
username. However, it is conceivable that somebody would want to authenticate
against something else, so instead use Django's limit for username length.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1from django.db import models
2import settings
3import finance_core
4from finance_core.models import BudgetArea, BudgetTerm
5
6import datetime
7
8APPROVAL_STATE_PENDING = 0
9APPROVAL_STATE_APPROVED = 1
10APPROVAL_STATE_REJECTED = -1
11APPROVAL_STATES = (
12    (APPROVAL_STATE_PENDING,  'Pending'),
13    (APPROVAL_STATE_APPROVED, 'Approved'),
14    (APPROVAL_STATE_REJECTED, 'Rejected'),
15)
16
17class ReimbursementRequest(models.Model):
18    submitter = models.CharField(max_length=30) # Username of submitter
19    check_to_first_name = models.CharField(max_length=50, verbose_name="check recipient's first name")
20    check_to_last_name = models.CharField(max_length=50, verbose_name="check recipient's last name")
21    check_to_email = models.EmailField(verbose_name="email address for check pickup")
22    check_to_addr = models.TextField(blank=True, verbose_name="address for check mailing", help_text="For most requests, this should be blank for pickup in SAO (W20-549)")
23    amount = models.DecimalField(max_digits=7, decimal_places=2, help_text='Do not include "$"')
24    budget_area = models.ForeignKey(BudgetArea, related_name='as_budget_area')
25    budget_term = models.ForeignKey(BudgetTerm)
26    expense_area = models.ForeignKey(BudgetArea, related_name='as_expense_area') # ~GL
27    request_time = models.DateTimeField(default=datetime.datetime.now)
28    approval_time = models.DateTimeField(blank=True, null=True,)
29    approval_status = models.IntegerField(default=0, choices=APPROVAL_STATES)
30    printing_time = models.DateTimeField(blank=True, null=True,)
31    name = models.CharField(max_length=50, verbose_name='short description', )
32    description = models.TextField(blank=True, verbose_name='long description', )
33    documentation = models.ForeignKey('Documentation', null=True, )
34
35    class Meta:
36        permissions = (
37            ('can_list', 'Can list requests',),
38            ('can_approve', 'Can approve requests',),
39            ('can_email', 'Can send mail about requests',),
40        )
41
42    def __unicode__(self, ):
43        return "%s: %s %s (%s) (by %s) for $%s" % (
44            self.name,
45            self.check_to_first_name,
46            self.check_to_last_name,
47            self.check_to_email,
48            self.submitter,
49            self.amount,
50        )
51
52    def convert(self, signatory, signatory_email=settings.SIGNATORY_EMAIL):
53        voucher = Voucher()
54        voucher.group_name = settings.GROUP_NAME
55        voucher.account = self.budget_area.get_account_number()
56        voucher.signatory = signatory
57        voucher.signatory_email = signatory_email
58        voucher.first_name = self.check_to_first_name
59        voucher.last_name = self.check_to_last_name
60        voucher.email_address = self.check_to_email
61        voucher.mailing_address = self.check_to_addr
62        voucher.amount = self.amount
63        voucher.description = self.label() + ': ' + self.name
64        voucher.gl = self.expense_area.get_account_number()
65        voucher.documentation = self.documentation
66        voucher.save()
67        finance_core.models.make_transfer(
68            self.name,
69            self.amount,
70            finance_core.models.LAYER_EXPENDITURE,
71            self.budget_term,
72            self.budget_area,
73            self.expense_area,
74            self.description,
75        )
76        self.approval_status = 1
77        self.approval_time = datetime.datetime.now()
78        self.save()
79
80    def label(self, ):
81        return settings.GROUP_ABBR + unicode(self.pk) + 'RR'
82
83class Voucher(models.Model):
84    group_name = models.CharField(max_length=10)
85    account = models.IntegerField()
86    signatory = models.CharField(max_length=50)
87    signatory_email = models.EmailField()
88    first_name = models.CharField(max_length=20)
89    last_name = models.CharField(max_length=20)
90    email_address = models.EmailField(max_length=50)
91    mailing_address = models.TextField(blank=True, )
92    amount = models.DecimalField(max_digits=7, decimal_places=2,)
93    description = models.TextField()
94    gl = models.IntegerField()
95    processed = models.BooleanField()
96    documentation = models.ForeignKey('Documentation', blank=True, null=True, )
97
98    def mailing_addr_lines(self):
99        import re
100        if self.mailing_address:
101            lst = re.split(re.compile('[\n\r]*'), self.mailing_address)
102            lst = filter(lambda elem: len(elem)>0, lst)
103        else:
104            lst = []
105        lst = lst + ['']*(3-len(lst))
106        return lst
107
108    def __unicode__(self, ):
109        return "%s: %s %s (%s) for $%s" % (
110            self.description,
111            self.first_name,
112            self.last_name,
113            self.email_address,
114            self.amount,
115        )
116
117    class Meta:
118        permissions = (
119            ('generate_vouchers', 'Can generate vouchers',),
120        )
121
122
123class Documentation(models.Model):
124    backing_file = models.FileField(upload_to='documentation', verbose_name='File', help_text='PDF files only', )
125    label = models.CharField(max_length=50, default="")
126    submitter = models.CharField(max_length=30, null=True, ) # Username of submitter
127    upload_time = models.DateTimeField(default=datetime.datetime.now)
128
129    def __unicode__(self, ):
130        return "%s; uploaded at %s" % (self.label, self.upload_time, )
131
132
133class StockEmail:
134    def __init__(self, name, label, recipients, template, subject_template, context, ):
135        """
136        Initialize a stock email object.
137       
138        Each argument is required.
139       
140        name:       Short name. Letters, numbers, and hyphens only.
141        label:      User-readable label. Briefly describe what the email says
142        recipients: Who receives the email. List of "recipient" (check recipient), "area" (area owner), "admins" (site admins)
143        template:   Django template filename with the actual text
144        subject_template: Django template string with the subject
145        context:    Type of context the email needs. Must be 'request' currently.
146        """
147
148        self.name       = name
149        self.label      = label
150        self.recipients = recipients
151        self.template   = template
152        self.subject_template = subject_template
153        self.context    = context
154
155    def send_email_request(self, request,):
156        """
157        Send an email that requires context "request".
158        """
159
160        assert self.context == 'request'
161
162        # Generate text
163        from django.template import Context, Template
164        from django.template.loader import get_template
165        ctx = Context({
166            'prefix': settings.EMAIL_SUBJECT_PREFIX,
167            'request': request,
168            'sender': settings.USER_EMAIL_SIGNATURE,
169        })
170        tmpl = get_template(self.template)
171        body = tmpl.render(ctx)
172        subject_tmpl = Template(self.subject_template)
173        subject = subject_tmpl.render(ctx)
174
175        # Generate recipients
176        recipients = []
177        for rt in self.recipients:
178            if rt == 'recipient':
179                recipients.append(request.check_to_email)
180            elif rt == 'area':
181                recipients.append(request.budget_area.owner_address())
182            elif rt == 'admins':
183                pass # you don't *actually* have a choice...
184        for name, addr in settings.ADMINS:
185            recipients.append(addr)
186
187        # Send mail!
188        from django.core.mail import send_mail
189        send_mail(
190            subject,
191            body,
192            settings.SERVER_EMAIL,
193            recipients,
194        )
195
196stock_emails = {
197    'nodoc': StockEmail(
198        name='nodoc',
199        label='No documentation',
200        recipients=['recipient', 'area',],
201        template='vouchers/emails/no_docs_user.txt',
202        subject_template='{{prefix}}Missing documentation for reimbursement',
203        context = 'request',
204    ),
205    'voucher-sao': StockEmail(
206        name='voucher-sao',
207        label='Voucher submitted to SAO',
208        recipients=['recipient', ],
209        template='vouchers/emails/voucher_sao_user.txt',
210        subject_template='{{prefix}}Reimbursement sent to SAO for processing',
211        context = 'request',
212    ),
213}
Note: See TracBrowser for help on using the repository browser.