X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=bluechips%2Flib%2Ftotals.py;h=94a62a127bbe73d63f70bec4f8c9e6928414a18e;hb=fed6d11d2cbd6d617d18bc01a78196865da4155b;hp=3cdbf45efbdec674d8bfc14df8fc17b85396c181;hpb=29bb94f07aaf933dd06bf4eef8b8a40222d977c5;p=bluechips.git diff --git a/bluechips/lib/totals.py b/bluechips/lib/totals.py index 3cdbf45..94a62a1 100644 --- a/bluechips/lib/totals.py +++ b/bluechips/lib/totals.py @@ -3,11 +3,11 @@ Calculate the total state of the books """ from bluechips import model -from bluechips.model.meta import Session +from bluechips.model import meta -import sqlalchemy +from bluechips.model.types import Currency -from decimal import Decimal +import sqlalchemy class DirtyBooks(Exception): """ @@ -19,40 +19,43 @@ def debts(): # In this scheme, negative numbers represent money the house owes # the user, and positive numbers represent money the user owes the # house - users = Session.query(model.User) + users = meta.Session.query(model.User) - debts = {} + debts_dict = dict((u, Currency(0)) for u in users) # First, credit everyone for expenditures they've made - for user in users: - debts[user] = -sum(map((lambda x: x.amount), user.expenditures)) + total_expenditures = meta.Session.query(model.Expenditure).\ + add_column(sqlalchemy.func.sum(model.Expenditure.amount).label('total_spend')).\ + group_by(model.Expenditure.spender_id) + for expenditure, total_spend in total_expenditures: + debts_dict[expenditure.spender] -= total_spend # Next, debit everyone for expenditures that they have an # investment in (i.e. splits) - total_splits = Session.query(model.Split).\ + total_splits = meta.Session.query(model.Split).\ add_column(sqlalchemy.func.sum(model.Split.share).label('total_split')).\ group_by(model.Split.user_id) for split, total_cents in total_splits: - debts[split.user] += (total_cents / 100) + debts_dict[split.user] += total_cents # Finally, move transfers around appropriately # # To keep this from getting to be expensive, have SQL sum up # transfers for us - transfer_q = Session.query(model.Transfer).\ + transfer_q = meta.Session.query(model.Transfer).\ add_column(sqlalchemy.func.sum(model.Transfer.amount).label('total_amount')) total_debits = transfer_q.group_by(model.Transfer.debtor_id) total_credits = transfer_q.group_by(model.Transfer.creditor_id) for transfer, total_amount in total_debits: - debts[transfer.debtor] -= (total_amount / 100) + debts_dict[transfer.debtor] -= total_amount for transfer, total_amount in total_credits: - debts[transfer.creditor] += (total_amount / 100) + debts_dict[transfer.creditor] += total_amount - return debts + return debts_dict def settle(debts_dict): # This algorithm has been shamelessly stolen from Nelson Elhage's @@ -60,14 +63,17 @@ def settle(debts_dict): debts_list = [dict(who=user, amount=amount) for user, amount in \ debts_dict.iteritems()] - debts_list.sort(reverse=True, key=(lambda x: abs(x['amount']))) + #debts_list.sort(reverse=True, key=(lambda x: abs(x['amount']))) owes_list = [debt for debt in debts_list if debt['amount'] > 0] owed_list = [debt for debt in debts_list if debt['amount'] < 0] - settle = [] + settle_list = [] while len(owes_list) > 0 and len(owed_list) > 0: + owes_list.sort(reverse=True, key=(lambda x: abs(x['amount']))) + owed_list.sort(reverse=True, key=(lambda x: abs(x['amount']))) + owes = owes_list[0] owed = owed_list[0] @@ -88,13 +94,13 @@ def settle(debts_dict): owes_list.pop(0) val = owes['amount'] - settle.append((owes['who'], owed['who'], val)) + settle_list.append((owes['who'], owed['who'], val)) if len(owes_list) > 0: raise DirtyBooks, ("People still owe money", owes_list) if len(owed_list) > 0: raise DirtyBooks, ("People are still owed money", owed_list) - return settle + return settle_list __all__ = ['debts', 'settle']