X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=bluechips%2Fcontrollers%2Fspend.py;h=ddd0a3cd45947b3fbe9d3e466ebce6c6f33d8901;hb=14a694445c9ce5493d644002a42261b39591d228;hp=4e89b35b55c27ed6c0d79cff74609e991aa3d2ae;hpb=375bf23b86666583e923b02ec2546cad52f5662d;p=bluechips.git diff --git a/bluechips/controllers/spend.py b/bluechips/controllers/spend.py index 4e89b35..ddd0a3c 100644 --- a/bluechips/controllers/spend.py +++ b/bluechips/controllers/spend.py @@ -2,8 +2,11 @@ Handle expenditures """ +from __future__ import division import logging +import re +import string from decimal import Decimal, InvalidOperation from bluechips.lib.base import * @@ -13,6 +16,7 @@ from pylons.decorators import validate from pylons.decorators.secure import authenticate_form from pylons.controllers.util import abort +import formencode from formencode import validators, Schema from formencode.foreach import ForEach from formencode.variabledecode import NestedVariables @@ -22,12 +26,35 @@ from mailer import Message log = logging.getLogger(__name__) +class ExpenditureExpression(validators.FancyValidator): + goodChars = set('1234567890.+-/*() ') + + def _to_python(self, value, state): + if (not set(value) <= self.goodChars or + re.search(r'([\+\-\*\/])\1', value)): + raise formencode.Invalid("Expression contains illegal characters", value, state) + + if value == '': + return value, Decimal("0") + + try: + number = eval(value) + return value, Decimal(str(number)) + except: + raise formencode.Invalid("Not a valid mathematical expression", value, state) + +class TagValidator(validators.FancyValidator): + def _to_python(self, value,state): + try: + return set(map(string.strip, value.split(','))) + except: + raise formencode.Invalid("Unable to parse tags", value, state) class ShareSchema(Schema): "Validate individual user shares." allow_extra_fields = False user_id = validators.Int(not_empty=True) - amount = validators.Number(not_empty=True) + amount = ExpenditureExpression() def validate_state(value_dict, state, validator): @@ -42,7 +69,8 @@ class ExpenditureSchema(Schema): pre_validators = [NestedVariables()] spender_id = validators.Int(not_empty=True) amount = model.types.CurrencyValidator(not_empty=True) - description = validators.UnicodeString() + description = validators.UnicodeString(not_empty=True) + tags = TagValidator() date = validators.DateConverter() shares = ForEach(ShareSchema) chained_validators = [ValidateNotAllZero] @@ -53,7 +81,7 @@ class SpendController(BaseController): return self.edit() def edit(self, id=None): - c.users = meta.Session.query(model.User.id, model.User) + c.users = get_users() if id is None: c.title = 'Add a New Expenditure' c.expenditure = model.Expenditure() @@ -67,8 +95,10 @@ class SpendController(BaseController): user_id, user = user_row val = 0 if user.resident: - val = Decimal(100) / Decimal(num_residents) + val = Decimal(1) c.values['shares-%d.amount' % ii] = val + + c.values['tags'] = u"" else: c.title = 'Edit an Expenditure' c.expenditure = meta.Session.query(model.Expenditure).get(id) @@ -77,16 +107,12 @@ class SpendController(BaseController): c.values = {} for ii, user_row in enumerate(c.users): user_id, user = user_row - shares_by_user = dict(((sp.user, sp.share) for sp + shares_by_user = dict(((sp.user, sp.share_text) for sp in c.expenditure.splits)) - share = shares_by_user.get(user, 0) - if c.expenditure.amount == 0: - percent = 0 - else: - percent = (Decimal(100) * Decimal(int(share)) / - Decimal(int(c.expenditure.amount))).\ - quantize(Decimal("0.001")) - c.values['shares-%d.amount' % ii] = percent + share = shares_by_user.get(user, '') + c.values['shares-%d.amount' % ii] = share + + c.values['tags'] = ', '.join(c.expenditure.tags) return render('/spend/index.mako') @@ -108,15 +134,21 @@ class SpendController(BaseController): # Set the fields that were submitted shares = self.form_result.pop('shares') + tags = self.form_result.pop('tags') or set() update_sar(e, self.form_result) users = dict(meta.Session.query(model.User.id, model.User).all()) split_dict = {} + split_text_dict = {} for share_params in shares: user = users[share_params['user_id']] - split_dict[user] = Decimal(str(share_params['amount'])) - e.split(split_dict) - + amount_text, amount = share_params['amount'] or ('',Decimal('0')) + split_dict[user] = amount + split_text_dict[user] = amount_text + e.split(split_dict, split_text_dict) + e.tags.clear() + e.tags |= tags + meta.Session.commit() show = ("Expenditure of %s paid for by %s %s." %