import logging
import re
+import string
from decimal import Decimal, InvalidOperation
from bluechips.lib.base import *
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."
spender_id = validators.Int(not_empty=True)
amount = model.types.CurrencyValidator(not_empty=True)
description = validators.UnicodeString(not_empty=True)
+ tags = TagValidator()
date = validators.DateConverter()
shares = ForEach(ShareSchema)
chained_validators = [ValidateNotAllZero]
if user.resident:
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)
share = shares_by_user.get(user, '')
c.values['shares-%d.amount' % ii] = share
+ c.values['tags'] = ', '.join([tag.tag for tag in c.expenditure.tags])
+
return render('/spend/index.mako')
@redirect_on_get('edit')
# 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[user] = amount
split_text_dict[user] = amount_text
e.split(split_dict, split_text_dict)
-
+ e.tag(tags)
+
meta.Session.commit()
show = ("Expenditure of %s paid for by %s %s." %
from bluechips.model.split import Split
from bluechips.model.subitem import Subitem
from bluechips.model.transfer import Transfer
+from bluechips.model.tag import Tag
from bluechips.model import meta
from bluechips.model import types
sa.Column('share', types.DBCurrency, nullable=False)
)
+tags = sa.Table('tags', meta.metadata,
+ sa.Column('id', sa.types.Integer, primary_key=True),
+ sa.Column('expenditure_id', sa.types.Integer,
+ sa.ForeignKey('expenditures.id'), nullable=False),
+ sa.Column('tag', sa.Text, nullable=False))
+
+
subitems = sa.Table('subitems', meta.metadata,
sa.Column('id', sa.types.Integer, primary_key=True),
sa.Column('expenditure_id', sa.types.Integer,
properties={
'splits': orm.relation(Split, backref='expenditure',
cascade='all, delete'),
+ 'tags': orm.relation(Tag, backref='expenditure',
+ cascade='all, delete'),
'subitems': orm.relation(Subitem, backref='expenditure',
cascade='all, delete')
})
'user': orm.relation(User)
})
+orm.mapper(Tag, tags)
+
orm.mapper(Subitem, subitems, properties={
'user': orm.relation(User)
})
users.c.id))
})
-__all__ = ['users', 'expenditures', 'splits', 'subitems', 'transfers',
- 'User', 'Expenditure', 'Split', 'Subitem', 'Transfer',
+__all__ = ['users', 'expenditures', 'splits', 'tags', 'subitems', 'transfers',
+ 'User', 'Expenditure', 'Split', 'Tag', 'Subitem', 'Transfer',
'meta']
from bluechips.model.split import Split
from bluechips.model import meta
from bluechips.model.types import Currency
+from bluechips.model.tag import Tag
from decimal import Decimal
from datetime import datetime
import random
s = Split(self, user, share, split_text_dict[user])
meta.Session.add(s)
+ def tag(self, tags):
+ map(meta.Session.delete,
+ meta.Session.query(Tag).filter_by(expenditure_id=self.id))
+
+ for tag in tags:
+ t = Tag(self, tag)
+ meta.Session.add(t)
+
def involves(self, user):
"Returns True if ``user`` is involved in this expenditure."
return (any((split.user == user) and (split.share != 0)
--- /dev/null
+class Tag(object):
+ def __init__(self, expenditure=None, tag=u""):
+ self.expenditure = expenditure
+ self.tag = tag
+
+ def __repr__(self):
+ return '<Tag: expense: %s value: %s>' % (self.expenditure,
+ self.tag)
+
+__all__ = ['Tag']
<th><label for="description">Description</label></th>
<td>${h.text('description', c.expenditure.description, size=64)}</td>
</tr>
+ <tr>
+ <th><label for="tags">Tags</label></th>
+ <td>${h.text('tags', c.values['tags'], size=64)}</td>
+ </tr>
</table>
<p>Change how an expenditure is split up. Enter a percentage, or something like a percentage, for each user. They don't have to add to 100.</p>