aboutsummaryrefslogtreecommitdiff
path: root/budget
diff options
context:
space:
mode:
authorAlexis Metaireau <alexis@notmyidea.org>2013-05-09 18:32:55 -0700
committerAlexis Metaireau <alexis@notmyidea.org>2013-05-09 18:32:55 -0700
commita71d249e6c35b9a204d50e40365945c359ee5b63 (patch)
tree4c7e03c81868237192992d8d2ff587f68fab0a4d /budget
parentaa7d79d2ad119e575d8cd14f19369e74b22f804b (diff)
parentff9ead22031563b31f14e87ae3b3c537a06b8c41 (diff)
downloadihatemoney-mirror-a71d249e6c35b9a204d50e40365945c359ee5b63.zip
ihatemoney-mirror-a71d249e6c35b9a204d50e40365945c359ee5b63.tar.gz
ihatemoney-mirror-a71d249e6c35b9a204d50e40365945c359ee5b63.tar.bz2
Merge pull request #96 from aavenel/master
New feature : Settle the bill
Diffstat (limited to 'budget')
-rw-r--r--budget/messages.pot253
-rw-r--r--budget/models.py47
-rw-r--r--budget/templates/layout.html3
-rw-r--r--budget/templates/list_bills.html2
-rw-r--r--budget/templates/settle_bills.html43
-rw-r--r--budget/tests.py67
-rw-r--r--budget/translations/fr/LC_MESSAGES/messages.mobin7123 -> 7888 bytes
-rw-r--r--budget/translations/fr/LC_MESSAGES/messages.po262
-rw-r--r--budget/web.py7
9 files changed, 460 insertions, 224 deletions
diff --git a/budget/messages.pot b/budget/messages.pot
index effeccf..b3cb0cc 100644
--- a/budget/messages.pot
+++ b/budget/messages.pot
@@ -1,203 +1,211 @@
# Translations template for PROJECT.
-# Copyright (C) 2011 ORGANIZATION
+# Copyright (C) 2013 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
-# Alexis Métaireau <alexis@notmyidea.org>, 2011.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-11-20 14:05+0100\n"
+"POT-Creation-Date: 2013-05-09 22:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: Quentin Roy <royque@gmail.com>\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
-#: forms.py:20
-msgid "Select All/None"
+#: forms.py:22
+msgid "Select all"
msgstr ""
-#: forms.py:57
+#: forms.py:22
+msgid "Select none"
+msgstr ""
+
+#: forms.py:61
msgid "Project name"
msgstr ""
-#: forms.py:58 forms.py:82 forms.py:93
+#: forms.py:62 forms.py:86 forms.py:102
msgid "Private code"
msgstr ""
-#: forms.py:59
+#: forms.py:63
msgid "Email"
msgstr ""
-#: forms.py:81 forms.py:92 forms.py:98
+#: forms.py:85 forms.py:101 forms.py:107
msgid "Project identifier"
msgstr ""
-#: forms.py:83 templates/send_invites.html:5
+#: forms.py:87 templates/send_invites.html:5
msgid "Create the project"
msgstr ""
-#: forms.py:88
+#: forms.py:92
msgid ""
"The project identifier is used to log in and for the URL of the project. "
"We tried to generate an identifier for you but a project with this "
-"identifier already exists. Please create a new identifier you will be "
-"able to remember."
+"identifier already exists. Please create a new identifier that you will "
+"be able to remember."
msgstr ""
-#: forms.py:94
+#: forms.py:103
msgid "Get in"
msgstr ""
-#: forms.py:99
+#: forms.py:108
msgid "Send me the code by email"
msgstr ""
-#: forms.py:103
+#: forms.py:112
msgid "This project does not exists"
msgstr ""
-#: forms.py:107
+#: forms.py:116
msgid "Date"
msgstr ""
-#: forms.py:108
+#: forms.py:117
msgid "What?"
msgstr ""
-#: forms.py:109
+#: forms.py:118
msgid "Payer"
msgstr ""
-#: forms.py:110
+#: forms.py:119
msgid "Amount paid"
msgstr ""
-#: forms.py:111 templates/list_bills.html:154
+#: forms.py:120 templates/list_bills.html:103
msgid "For whom?"
msgstr ""
-#: forms.py:113
-msgid "Send the bill"
+#: forms.py:122
+msgid "Submit"
msgstr ""
-#: forms.py:139
-msgid "Bills can't be null"
+#: forms.py:123
+msgid "Submit and add a new one"
msgstr ""
-#: forms.py:144
-msgid "Name"
+#: forms.py:149
+msgid "Bills can't be null"
msgstr ""
-#: forms.py:144
-msgid "Type user name here"
+#: forms.py:154
+msgid "Name"
msgstr ""
-#: forms.py:145 templates/forms.html:94
+#: forms.py:155 templates/forms.html:95
msgid "Add"
msgstr ""
-#: forms.py:153
+#: forms.py:163
msgid "User name incorrect"
msgstr ""
-#: forms.py:157
+#: forms.py:167
msgid "This project already have this member"
msgstr ""
-#: forms.py:167
+#: forms.py:178
msgid "People to notify"
msgstr ""
-#: forms.py:168
+#: forms.py:179
msgid "Send invites"
msgstr ""
-#: forms.py:174
+#: forms.py:185
#, python-format
msgid "The email %(email)s is not valid"
msgstr ""
-#: forms.py:179
-msgid "Start date"
+#: forms.py:190
+msgid "Name for this archive (optional)"
msgstr ""
-#: forms.py:180
-msgid "End date"
+#: forms.py:191
+msgid "Start date"
msgstr ""
-#: forms.py:181
-msgid "Name for this archive (optional)"
+#: forms.py:192
+msgid "End date"
msgstr ""
-#: web.py:89
+#: web.py:95
msgid "This private code is not the right one"
msgstr ""
-#: web.py:137
+#: web.py:147
#, python-format
msgid "You have just created '%(project)s' to share your expenses"
msgstr ""
-#: web.py:148
+#: web.py:165
#, python-format
-msgid "The project identifier is %(project)s"
+msgid "%(msg_compl)sThe project identifier is %(project)s"
msgstr ""
-#: web.py:166
+#: web.py:185
msgid "a mail has been sent to you with the password"
msgstr ""
-#: web.py:229
+#: web.py:211
+msgid "Project successfully deleted"
+msgstr ""
+
+#: web.py:254
#, python-format
msgid "You have been invited to share your expenses for %(project)s"
msgstr ""
-#: web.py:236
+#: web.py:261
msgid "Your invitations have been sent"
msgstr ""
-#: web.py:261
+#: web.py:290
#, python-format
msgid "%(member)s had been added"
msgstr ""
-#: web.py:273
+#: web.py:303
#, python-format
msgid "%(name)s is part of this project again"
msgstr ""
-#: web.py:281
+#: web.py:311
#, python-format
msgid "User '%(name)s' has been deactivated"
msgstr ""
-#: web.py:283
+#: web.py:313
#, python-format
msgid "User '%(name)s' has been removed"
msgstr ""
-#: web.py:300
+#: web.py:331
msgid "The bill has been added"
msgstr ""
-#: web.py:315
+#: web.py:351
msgid "The bill has been deleted"
msgstr ""
-#: web.py:333
+#: web.py:369
msgid "The bill has been modified"
msgstr ""
-#: web.py:357
+#: web.py:399
msgid "The data from XX to XX has been archived"
msgstr ""
-#: templates/add_bill.html:19
+#: templates/add_bill.html:9
msgid "Back to the list"
msgstr ""
@@ -219,8 +227,27 @@ msgstr ""
msgid "Create a new project"
msgstr ""
-#: templates/edit_project.html:6 templates/list_bills.html:77
-#: templates/list_bills.html:87
+#: templates/dashboard.html:5
+msgid "Project"
+msgstr ""
+
+#: templates/dashboard.html:5
+msgid "Number of members"
+msgstr ""
+
+#: templates/dashboard.html:5
+msgid "Number of bills"
+msgstr ""
+
+#: templates/dashboard.html:5
+msgid "Newest bill"
+msgstr ""
+
+#: templates/dashboard.html:5
+msgid "Oldest bill"
+msgstr ""
+
+#: templates/edit_project.html:6 templates/list_bills.html:24
msgid "you sure?"
msgstr ""
@@ -228,31 +255,35 @@ msgstr ""
msgid "Edit this project"
msgstr ""
-#: templates/forms.html:24
+#: templates/forms.html:23
msgid "Can't remember the password?"
msgstr ""
-#: templates/forms.html:27
+#: templates/forms.html:26
msgid "Cancel"
msgstr ""
-#: templates/forms.html:69
+#: templates/forms.html:68
msgid "Edit the project"
msgstr ""
-#: templates/forms.html:70 templates/list_bills.html:139
-#: templates/list_bills.html:167
+#: templates/forms.html:69 templates/list_bills.html:70
+#: templates/list_bills.html:114
msgid "delete"
msgstr ""
-#: templates/forms.html:78
+#: templates/forms.html:77
msgid "Edit this bill"
msgstr ""
-#: templates/forms.html:78
+#: templates/forms.html:77 templates/list_bills.html:94
msgid "Add a bill"
msgstr ""
+#: templates/forms.html:95
+msgid "Type user name here"
+msgstr ""
+
#: templates/forms.html:102
msgid "Send the invitations"
msgstr ""
@@ -265,35 +296,35 @@ msgstr ""
msgid "Create an archive"
msgstr ""
-#: templates/forms.html:115
+#: templates/forms.html:116
msgid "Create the archive"
msgstr ""
-#: templates/home.html:9
+#: templates/home.html:8
msgid "Manage your shared <br>expenses, easily"
msgstr ""
-#: templates/home.html:10
+#: templates/home.html:9
msgid "Try out the demo"
msgstr ""
-#: templates/home.html:13
+#: templates/home.html:12
msgid "You're sharing a house?"
msgstr ""
-#: templates/home.html:13
+#: templates/home.html:12
msgid "Going on holidays with friends?"
msgstr ""
-#: templates/home.html:13
+#: templates/home.html:12
msgid "Simply sharing money with others?"
msgstr ""
-#: templates/home.html:13
+#: templates/home.html:12
msgid "We can help!"
msgstr ""
-#: templates/home.html:26
+#: templates/home.html:24
msgid "Log to an existing project"
msgstr ""
@@ -305,107 +336,109 @@ msgstr ""
msgid "can't remember your password?"
msgstr ""
-#: templates/home.html:34
+#: templates/home.html:36
msgid "or create a new one"
msgstr ""
-#: templates/home.html:36
+#: templates/home.html:40
msgid "let's get started"
msgstr ""
+#: templates/home.html:51
+msgid ""
+"This access code will be sent to your friends. It is stored as-is by the "
+"server, so don\\'t reuse a personal password!"
+msgstr ""
+
#: templates/layout.html:5
msgid "Account manager"
msgstr ""
-#: templates/layout.html:54
+#: templates/layout.html:45 templates/settle_bills.html:4
msgid "Bills"
msgstr ""
-#: templates/layout.html:58
+#: templates/layout.html:46 templates/settle_bills.html:5
+msgid "Settle"
+msgstr ""
+
+#: templates/layout.html:53
msgid "options"
msgstr ""
-#: templates/layout.html:60
+#: templates/layout.html:55
msgid "Project settings"
msgstr ""
-#: templates/layout.html:64
+#: templates/layout.html:59
msgid "switch to"
msgstr ""
-#: templates/layout.html:67
+#: templates/layout.html:62
msgid "Start a new project"
msgstr ""
-#: templates/layout.html:69
+#: templates/layout.html:64
msgid "Logout"
msgstr ""
-#: templates/layout.html:95
+#: templates/layout.html:92
msgid "This is a free software"
msgstr ""
-#: templates/layout.html:95
+#: templates/layout.html:92
msgid "you can contribute and improve it!"
msgstr ""
-#: templates/list_bills.html:115
-msgid "Balance"
-msgstr ""
-
-#: templates/list_bills.html:140
+#: templates/list_bills.html:74
msgid "reactivate"
msgstr ""
-#: templates/list_bills.html:144
+#: templates/list_bills.html:88
msgid "The project identifier is"
msgstr ""
-#: templates/list_bills.html:144
+#: templates/list_bills.html:88
msgid "remember it!"
msgstr ""
-#: templates/list_bills.html:145
+#: templates/list_bills.html:89
msgid "Add a new bill"
msgstr ""
-#: templates/list_bills.html:148
-msgid "hide this form"
-msgstr ""
-
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "When?"
msgstr ""
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "Who paid?"
msgstr ""
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "For what?"
msgstr ""
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103 templates/settle_bills.html:31
msgid "How much?"
msgstr ""
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "Actions"
msgstr ""
-#: templates/list_bills.html:162
+#: templates/list_bills.html:111
msgid "each"
msgstr ""
-#: templates/list_bills.html:164
+#: templates/list_bills.html:113
msgid "edit"
msgstr ""
-#: templates/list_bills.html:177
+#: templates/list_bills.html:122
msgid "Nothing to list yet. You probably want to"
msgstr ""
-#: templates/list_bills.html:177
+#: templates/list_bills.html:122
msgid "add a bill"
msgstr ""
@@ -449,3 +482,11 @@ msgstr ""
msgid "and notify them yourself"
msgstr ""
+#: templates/settle_bills.html:31
+msgid "Who pays?"
+msgstr ""
+
+#: templates/settle_bills.html:31
+msgid "To whom?"
+msgstr ""
+
diff --git a/budget/models.py b/budget/models.py
index db57869..900b1d0 100644
--- a/budget/models.py
+++ b/budget/models.py
@@ -49,6 +49,53 @@ class Project(db.Model):
return balances
+ 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 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)
+ if match:
+ for m in match:
+ 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"], "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"], "receiver": 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 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().count() > 0
diff --git a/budget/templates/layout.html b/budget/templates/layout.html
index 8e6d3b2..543bcb3 100644
--- a/budget/templates/layout.html
+++ b/budget/templates/layout.html
@@ -41,7 +41,10 @@
<h1><a class="brand" href="{{ url_for(".home") }}">#! money?</a></h1>
{% if g.project %}
<ul class="nav primary-nav">
+ {% block navbar %}
<li class="active"><a href="{{ url_for(".list_bills") }}">{{ _("Bills") }}</a></li>
+ <li><a href="{{ url_for(".settle_bill") }}">{{ _("Settle") }}</a></li>
+ {% endblock %}
</ul>
{% endif %}
<ul class="nav pull-right secondary-nav">
diff --git a/budget/templates/list_bills.html b/budget/templates/list_bills.html
index 389e73f..ee97624 100644
--- a/budget/templates/list_bills.html
+++ b/budget/templates/list_bills.html
@@ -73,7 +73,7 @@
<form class="action reactivate" action="{{ url_for(".reactivate", member_id=member.id) }}" method="POST">
<button type="submit">{{ _("reactivate") }}</button></form></td>
{% endif %}
- <td class="balance-value {% if balance[member.id] > 0 %}positive{% elif balance[member.id] < 0 %}negative{% endif %}">
+ <td class="balance-value {% if balance[member] > 0 %}positive{% elif balance[member.id] < 0 %}negative{% endif %}">
{% if balance[member.id] > 0 %}+{% endif %}{{ balance[member.id] }}
</td>
</tr>
diff --git a/budget/templates/settle_bills.html b/budget/templates/settle_bills.html
new file mode 100644
index 0000000..29d9b26
--- /dev/null
+++ b/budget/templates/settle_bills.html
@@ -0,0 +1,43 @@
+{% extends "layout.html" %}
+
+{% block navbar %}
+<li><a href="{{ url_for(".list_bills") }}">{{ _("Bills") }}</a></li>
+<li class="active"><a href="{{ url_for(".settle_bill") }}">{{ _("Settle") }}</a></li>
+{% endblock %}
+
+{% block sidebar %}
+<div id="sidebar" class="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] != 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] > 0 %}positive{% elif balance[member.id] < 0 %}negative{% endif %}">
+ {% if balance[member.id] > 0 %}+{% endif %}{{ balance[member.id] }}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+
+</div>
+{% endblock %}
+
+
+{% block content %}
+ <table id="bill_table" class="split_bills table table-striped">
+ <thead><tr><th>{{ _("Who pays?") }}</th><th>{{ _("To whom?") }}</th><th>{{ _("How much?") }}</th></tr></thead>
+ <tbody>
+ {% for bill in bills %}
+ <tr class="{{ loop.cycle("odd", "even") }}" receiver={{bill.receiver.id}}>
+ <td>{{ bill.ower }}</td>
+ <td>{{ bill.receiver }}</td>
+ <td>{{ "%0.2f"|format(bill.amount) }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+
+{% endblock %}
diff --git a/budget/tests.py b/budget/tests.py
index 14e605a..9eea518 100644
--- a/budget/tests.py
+++ b/budget/tests.py
@@ -6,6 +6,7 @@ except ImportError:
import base64
import json
+from collections import defaultdict
from flask import session
@@ -21,9 +22,11 @@ class TestCase(unittest.TestCase):
run.app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///memory"
run.app.config['CSRF_ENABLED'] = False # simplify the tests
self.app = run.app.test_client()
-
- models.db.init_app(run.app)
- run.mail.init_app(run.app)
+ try:
+ models.db.init_app(run.app)
+ run.mail.init_app(run.app)
+ except:
+ pass
models.db.app = run.app
models.db.create_all()
@@ -439,7 +442,11 @@ class BudgetTestCase(TestCase):
})
balance = models.Project.query.get("raclette").balance
- self.assertDictEqual(balance, {3: -8.12, 1: 8.12, 2: 0.0})
+ result = {}
+ result[models.Project.query.get("raclette").members[0].id] = 8.12
+ result[models.Project.query.get("raclette").members[1].id] = 0.0
+ result[models.Project.query.get("raclette").members[2].id] = -8.12
+ self.assertDictEqual(balance, result)
def test_edit_project(self):
# A project should be editable
@@ -470,6 +477,58 @@ class BudgetTestCase(TestCase):
response = self.app.get("/dashboard")
self.assertEqual(response.status_code, 200)
+ def test_settle_page(self):
+ self.post_project("raclette")
+ response = self.app.get("/raclette/settle_bills")
+ self.assertEqual(response.status_code, 200)
+
+ def test_settle(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'})
+ #Add a member with a balance=0 :
+ self.app.post("/raclette/members/add", data={'name': 'toto'})
+
+ # create bills
+ self.app.post("/raclette/add", data={
+ 'date': '2011-08-10',
+ 'what': u'fromage à raclette',
+ 'payer': 1,
+ 'payed_for': [1, 2, 3],
+ 'amount': '10.0',
+ })
+
+ self.app.post("/raclette/add", data={
+ 'date': '2011-08-10',
+ 'what': u'red wine',
+ 'payer': 2,
+ 'payed_for': [1],
+ 'amount': '20',
+ })
+
+ self.app.post("/raclette/add", data={
+ 'date': '2011-08-10',
+ 'what': u'delicatessen',
+ 'payer': 1,
+ 'payed_for': [1, 2],
+ 'amount': '10',
+ })
+ project = models.Project.query.get('raclette')
+ transactions = project.get_transactions_to_settle_bill()
+ members = defaultdict(int)
+ #We should have the same values between transactions and project balances
+ for t in transactions:
+ members[t['ower']]-=t['amount']
+ members[t['receiver']]+=t['amount']
+ balance = models.Project.query.get("raclette").balance
+ for m, a in members.items():
+ self.assertEqual(a, balance[m.id])
+ return
+
+
class APITestCase(TestCase):
"""Tests the API"""
diff --git a/budget/translations/fr/LC_MESSAGES/messages.mo b/budget/translations/fr/LC_MESSAGES/messages.mo
index 563a8e4..4b71866 100644
--- a/budget/translations/fr/LC_MESSAGES/messages.mo
+++ b/budget/translations/fr/LC_MESSAGES/messages.mo
Binary files differ
diff --git a/budget/translations/fr/LC_MESSAGES/messages.po b/budget/translations/fr/LC_MESSAGES/messages.po
index ff180b8..467329e 100644
--- a/budget/translations/fr/LC_MESSAGES/messages.po
+++ b/budget/translations/fr/LC_MESSAGES/messages.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-11-20 13:49+0100\n"
+"POT-Creation-Date: 2013-05-09 22:24+0200\n"
"PO-Revision-Date: 2011-10-14 23:51+0200\n"
"Last-Translator: Quentin Roy <royque@gmail.com>\n"
"Language-Team: fr <LL@li.org>\n"
@@ -17,192 +17,199 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
-#: forms.py:20
-msgid "Select All/None"
-msgstr "Cocher Tous/Aucun"
+#: forms.py:22
+msgid "Select all"
+msgstr "Tout cocher"
-#: forms.py:57
+#: forms.py:22
+msgid "Select none"
+msgstr "Tout décocher"
+
+#: forms.py:61
msgid "Project name"
msgstr "Nom de projet"
-#: forms.py:58 forms.py:82 forms.py:93
+#: forms.py:62 forms.py:86 forms.py:102
msgid "Private code"
msgstr "Code d'accès"
-#: forms.py:59
+#: forms.py:63
msgid "Email"
msgstr "Email"
-#: forms.py:81 forms.py:92 forms.py:98
+#: forms.py:85 forms.py:101 forms.py:107
msgid "Project identifier"
msgstr "Identifiant du projet"
-#: forms.py:83 templates/send_invites.html:5
+#: forms.py:87 templates/send_invites.html:5
msgid "Create the project"
msgstr "Créer le projet"
-#: forms.py:88
+#: forms.py:92
msgid ""
"The project identifier is used to log in and for the URL of the project. "
"We tried to generate an identifier for you but a project with this "
-"identifier already exists. Please create a new identifier you will be "
-"able to remember."
+"identifier already exists. Please create a new identifier that you will "
+"be able to remember."
msgstr ""
-"L'identifiant de projet est utilisé pour se connecter et dans l'URL du "
-"projetNous avons essayé de générer une identifiant pour ce projet mais "
+"L'identifiant du projet est utilisé pour se connecter."
+"Nous avons essayé de générer un identifiant mais "
"celui ci existe déjà. Merci de créer un nouvel identifiant que vous serez"
" capable de retenir"
-#: forms.py:94
+#: forms.py:103
msgid "Get in"
msgstr "Entrer"
-#: forms.py:99
+#: forms.py:108
msgid "Send me the code by email"
msgstr "Envoyez moi le code par email"
-#: forms.py:103
+#: forms.py:112
msgid "This project does not exists"
msgstr "Ce projet n'existe pas"
-#: forms.py:107
+#: forms.py:116
msgid "Date"
msgstr "Date"
-#: forms.py:108
+#: forms.py:117
msgid "What?"
msgstr "Quoi ?"
-#: forms.py:109
+#: forms.py:118
msgid "Payer"
msgstr "Payeur"
-#: forms.py:110
+#: forms.py:119
msgid "Amount paid"
msgstr "Montant"
-#: forms.py:111 templates/list_bills.html:154
+#: forms.py:120 templates/list_bills.html:103
msgid "For whom?"
msgstr "Pour qui ?"
-#: forms.py:113
-msgid "Send the bill"
-msgstr "Enregistrer la facture"
+#: forms.py:122
+msgid "Submit"
+msgstr "Valider"
+
+#: forms.py:123
+msgid "Submit and add a new one"
+msgstr "Valider et ajouter une autre facture"
-#: forms.py:139
-#, fuzzy
+#: forms.py:149
msgid "Bills can't be null"
-msgstr "Le montant d'une facture ne peut pas être négatif"
+msgstr "Le montant d'une facture ne peut pas être nul."
-#: forms.py:144
+#: forms.py:154
msgid "Name"
msgstr "Nom"
-#: forms.py:144
-msgid "Type user name here"
-msgstr "Nouveau participant"
-
-#: forms.py:145 templates/forms.html:94
+#: forms.py:155 templates/forms.html:95
msgid "Add"
msgstr "Ajouter"
-#: forms.py:153
+#: forms.py:163
msgid "User name incorrect"
-msgstr ""
+msgstr "Nom d'utilisateur incorrect"
-#: forms.py:157
+#: forms.py:167
msgid "This project already have this member"
msgstr "Ce membre existe déjà pour ce projet"
-#: forms.py:167
+#: forms.py:178
msgid "People to notify"
msgstr "Personnes à prévenir"
-#: forms.py:168
+#: forms.py:179
msgid "Send invites"
msgstr "Envoyer les invitations"
-#: forms.py:174
+#: forms.py:185
#, python-format
msgid "The email %(email)s is not valid"
msgstr "L'email %(email)s est invalide"
-#: forms.py:179
+#: forms.py:190
+msgid "Name for this archive (optional)"
+msgstr "Nom pour cette archive (optionnel)"
+
+#: forms.py:191
msgid "Start date"
msgstr "Date de départ"
-#: forms.py:180
+#: forms.py:192
msgid "End date"
msgstr "Date de fin"
-#: forms.py:181
-msgid "Name for this archive (optional)"
-msgstr "Nom pour cette archive"
-
-#: web.py:89
+#: web.py:95
msgid "This private code is not the right one"
msgstr "Le code que vous avez entré n'est pas correct"
-#: web.py:137
+#: web.py:147
#, python-format
msgid "You have just created '%(project)s' to share your expenses"
msgstr "Vous venez de créer '%(project)s' pour partager vos dépenses"
-#: web.py:148
+#: web.py:165
#, python-format
-msgid "The project identifier is %(project)s"
+msgid "%(msg_compl)sThe project identifier is %(project)s"
msgstr "L'identifiant de ce projet est '%(project)s'"
-#: web.py:166
+#: web.py:185
msgid "a mail has been sent to you with the password"
msgstr "Un email vous a été envoyé avec le mot de passe"
-#: web.py:229
+#: web.py:211
+msgid "Project successfully deleted"
+msgstr "Projet supprimé"
+
+#: web.py:254
#, python-format
msgid "You have been invited to share your expenses for %(project)s"
msgstr "Vous avez été invité à partager vos dépenses pour %(project)s"
-#: web.py:236
+#: web.py:261
msgid "Your invitations have been sent"
msgstr "Vos invitations ont bien été envoyées"
-#: web.py:261
+#: web.py:290
#, python-format
msgid "%(member)s had been added"
msgstr "%(member)s a bien été ajouté"
-#: web.py:273
+#: web.py:303
#, python-format
msgid "%(name)s is part of this project again"
msgstr "%(name)s a rejoint le projet"
-#: web.py:281
+#: web.py:311
#, python-format
msgid "User '%(name)s' has been deactivated"
msgstr "Le membre '%(name)s' a été désactivé"
-#: web.py:283
+#: web.py:313
#, python-format
msgid "User '%(name)s' has been removed"
msgstr "Le membre '%(name)s' a été supprimé"
-#: web.py:300
+#: web.py:331
msgid "The bill has been added"
msgstr "La facture a bien été ajoutée"
-#: web.py:315
+#: web.py:351
msgid "The bill has been deleted"
msgstr "La facture a été supprimée"
-#: web.py:333
+#: web.py:369
msgid "The bill has been modified"
msgstr "La facture a été modifiée"
-#: web.py:357
+#: web.py:399
msgid "The data from XX to XX has been archived"
msgstr "Les données de XX à XX ont été archivées"
-#: templates/add_bill.html:19
+#: templates/add_bill.html:9
msgid "Back to the list"
msgstr "Retourner à la liste"
@@ -224,8 +231,27 @@ msgstr " ?"
msgid "Create a new project"
msgstr "Créer un nouveau projet"
-#: templates/edit_project.html:6 templates/list_bills.html:77
-#: templates/list_bills.html:87
+#: templates/dashboard.html:5
+msgid "Project"
+msgstr "Projets"
+
+#: templates/dashboard.html:5
+msgid "Number of members"
+msgstr "Nombre de membres"
+
+#: templates/dashboard.html:5
+msgid "Number of bills"
+msgstr "Nombre de factures"
+
+#: templates/dashboard.html:5
+msgid "Newest bill"
+msgstr "Facture la plus récente"
+
+#: templates/dashboard.html:5
+msgid "Oldest bill"
+msgstr "Facture la plus ancienne"
+
+#: templates/edit_project.html:6 templates/list_bills.html:24
msgid "you sure?"
msgstr "c'est sûr ?"
@@ -233,31 +259,35 @@ msgstr "c'est sûr ?"
msgid "Edit this project"
msgstr "Éditer ce projet"
-#: templates/forms.html:24
+#: templates/forms.html:23
msgid "Can't remember the password?"
msgstr "Vous ne vous souvenez plus du code d'accès ?"
-#: templates/forms.html:27
+#: templates/forms.html:26
msgid "Cancel"
msgstr "Annuler"
-#: templates/forms.html:69
+#: templates/forms.html:68
msgid "Edit the project"
msgstr "Éditer le projet"
-#: templates/forms.html:70 templates/list_bills.html:139
-#: templates/list_bills.html:167
+#: templates/forms.html:69 templates/list_bills.html:70
+#: templates/list_bills.html:114
msgid "delete"
msgstr "supprimer"
-#: templates/forms.html:78
+#: templates/forms.html:77
msgid "Edit this bill"
msgstr "Éditer cette facture"
-#: templates/forms.html:78
+#: templates/forms.html:77 templates/list_bills.html:94
msgid "Add a bill"
msgstr "Ajouter une facture"
+#: templates/forms.html:95
+msgid "Type user name here"
+msgstr "Nouveau participant"
+
#: templates/forms.html:102
msgid "Send the invitations"
msgstr "Envoyer les invitations"
@@ -270,35 +300,35 @@ msgstr "Non merci"
msgid "Create an archive"
msgstr "Créer une archive"
-#: templates/forms.html:115
+#: templates/forms.html:116
msgid "Create the archive"
msgstr "Créer l'archive"
-#: templates/home.html:9
+#: templates/home.html:8
msgid "Manage your shared <br>expenses, easily"
msgstr "Gérez vos dépenses<br> partagées, facilement"
-#: templates/home.html:10
+#: templates/home.html:9
msgid "Try out the demo"
msgstr "Essayez la démo"
-#: templates/home.html:13
+#: templates/home.html:12
msgid "You're sharing a house?"
msgstr "Vous êtes en colocation ?"
-#: templates/home.html:13
+#: templates/home.html:12
msgid "Going on holidays with friends?"
msgstr "Partez en vacances avec des amis ?"
-#: templates/home.html:13
+#: templates/home.html:12
msgid "Simply sharing money with others?"
msgstr "Ça vous arrive de partager de l'argent avec d'autres ?"
-#: templates/home.html:13
+#: templates/home.html:12
msgid "We can help!"
msgstr "On peut vous aider !"
-#: templates/home.html:26
+#: templates/home.html:24
msgid "Log to an existing project"
msgstr "Se connecter à un projet existant"
@@ -310,107 +340,111 @@ msgstr "se connecter"
msgid "can't remember your password?"
msgstr "vous ne vous souvenez plus du code d'accès ?"
-#: templates/home.html:34
+#: templates/home.html:36
msgid "or create a new one"
msgstr "ou créez en un nouveau"
-#: templates/home.html:36
+#: templates/home.html:40
msgid "let's get started"
msgstr "c'est parti !"
+#: templates/home.html:51
+msgid ""
+"This access code will be sent to your friends. It is stored as-is by the "
+"server, so don\\'t reuse a personal password!"
+msgstr ""
+"Ce code d'accès va être envoyé à vos amis et stocké en clair sur le "
+"serveur.N'utilisez pas un mot de passe personnel !"
+
#: templates/layout.html:5
msgid "Account manager"
msgstr "Gestion de comptes"
-#: templates/layout.html:54
+#: templates/layout.html:45 templates/settle_bills.html:4
msgid "Bills"
msgstr "Factures"
-#: templates/layout.html:58
+#: templates/layout.html:46 templates/settle_bills.html:5
+msgid "Settle"
+msgstr "Remboursements"
+
+#: templates/layout.html:53
msgid "options"
msgstr "options"
-#: templates/layout.html:60
+#: templates/layout.html:55
msgid "Project settings"
msgstr "Options du projet"
-#: templates/layout.html:64
+#: templates/layout.html:59
msgid "switch to"
msgstr "aller à"
-#: templates/layout.html:67
+#: templates/layout.html:62
msgid "Start a new project"
msgstr "Nouveau projet"
-#: templates/layout.html:69
+#: templates/layout.html:64
msgid "Logout"
msgstr "Se déconnecter"
-#: templates/layout.html:95
+#: templates/layout.html:92
msgid "This is a free software"
msgstr "Ceci est un logiciel libre"
-#: templates/layout.html:95
+#: templates/layout.html:92
msgid "you can contribute and improve it!"
msgstr "vous pouvez y contribuer et l'améliorer"
-#: templates/list_bills.html:115
-msgid "Balance"
-msgstr "Balance"
-
-#: templates/list_bills.html:140
+#: templates/list_bills.html:74
msgid "reactivate"
msgstr "ré-activer"
-#: templates/list_bills.html:144
+#: templates/list_bills.html:88
msgid "The project identifier is"
msgstr "L'identifiant de ce projet est"
-#: templates/list_bills.html:144
+#: templates/list_bills.html:88
msgid "remember it!"
msgstr "souvenez vous en !"
-#: templates/list_bills.html:145
+#: templates/list_bills.html:89
msgid "Add a new bill"
msgstr "Nouvelle facture"
-#: templates/list_bills.html:148
-msgid "hide this form"
-msgstr "cacher ce formulaire"
-
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "When?"
msgstr "Quand ?"
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "Who paid?"
msgstr "Qui a payé ?"
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "For what?"
msgstr "Pour quoi ?"
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103 templates/settle_bills.html:31
msgid "How much?"
msgstr "Combien ?"
-#: templates/list_bills.html:154
+#: templates/list_bills.html:103
msgid "Actions"
msgstr "Actions"
-#: templates/list_bills.html:162
+#: templates/list_bills.html:111
msgid "each"
msgstr "chacun"
-#: templates/list_bills.html:164
+#: templates/list_bills.html:113
msgid "edit"
msgstr "éditer"
-#: templates/list_bills.html:177
+#: templates/list_bills.html:122
msgid "Nothing to list yet. You probably want to"
msgstr "Rien à lister pour l'instant. Vous voulez surement"
-#: templates/list_bills.html:177
+#: templates/list_bills.html:122
msgid "add a bill"
msgstr "ajouter une facture"
@@ -456,3 +490,11 @@ msgstr "sauter cette étape"
msgid "and notify them yourself"
msgstr "et les notifier vous même"
+#: templates/settle_bills.html:31
+msgid "Who pays?"
+msgstr "Qui doit payer ?"
+
+#: templates/settle_bills.html:31
+msgid "To whom?"
+msgstr "Pour qui ?"
+
diff --git a/budget/web.py b/budget/web.py
index 5afd9b4..0b302cd 100644
--- a/budget/web.py
+++ b/budget/web.py
@@ -383,10 +383,11 @@ def change_lang(lang):
return redirect(request.headers.get('Referer') or url_for('.home'))
-@main.route("/<project_id>/compute")
-def compute_bills():
+@main.route("/<project_id>/settle_bills")
+def settle_bill():
"""Compute the sum each one have to pay to each other and display it"""
- return render_template("compute_bills.html")
+ bills = g.project.get_transactions_to_settle_bill()
+ return render_template("settle_bills.html", bills=bills)
@main.route("/<project_id>/archives/create", methods=["GET", "POST"])