From cb13fbb782d3fda9f2ce20fcffddeb7cdf3a84a8 Mon Sep 17 00:00:00 2001 From: Xavier Mehrenberger Date: Mon, 12 Mar 2012 00:35:06 +0100 Subject: Split bills function and basic template. --- budget/models.py | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'budget/models.py') diff --git a/budget/models.py b/budget/models.py index 5783703..a92281b 100644 --- a/budget/models.py +++ b/budget/models.py @@ -45,10 +45,57 @@ class Project(db.Model): for person in self.members: balance = should_receive[person] - should_pay[person] - balances[person.id] = round(balance, 2) + balances[person] = round(balance, 2) return balances + def settle_bill(self): + """Return a list of transactions that could be made to settle the bill""" + balances = self.balance + credits, debts = list(), list() + transactions = list() + # Create lists of credits and debts + for person in balances.keys(): + if balances[person] > 0: + credits.append({"person": person, "balance": balances[person]}) + elif balances[person] < 0: + debts.append({"person": person, "balance": -balances[person]}) + # Try and find exact matches + for credit in credits: + match = self.exactmatch(credit["balance"], debts) + if match: + for m in match: + transactions.append({"ower": m["person"], "payer": credit["person"], "amount": m["balance"]}) + debts.remove(m) + credits.remove(credit) + # Split any remaining debts & credits + while credits and debts: + if credits[0]["balance"] > debts[0]["balance"]: + transactions.append({"ower": debts[0]["person"], "payer": credits[0]["person"], "amount": debts[0]["balance"]}) + credits[0]["balance"] = credits[0]["balance"] - debts[0]["balance"] + del debts[0] + else: + transactions.append({"ower": debts[0]["person"], "payer": credits[0]["person"], "amount": credits[0]["balance"]}) + debts[0]["balance"] = debts[0]["balance"] - credits[0]["balance"] + del credits[0] + return transactions + + def exactmatch(self, credit, debts): + """Recursively try and find subsets of 'debts' whose sum is equal to credit""" + if not debts: + return [] + if debts[0]["balance"] > credit: + return self.exactmatch(credit, debts[1:]) + elif debts[0]["balance"] == credit: + return [debts[0]] + else: + match = self.exactmatch(credit-debts[0]["balance"], debts[1:]) + if match: + match.append(debts[0]) + else: + match = self.exactmatch(credit, debts[1:]) + return match + def has_bills(self): """return if the project do have bills or not""" return self.get_bills().count() > 0 -- cgit v1.1 From 1fa0cff180d668a8d93d24413fe7832cdbd3e826 Mon Sep 17 00:00:00 2001 From: "A.Avenel" Date: Sun, 7 Apr 2013 20:25:25 +0200 Subject: use "member.id" instead of "member" --- budget/models.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'budget/models.py') diff --git a/budget/models.py b/budget/models.py index 8f57ffd..1f3fa4f 100644 --- a/budget/models.py +++ b/budget/models.py @@ -45,21 +45,19 @@ class Project(db.Model): for person in self.members: balance = should_receive[person] - should_pay[person] - balances[person] = round(balance, 2) + balances[person.id] = round(balance, 2) return balances - def settle_bill(self): + def settle_bills(self): """Return a list of transactions that could be made to settle the bill""" - balances = self.balance - credits, debts = list(), list() - transactions = list() + credits, debts, transactions = [],[],[] # Create lists of credits and debts - for person in balances.keys(): - if balances[person] > 0: - credits.append({"person": person, "balance": balances[person]}) - elif balances[person] < 0: - debts.append({"person": person, "balance": -balances[person]}) + for person in self.members: + if self.balance[person.id] > 0: + credits.append({"person": person, "balance": self.balance[person.id]}) + elif self.balance[person.id] < 0: + debts.append({"person": person, "balance": -self.balance[person.id]}) # Try and find exact matches for credit in credits: match = self.exactmatch(credit["balance"], debts) @@ -83,7 +81,7 @@ class Project(db.Model): def exactmatch(self, credit, debts): """Recursively try and find subsets of 'debts' whose sum is equal to credit""" if not debts: - return [] + return None if debts[0]["balance"] > credit: return self.exactmatch(credit, debts[1:]) elif debts[0]["balance"] == credit: -- cgit v1.1 From 0d7c82b12267ed3a9ece1ca72a71cea077e9cc0f Mon Sep 17 00:00:00 2001 From: "A.Avenel" Date: Sun, 7 Apr 2013 22:14:32 +0200 Subject: More code cleanup for "settle bills" --- budget/models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'budget/models.py') diff --git a/budget/models.py b/budget/models.py index 1f3fa4f..49c3eb4 100644 --- a/budget/models.py +++ b/budget/models.py @@ -49,7 +49,7 @@ class Project(db.Model): return balances - def settle_bills(self): + def get_transactions_to_settle_bill(self): """Return a list of transactions that could be made to settle the bill""" credits, debts, transactions = [],[],[] # Create lists of credits and debts @@ -63,17 +63,17 @@ class Project(db.Model): match = self.exactmatch(credit["balance"], debts) if match: for m in match: - transactions.append({"ower": m["person"], "payer": credit["person"], "amount": m["balance"]}) + transactions.append({"ower": m["person"], "receiver": credit["person"], "amount": m["balance"]}) debts.remove(m) credits.remove(credit) # Split any remaining debts & credits while credits and debts: if credits[0]["balance"] > debts[0]["balance"]: - transactions.append({"ower": debts[0]["person"], "payer": credits[0]["person"], "amount": debts[0]["balance"]}) + transactions.append({"ower": debts[0]["person"], "receiver": credits[0]["person"], "amount": debts[0]["balance"]}) credits[0]["balance"] = credits[0]["balance"] - debts[0]["balance"] del debts[0] else: - transactions.append({"ower": debts[0]["person"], "payer": credits[0]["person"], "amount": credits[0]["balance"]}) + transactions.append({"ower": debts[0]["person"], "receiver": credits[0]["person"], "amount": credits[0]["balance"]}) debts[0]["balance"] = debts[0]["balance"] - credits[0]["balance"] del credits[0] return transactions -- cgit v1.1 From ff9ead22031563b31f14e87ae3b3c537a06b8c41 Mon Sep 17 00:00:00 2001 From: "A.Avenel" Date: Thu, 9 May 2013 23:23:23 +0200 Subject: Optimization --- budget/models.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'budget/models.py') diff --git a/budget/models.py b/budget/models.py index 49c3eb4..2d44145 100644 --- a/budget/models.py +++ b/budget/models.py @@ -51,13 +51,15 @@ class Project(db.Model): def get_transactions_to_settle_bill(self): """Return a list of transactions that could be made to settle the bill""" + #cache value for better performance + balance = self.balance credits, debts, transactions = [],[],[] # Create lists of credits and debts for person in self.members: - if self.balance[person.id] > 0: - credits.append({"person": person, "balance": self.balance[person.id]}) - elif self.balance[person.id] < 0: - debts.append({"person": person, "balance": -self.balance[person.id]}) + if balance[person.id] > 0: + credits.append({"person": person, "balance": balance[person.id]}) + elif balance[person.id] < 0: + debts.append({"person": person, "balance": -balance[person.id]}) # Try and find exact matches for credit in credits: match = self.exactmatch(credit["balance"], debts) -- cgit v1.1