aboutsummaryrefslogtreecommitdiff
path: root/budget
diff options
context:
space:
mode:
Diffstat (limited to 'budget')
-rw-r--r--budget/models.py26
-rw-r--r--budget/templates/compute_bills.html11
-rw-r--r--budget/templates/list_bills.html18
-rw-r--r--budget/web.py38
4 files changed, 63 insertions, 30 deletions
diff --git a/budget/models.py b/budget/models.py
index bf9ad92..efb5a3d 100644
--- a/budget/models.py
+++ b/budget/models.py
@@ -1,3 +1,5 @@
+from collections import defaultdict
+
from datetime import datetime
from flaskext.sqlalchemy import SQLAlchemy
@@ -12,6 +14,28 @@ class Project(db.Model):
contact_email = db.Column(db.String)
members = db.relationship("Person", backref="project")
+ @property
+ def active_members(self):
+ return [m for m in self.members if m.activated]
+
+ def get_balance(self):
+
+ balances, should_pay, should_receive = defaultdict(int), defaultdict(int), defaultdict(int)
+
+ # for each person
+ for person in self.members:
+ # get the list of bills he has to pay
+ bills = Bill.query.filter(Bill.owers.contains(person))
+ for bill in bills.all():
+ if person != bill.payer:
+ should_pay[person] += bill.pay_each()
+ should_receive[bill.payer] += bill.pay_each()
+
+ for person in self.members:
+ balances[person] = should_receive[person] - should_pay[person]
+
+ return balances
+
def __repr__(self):
return "<Project %s>" % self.name
@@ -22,7 +46,7 @@ class Person(db.Model):
bills = db.relationship("Bill", backref="payer")
name = db.Column(db.UnicodeText)
- # activated = db.Column(db.Boolean, default=True)
+ activated = db.Column(db.Boolean, default=True)
def __str__(self):
return self.name
diff --git a/budget/templates/compute_bills.html b/budget/templates/compute_bills.html
index 8f286cf..4c6fd56 100644
--- a/budget/templates/compute_bills.html
+++ b/budget/templates/compute_bills.html
@@ -1,4 +1,9 @@
{% extends "layout.html" %}
+
+{% block top_menu %}
+<a href="{{ url_for('list_bills', project_id=project.id) }}">Back to the list</a>
+{% endblock %}
+
{% block content %}
<h2>Computations</h2>
@@ -12,14 +17,14 @@
</div>
<div class="container span-6 last">
- <a class="awesome large green button" onclick = "if (! confirm('Are you sure ?')) return false;" href="{{ url_for("reset_bills") }}">Mark this as payed / processed</a>
+ <a class="awesome large green button" onclick = "if (! confirm('Are you sure ?')) return false;" href="">Mark this as payed / processed</a>
</div>
<table>
<thead><tr><th>Name</th><th>Balance</th></tr></thead>
<tbody>
-{% for name, balance in balances.items() %}
- <tr><td>{{ name }}</td><td>{{ balance }}</td></tr>
+{% for person, balance in balances.items() %}
+ <tr><td>{{ person.name }}</td><td>{{ balance }}</td></tr>
{% endfor %}
</tbody>
</table>
diff --git a/budget/templates/list_bills.html b/budget/templates/list_bills.html
index a26dccc..48308fe 100644
--- a/budget/templates/list_bills.html
+++ b/budget/templates/list_bills.html
@@ -7,16 +7,22 @@
{% endblock %}
{% block content %}
-<div id="leftmenu" class="span-6">
+<div id="leftmenu" class="span-4">
<ul>
- {% for member in project.members %}
- <li>{{ member.name }}</li>
+ {% set balance = project.get_balance() %}
+ {% for member in project.active_members %}
+ <li> {{ member.name }} {{ balance[member] }} <a href="{{ url_for("remove_member", project_id=project.id, member_id=member.id) }}">x</a></li>
{% endfor %}
</ul>
- {% set form=member_form %}
- {% include "member_form.html" %}
+ <form action="{{ url_for("add_member", project_id=project.id) }}" method="post">
+ {{ forms.add_member(member_form) }}
+ </form>
</div>
-<div id="content" class="span-18 last">
+<div id="content" class="uniForm span-20 last">
+ <form id="add_bill" action="{{ url_for('add_bill', project_id=project.id) }}" method="post" style="width: 400px; display: none">
+ {{ forms.add_bill(bill_form) }}
+ </form>
+
{% if bills.count() > 0 %}
<table>
<thead><tr><th>When ?</th><th>Who paid?</th><th>for what ?</th><th>Owers</th><th>How much ?</th><th>Actions</th></tr></thead>
diff --git a/budget/web.py b/budget/web.py
index 1afb8c1..c2909bc 100644
--- a/budget/web.py
+++ b/budget/web.py
@@ -1,3 +1,5 @@
+from collections import defaultdict
+
from flask import (Flask, session, request, redirect, url_for, render_template,
flash)
from flaskext.mail import Mail, Message
@@ -107,7 +109,10 @@ def list_bills(project):
# FIXME filter to only get the bills for this particular project
bills = Bill.query.order_by(Bill.id.asc())
return render_template("list_bills.html",
- bills=bills, project=project, member_form=MemberForm(project))
+ bills=bills, project=project,
+ member_form=MemberForm(project),
+ bill_form=get_billform_for(project)
+ )
@app.route("/<string:project_id>/members/add", methods=["GET", "POST"])
@requires_auth
@@ -121,10 +126,20 @@ def add_member(project):
return redirect(url_for("list_bills", project_id=project.id))
return render_template("add_member.html", form=form, project=project)
+@app.route("/<string:project_id>/members/<int:member_id>/delete", methods=["GET", "POST"])
+@requires_auth
+def remove_member(project, member_id):
+ person = Person.query.get_or_404(member_id)
+ if person.project == project:
+ person.activated = False
+ db.session.commit()
+ flash("%s has been removed" % person.name)
+ return redirect(url_for("list_bills", project_id=project.id))
+
@app.route("/<string:project_id>/add", methods=["GET", "POST"])
@requires_auth
def add_bill(project):
- form = get_billform_for(project.id)
+ form = get_billform_for(project)
if request.method == 'POST':
if form.validate():
db.session.add(form.save())
@@ -140,24 +155,7 @@ def add_bill(project):
@requires_auth
def compute_bills(project):
"""Compute the sum each one have to pay to each other and display it"""
- # FIXME make it work
-
- balances, should_pay, should_receive = {}, {}, {}
- # for each person, get the list of should_pay other have for him
- for name, void in PAYER_CHOICES:
- bills = Bill.query.join(BillOwer).filter(Bill.processed==False)\
- .filter(BillOwer.name==name)
- for bill in bills.all():
- if name != bill.payer:
- should_pay.setdefault(name, 0)
- should_pay[name] += bill.pay_each()
- should_receive.setdefault(bill.payer, 0)
- should_receive[bill.payer] += bill.pay_each()
-
- for name, void in PAYER_CHOICES:
- balances[name] = should_receive.get(name, 0) - should_pay.get(name, 0)
-
- return render_template("compute_bills.html", balances=balances, project=project)
+ return render_template("compute_bills.html", project=project)
@app.route("/<string:project_id>/reset")