1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/ihatemoney_ynh.git synced 2024-09-03 19:26:15 +02:00

Merge pull request #96 from aavenel/master

New feature : Settle the bill
This commit is contained in:
Alexis Metaireau 2013-05-09 18:32:55 -07:00
commit a71d249e6c
9 changed files with 471 additions and 235 deletions

View file

@ -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."
msgstr ""
#: forms.py:94
msgid "Get in"
msgstr ""
#: forms.py:99
msgid "Send me the code by email"
"identifier already exists. Please create a new identifier that you will "
"be able to remember."
msgstr ""
#: forms.py:103
msgid "This project does not exists"
msgstr ""
#: forms.py:107
msgid "Date"
msgid "Get in"
msgstr ""
#: forms.py:108
msgid "Send me the code by email"
msgstr ""
#: forms.py:112
msgid "This project does not exists"
msgstr ""
#: forms.py:116
msgid "Date"
msgstr ""
#: 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
#: forms.py:123
msgid "Submit and add a new one"
msgstr ""
#: forms.py:149
msgid "Bills can't be null"
msgstr ""
#: forms.py:144
#: forms.py:154
msgid "Name"
msgstr ""
#: forms.py:144
msgid "Type user name here"
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"
msgstr ""
#: forms.py:180
msgid "End date"
msgstr ""
#: forms.py:181
#: forms.py:190
msgid "Name for this archive (optional)"
msgstr ""
#: web.py:89
#: forms.py:191
msgid "Start date"
msgstr ""
#: forms.py:192
msgid "End date"
msgstr ""
#: 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 ""

View file

@ -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

View file

@ -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">

View file

@ -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>

View file

@ -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 %}

View file

@ -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"""

View file

@ -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:139
#, fuzzy
#: forms.py:123
msgid "Submit and add a new one"
msgstr "Valider et ajouter une autre facture"
#: 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 ?"

View file

@ -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"])