]> asedeno.scripts.mit.edu Git - bluechips.git/blob - bluechips/lib/split.py
When entering a split, only delete old splits from the same expense
[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             filter_by(expenditure_id=e.id))
43     
44     total = sum(split_dict.itervalues())
45     
46     for user, share in split_dict.iteritems():
47         split_dict[user] = share / total
48     
49     amounts_dict = dict()
50     
51     for user, share in split_dict.iteritems():
52         amounts_dict[user] = round_currency(split_dict[user] * e.amount)
53     
54     difference = e.amount - sum(amounts_dict.itervalues())
55     
56     if difference > 0:
57         for i in xrange(difference * 100):
58             winner = random.choice(amounts_dict.keys())
59             amounts_dict[winner] += Decimal('0.01')
60     elif difference < 0:
61         for i in xrange(difference * -100):
62             winner = random.choice(amounts_dict.keys())
63             amounts_dict[winner] -= Decimal('0.01')
64     
65     for user, share in amounts_dict.iteritems():
66         s = model.Split()
67         s.expenditure = e
68         s.user = user
69         s.share = share
70         Session.save(s)
71
72 __all__ = ['split', 'even_split']