diff --git a/ihatemoney/models.py b/ihatemoney/models.py index 3272cf41c..70c7fd04f 100644 --- a/ihatemoney/models.py +++ b/ihatemoney/models.py @@ -113,42 +113,57 @@ def active_members(self): @property def full_balance(self): - """Returns a triple of dicts: + """Returns a tuple of dicts: - - dict mapping each member to its balance + - dict mapping each member to its overall balance - - dict mapping each member to how much he/she should pay others - (i.e. how much he/she benefited from bills) + - dict mapping each member to its expenses (i.e. how much he/she + benefited from all bills, whoever actually paid) - - dict mapping each member to how much he/she should be paid by - others (i.e. how much he/she has paid for bills) + - dict mapping each member to how much he/she has paid for bills + + - dict mapping each member to how much he/she has transferred + money to other members + + - dict mapping each member to how much he/she has received money + from other members + + balance, spent, paid, transferred, received - balance spent paid """ - balances, should_pay, should_receive = (defaultdict(int) for time in (1, 2, 3)) + balances, spent, paid, transferred, received = ( + defaultdict(float) for _ in range(5) + ) for bill in self.get_bills_unordered().all(): total_weight = sum(ower.weight for ower in bill.owers) if bill.bill_type == BillType.EXPENSE: - should_receive[bill.payer.id] += bill.converted_amount + paid[bill.payer.id] += bill.converted_amount for ower in bill.owers: - should_pay[ower.id] += ( - ower.weight * bill.converted_amount / total_weight - ) + spent[ower.id] += ower.weight * bill.converted_amount / total_weight if bill.bill_type == BillType.REIMBURSEMENT: - should_receive[bill.payer.id] += bill.converted_amount + transferred[bill.payer.id] += bill.converted_amount for ower in bill.owers: - should_receive[ower.id] -= bill.converted_amount + received[ower.id] += ( + ower.weight * bill.converted_amount / total_weight + ) for person in self.members: - balance = should_receive[person.id] - should_pay[person.id] + balance = ( + paid[person.id] + - spent[person.id] + + transferred[person.id] + - received[person.id] + ) balances[person.id] = balance return ( balances, - should_pay, - should_receive, + spent, + paid, + transferred, + received, ) @property @@ -157,17 +172,19 @@ def balance(self): @property def members_stats(self): - """Compute what each participant has paid + """Compute what each participant has spent, paid, transferred and received :return: one stat dict per participant :rtype list: """ - balance, spent, paid = self.full_balance + balance, spent, paid, transferred, received = self.full_balance return [ { "member": member, + "spent": -1.0 * spent[member.id], "paid": paid[member.id], - "spent": spent[member.id], + "transferred": transferred[member.id], + "received": -1.0 * received[member.id], "balance": balance[member.id], } for member in self.active_members @@ -209,7 +226,6 @@ def prettify(transactions, pretty_output): ) return pretty_transactions - # cache value for better performance members = {person.id: person for person in self.members} settle_plan = settle(self.balance.items()) or [] @@ -225,22 +241,6 @@ def prettify(transactions, pretty_output): return prettify(transactions, pretty_output) - def exactmatch(self, credit, debts): - """Recursively try and find subsets of 'debts' whose sum is equal to credit""" - if not debts: - return None - 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_unordered().count() > 0 diff --git a/ihatemoney/templates/statistics.html b/ihatemoney/templates/statistics.html index 86f9cd42e..e367c7470 100644 --- a/ihatemoney/templates/statistics.html +++ b/ihatemoney/templates/statistics.html @@ -10,20 +10,22 @@ {% block content %}
- + {% for stat in members_stats|sort(attribute='member.name') %} + + {% endfor %}
{{ _("Who?") }}{{ _("Paid") }}{{ _("Spent") }}
{{ _("Who?") }}{{ _("Paid") }}{{ _("Expenses") }}{{ _("Transferred") }}{{ _("Received") }}
{{ stat.member.name }} {{ stat.paid|currency }} {{ stat.spent|currency }}{{ stat.transferred|currency }}{{ stat.received|currency }}
-

{{ _("Expenses by Month") }}

+

{{ _("Expenses by month") }}

- + {% for month in months %}
{{ _("Period") }}{{ _("Spent") }}
{{ _("Period") }}{{ _("Expenses") }}