source: remit/vouchers/models.py @ a5fc5c8

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

Increase length of group_name field to 40

A lot of groups have names that are more than 10 characters...

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