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 "" % 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 %} +Back to the list +{% endblock %} + {% block content %}

Computations

@@ -12,14 +17,14 @@
- Mark this as payed / processed + Mark this as payed / processed
-{% for name, balance in balances.items() %} - +{% for person, balance in balances.items() %} + {% endfor %}
NameBalance
{{ name }}{{ balance }}
{{ person.name }}{{ balance }}
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 %} -
+
    - {% for member in project.members %} -
  • {{ member.name }}
  • + {% set balance = project.get_balance() %} + {% for member in project.active_members %} +
  • {{ member.name }} {{ balance[member] }} x
  • {% endfor %}
- {% set form=member_form %} - {% include "member_form.html" %} +
+ {{ forms.add_member(member_form) }} +
-
+
+ + {% if bills.count() > 0 %} 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("//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("//members//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("//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("//reset")
When ?Who paid?for what ?OwersHow much ?Actions