From 543df7c1d43c49fd8cf48e7028524cb760da5654 Mon Sep 17 00:00:00 2001 From: Baptiste Jonglez Date: Tue, 3 Jan 2017 21:36:49 +0100 Subject: [PATCH 1/3] Add a test to catch zero-amount transfers in the settle page --- budget/tests.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/budget/tests.py b/budget/tests.py index eea7537..f0a5ea7 100644 --- a/budget/tests.py +++ b/budget/tests.py @@ -580,6 +580,46 @@ class BudgetTestCase(TestCase): self.assertEqual(a, balance[m.id]) return + def test_settle_zero(self): + self.post_project("raclette") + + # add members + self.app.post("/raclette/members/add", data={'name': 'alexis'}) + self.app.post("/raclette/members/add", data={'name': 'fred'}) + self.app.post("/raclette/members/add", data={'name': 'tata'}) + + # create bills + self.app.post("/raclette/add", data={ + 'date': '2016-12-31', + 'what': u'fromage à raclette', + 'payer': 1, + 'payed_for': [1, 2, 3], + 'amount': '10.0', + }) + + self.app.post("/raclette/add", data={ + 'date': '2016-12-31', + 'what': u'red wine', + 'payer': 2, + 'payed_for': [1, 3], + 'amount': '20', + }) + + self.app.post("/raclette/add", data={ + 'date': '2017-01-01', + 'what': u'refund', + 'payer': 3, + 'payed_for': [2], + 'amount': '13.33', + }) + project = models.Project.query.get('raclette') + transactions = project.get_transactions_to_settle_bill() + members = defaultdict(int) + # There should not be any zero-amount transfer after rounding + for t in transactions: + rounded_amount = round(t['amount'], 2) + self.assertNotEqual(0.0, rounded_amount, + msg='%f is equal to zero after rounding' % t['amount']) class APITestCase(TestCase): From b507a5afa1b4e3594a3a35f3aae08f7f38989338 Mon Sep 17 00:00:00 2001 From: Baptiste Jonglez Date: Mon, 2 Jan 2017 14:52:59 +0100 Subject: [PATCH 2/3] Prevent transfers with a zero amount in the settle page This workarounds a rounding issue caused by the (incorrect) usage of floats for bill amounts. This fixes #138 --- budget/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/budget/models.py b/budget/models.py index 852b3e1..b17fc55 100644 --- a/budget/models.py +++ b/budget/models.py @@ -61,9 +61,9 @@ class Project(db.Model): credits, debts, transactions = [],[],[] # Create lists of credits and debts for person in self.members: - if balance[person.id] > 0: + if round(balance[person.id], 2) > 0: credits.append({"person": person, "balance": balance[person.id]}) - elif balance[person.id] < 0: + elif round(balance[person.id], 2) < 0: debts.append({"person": person, "balance": -balance[person.id]}) # Try and find exact matches for credit in credits: From d6cf89008fdb5e40395d3ccc879db2255f13e461 Mon Sep 17 00:00:00 2001 From: Baptiste Jonglez Date: Mon, 2 Jan 2017 14:55:48 +0100 Subject: [PATCH 3/3] Workaround rounding issues when displaying balance of users A user with a "0.00" balance would have either a "+0.00" in green or a "-0.00" in red, depending on the exact value of the floating-point value. Fix this by simply rounding to 2 digits before comparing to zero. --- budget/templates/list_bills.html | 6 +++--- budget/templates/settle_bills.html | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/budget/templates/list_bills.html b/budget/templates/list_bills.html index f081334..72b9032 100644 --- a/budget/templates/list_bills.html +++ b/budget/templates/list_bills.html @@ -65,7 +65,7 @@
{% set balance = g.project.balance %} - {% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id] != 0 %} + {% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %} {% endif %} - {% endfor %} diff --git a/budget/templates/settle_bills.html b/budget/templates/settle_bills.html index 4066b16..16c60b3 100644 --- a/budget/templates/settle_bills.html +++ b/budget/templates/settle_bills.html @@ -11,11 +11,11 @@
{{ member.name }} (x{{ member.weight|minimal_round(1) }}) @@ -82,8 +82,8 @@
- {% if balance[member.id] > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }} + + {% if balance[member.id]|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }}
{% set balance = g.project.balance %} - {% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id] != 0 %} + {% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %} - {% endfor %}
{{ member.name }} - {% if balance[member.id] > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }} + + {% if balance[member.id]|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }}