]> asedeno.scripts.mit.edu Git - bluechips.git/blob - bluechips/controllers/spend.py
added email notifications. requires schema change to add email column to users table.
[bluechips.git] / bluechips / controllers / spend.py
1 """
2 Handle expenditures
3 """
4
5 import logging
6
7 from decimal import Decimal, InvalidOperation
8
9 from bluechips.lib.base import *
10
11 from pylons import request, app_globals as g
12 from pylons.decorators.rest import dispatch_on
13 from pylons.decorators import validate
14
15 from formencode import validators, Schema
16 from formencode.foreach import ForEach
17 from formencode.variabledecode import NestedVariables
18
19 from mailer import Message
20
21 log = logging.getLogger(__name__)
22
23
24 class ShareSchema(Schema):
25     "Validate individual user shares."
26     allow_extra_fields = False
27     user_id = validators.Int(not_empty=True)
28     amount = validators.Number(not_empty=True)
29
30
31 class ExpenditureSchema(Schema):
32     "Validate an expenditure."
33     allow_extra_fields = False
34     pre_validators = [NestedVariables()]
35     spender_id = validators.Int(not_empty=True)
36     amount = model.types.CurrencyValidator(not_empty=True)
37     description = validators.UnicodeString()
38     date = validators.DateConverter()
39     shares = ForEach(ShareSchema)
40     
41
42 class SpendController(BaseController):
43     def index(self):
44         return self.edit()
45     
46     def edit(self, id=None):
47         c.users = meta.Session.query(model.User.id, model.User)
48         if id is None:
49             c.title = 'Add a New Expenditure'
50             c.expenditure = model.Expenditure()
51             c.expenditure.spender_id = request.environ['user'].id
52
53             num_residents = meta.Session.query(model.User).\
54                     filter_by(resident=True).count()
55             # Pre-populate split percentages for an even split.
56             c.values = {}
57             for ii, user_row in enumerate(c.users):
58                 user_id, user = user_row
59                 if user.resident:
60                     val = Decimal(100) / Decimal(num_residents)
61                 else:
62                     val = 0
63                 c.values['shares-%d.amount' % ii] = val
64         else:
65             c.title = 'Edit an Expenditure'
66             c.expenditure = meta.Session.query(model.Expenditure).get(id)
67         return render('/spend/index.mako')
68
69     @validate(schema=ExpenditureSchema(), form='edit', variable_decode=True)
70     def update(self, id=None):
71         # Either create a new object, or, if we're editing, get the
72         # old one
73         if id is None:
74             e = model.Expenditure()
75             meta.Session.add(e)
76             op = 'created'
77         else:
78             e = meta.Session.query(model.Expenditure).get(id)
79             op = 'updated'
80         
81         # Set the fields that were submitted
82         shares = self.form_result.pop('shares')
83         update_sar(e, self.form_result)
84         if e.id is not None:
85             e.update_split()
86
87         users = dict(meta.Session.query(model.User.id, model.User).all())
88         split_dict = {}
89         for share_params in shares:
90             user = users[share_params['user_id']]
91             split_dict[user] = Decimal(share_params['amount'])
92         e.split(split_dict)
93         
94         meta.Session.commit()
95        
96         show = ("Expenditure of %s paid for by %s %s." %
97                 (e.amount, e.spender, op))
98         h.flash(show)
99
100         # Send email notification to involved users if they have an email set.
101         involved_users = set(sp.user for sp in e.splits if sp.share != 0)
102         involved_users.add(e.spender)
103         body = render('/emails/expenditure.txt',
104                       extra_vars={'expenditure': e,
105                                   'op': op})
106         g.handle_notification(involved_users, show, body)
107
108         return h.redirect_to('/')