]> asedeno.scripts.mit.edu Git - bluechips.git/blob - bluechips/model/expenditure.py
Switch from using Decimal to using a new Currency class
[bluechips.git] / bluechips / model / expenditure.py
1 from user import User
2 from split import Split
3 from bluechips.model import meta
4 from bluechips.model.types import Currency
5 from decimal import Decimal
6 import random
7
8 class Expenditure(object):
9     def __repr__(self):
10         return '<Expenditure: spender: %s spent: %s>' % (self.spender,
11                                                          self.amount)
12
13     def even_split(self):
14         """
15         Split up an expenditure evenly among the resident users
16         """
17         
18         residents = meta.Session.query(User).filter(User.resident==True)
19         split_percentage = Decimal(100) / Decimal(residents.count())
20         self.split(dict((resident, split_percentage) for resident in residents))
21     
22     def split(self, split_dict):
23         """
24         Split up an expenditure.
25         
26         split_dict should be a dict mapping from bluechips.model:User
27         objects to a decimal:Decimal object representing the percentage
28         that user is responsible for.
29         
30         Percentages will be normalized to sum to 100%.
31         
32         If the split leaks or gains money due to rounding errors, the
33         pennies will be randomly distributed to one of the users.
34         
35         I mean, come on. You're already living together. Are you really
36         going to squabble over a few pennies?
37         """
38         
39         map(meta.Session.delete, meta.Session.query(Split).\
40                 filter_by(expenditure_id=self.id))
41         
42         total = sum(split_dict.itervalues())
43         
44         for user, share in split_dict.iteritems():
45             split_dict[user] = share / total
46             
47         amounts_dict = dict()
48         
49         for user, share in split_dict.iteritems():
50             amounts_dict[user] = Currency(split_dict[user] * self.amount)
51         
52         difference = self.amount - sum(amounts_dict.itervalues())
53         
54         if difference > 0:
55             for i in xrange(difference * 100):
56                 winner = random.choice(amounts_dict.keys())
57                 amounts_dict[winner] += Currency(1)
58         elif difference < 0:
59             for i in xrange(difference * -100):
60                 winner = random.choice(amounts_dict.keys())
61                 amounts_dict[winner] -= Currency(1)
62         
63         for user, share in amounts_dict.iteritems():
64             s = Split()
65             s.expenditure = self
66             s.user = user
67             s.share = share
68             meta.Session.save(s)
69
70 __all__ = ['Expenditure']