Skip to content

Commit

Permalink
Add a statistics tab
Browse files Browse the repository at this point in the history
  • Loading branch information
0livd committed Aug 3, 2017
1 parent 8fd53f8 commit 648b068
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 0 deletions.
10 changes: 10 additions & 0 deletions ihatemoney/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ def get_bills(self):
.order_by(Bill.date.desc())\
.order_by(Bill.id.desc())

def get_member_bills(self, member_id):
"""Return the list of bills related to a specific member"""
return Bill.query.join(Person, Project)\
.filter(Bill.payer_id == Person.id)\
.filter(Person.project_id == Project.id)\
.filter(Person.id == member_id)\
.filter(Project.id == self.id)\
.order_by(Bill.date.desc())\
.order_by(Bill.id.desc())

def get_pretty_bills(self, export_format="json"):
"""Return a list of project's bills with pretty formatting"""
bills = self.get_bills()
Expand Down
1 change: 1 addition & 0 deletions ihatemoney/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ <h1><a class="navbar-brand" href="{{ url_for(".home") }}">#! money?</a></h1>
{% block navbar %}
<li class="nav-item{% if current_view == 'list_bills' %} active{% endif %}"><a class="nav-link" href="{{ url_for(".list_bills") }}">{{ _("Bills") }}</a></li>
<li class="nav-item{% if current_view == 'settle_bill' %} active{% endif %}"><a class="nav-link" href="{{ url_for(".settle_bill") }}">{{ _("Settle") }}</a></li>
<li class="nav-item{% if current_view == 'statistics' %} active{% endif %}"><a class="nav-link" href="{{ url_for(".statistics") }}">{{ _("Statistics") }}</a></li>
{% endblock %}
{% endif %}
</ul>
Expand Down
35 changes: 35 additions & 0 deletions ihatemoney/templates/statistics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{% extends "sidebar_table_layout.html" %}

{% block sidebar %}
<div id="table_overflow">
<table class="balance table">
{% set balance = g.project.balance %}
{% for member in g.project.members | sort(attribute='name') if member.activated or balance[member.id]|round(2) != 0 %}
<tr id="bal-member-{{ member.id }}" action={% if member.activated %}delete{% else %}reactivate{% endif %}>
<td class="balance-name">{{ member.name }}</td>
<td class="balance-value {% if balance[member.id]|round(2) > 0 %}positive{% elif balance[member.id]|round(2) < 0 %}negative{% endif %}">
{% if balance[member.id]|round(2) > 0 %}+{% endif %}{{ "%.2f" | format(balance[member.id]) }}
</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}


{% block content %}
<table id="bill_table" class="split_bills table table-striped">
<thead><tr><th>{{ _("Who?") }}</th><th>{{ _("Paid") }}</th><th>{{ _("Spent") }}</th><th>{{ _("Balance") }}</th></tr></thead>
<tbody>
{% for member in members %}
<tr class="{{ loop.cycle("odd", "even") }}">
<td>{{ member.name }}</td>
<td>{{ "%0.2f"|format(paid[member.id]) }}</td>
<td>{{ "%0.2f"|format(spent[member.id]) }}</td>
<td>{{ "%0.2f"|format(balance[member.id]) }}</td>
</tr>
{% endfor %}
</tbody>
</table>

{% endblock %}
62 changes: 62 additions & 0 deletions ihatemoney/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,68 @@ def test_dashboard(self):
response = self.client.get("/dashboard")
self.assertEqual(response.status_code, 200)

def test_statistics_page(self):
self.post_project("raclette")
response = self.client.get("/raclette/statistics")
self.assertEqual(response.status_code, 200)

def test_statistics(self):
self.post_project("raclette")

# add members
self.client.post("/raclette/members/add", data={'name': 'alexis', 'weight': 2})
self.client.post("/raclette/members/add", data={'name': 'fred'})
self.client.post("/raclette/members/add", data={'name': 'tata'})
# Add a member with a balance=0 :
self.client.post("/raclette/members/add", data={'name': 'toto'})

# create bills
self.client.post("/raclette/add", data={
'date': '2011-08-10',
'what': 'fromage à raclette',
'payer': 1,
'payed_for': [1, 2, 3],
'amount': '10.0',
})

self.client.post("/raclette/add", data={
'date': '2011-08-10',
'what': 'red wine',
'payer': 2,
'payed_for': [1],
'amount': '20',
})

self.client.post("/raclette/add", data={
'date': '2011-08-10',
'what': 'delicatessen',
'payer': 1,
'payed_for': [1, 2],
'amount': '10',
})

response = self.client.get("/raclette/statistics")
self.assertIn("<td>alexis</td>\n "
+ "<td>20.00</td>\n "
+ "<td>31.67</td>\n "
+ "<td>-11.67</td>\n",
response.data.decode('utf-8'))
self.assertIn("<td>fred</td>\n "
+ "<td>20.00</td>\n "
+ "<td>5.83</td>\n "
+ "<td>14.17</td>\n",
response.data.decode('utf-8'))
self.assertIn("<td>tata</td>\n "
+ "<td>0.00</td>\n "
+ "<td>2.50</td>\n "
+ "<td>-2.50</td>\n",
response.data.decode('utf-8'))
self.assertIn("<td>toto</td>\n "
+ "<td>0.00</td>\n "
+ "<td>0.00</td>\n "
+ "<td>0.00</td>\n",
response.data.decode('utf-8'))

def test_settle_page(self):
self.post_project("raclette")
response = self.client.get("/raclette/settle_bills")
Expand Down
Binary file modified ihatemoney/translations/fr/LC_MESSAGES/messages.mo
Binary file not shown.
20 changes: 20 additions & 0 deletions ihatemoney/translations/fr/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,10 @@ msgstr "Factures"
msgid "Settle"
msgstr "Remboursements"

#: templates/layout.html:50
msgid "Statistics"
msgstr "Statistiques"

#: templates/layout.html:53
msgid "options"
msgstr "options"
Expand Down Expand Up @@ -525,3 +529,19 @@ msgstr "Qui doit payer ?"
#: templates/settle_bills.html:31
msgid "To whom?"
msgstr "Pour qui ?"

#: templates/statistics.html:22
msgid "Who?"
msgstr "Qui ?"

#: templates/statistics.html:22
msgid "Paid"
msgstr "A payé"

#: templates/statistics.html:22
msgid "Spent"
msgstr "A dépensé"

#: templates/statistics.html:22
msgid "Balance"
msgstr "Solde"
22 changes: 22 additions & 0 deletions ihatemoney/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,28 @@ def settle_bill():
)


@main.route("/<project_id>/statistics")
def statistics():
"""Compute what each member has paid and spent and display it"""
members = g.project.active_members
balance = g.project.balance
paid = {}
spent = {}
for member in members:
paid[member.id] = sum([bill.amount
for bill in g.project.get_member_bills(member.id).all()])
spent[member.id] = sum([bill.pay_each() * member.weight
for bill in g.project.get_bills().all() if member in bill.owers])
return render_template(
"statistics.html",
members=members,
balance=balance,
paid=paid,
spent=spent,
current_view='statistics',
)


@main.route("/dashboard")
def dashboard():
return render_template("dashboard.html", projects=Project.query.all())

0 comments on commit 648b068

Please sign in to comment.