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