+
{% endmacro %}
{% macro delete_project_history(form) %}
diff --git a/ihatemoney/web.py b/ihatemoney/web.py
index d9e7ec08..de5cac61 100644
--- a/ihatemoney/web.py
+++ b/ihatemoney/web.py
@@ -41,16 +41,16 @@ from ihatemoney.emails import send_creation_email
from ihatemoney.forms import (
AdminAuthenticationForm,
AuthenticationForm,
- DestructiveActionProjectForm,
+ DeleteProjectForm,
EditProjectForm,
EmptyForm,
+ ImportProjectForm,
InviteForm,
MemberForm,
PasswordReminder,
ProjectForm,
ProjectFormWithCaptcha,
ResetPasswordForm,
- UploadForm,
get_billform_for,
)
from ihatemoney.history import get_history, get_history_queries
@@ -412,17 +412,8 @@ def reset_password():
@main.route("//edit", methods=["GET", "POST"])
def edit_project():
edit_form = EditProjectForm(id=g.project.id)
- delete_form = DestructiveActionProjectForm(id=g.project.id)
- import_form = UploadForm()
- # Import form
- if import_form.validate_on_submit():
- try:
- import_project(import_form.file.data.stream, g.project)
- flash(_("Project successfully uploaded"))
-
- return redirect(url_for("main.list_bills"))
- except ValueError as e:
- flash(e.args[0], category="danger")
+ import_form = ImportProjectForm(id=g.project.id)
+ delete_form = DeleteProjectForm(id=g.project.id)
# Edit form
if edit_form.validate_on_submit():
@@ -446,108 +437,136 @@ def edit_project():
return render_template(
"edit_project.html",
edit_form=edit_form,
- delete_form=delete_form,
import_form=import_form,
+ delete_form=delete_form,
current_view="edit_project",
)
-def import_project(file, project):
- json_file = json.load(file)
+@main.route("//import", methods=["POST"])
+def import_project():
+ form = ImportProjectForm()
+ if form.validate():
+ try:
+ data = form.file.data
+ if data.mimetype == "application/json":
+ json_file = json.load(data.stream)
+ else:
+ raise ValueError("Unsupported file type")
- # Check if JSON is correct
- attr = ["what", "payer_name", "payer_weight", "amount", "currency", "date", "owers"]
- attr.sort()
- currencies = set()
- for e in json_file:
- # If currency is absent, empty, or explicitly set to XXX
- # set it to project default.
- if e.get("currency", "") in ["", "XXX"]:
- e["currency"] = project.default_currency
- if len(e) != len(attr):
- raise ValueError(_("Invalid JSON"))
- list_attr = []
- for i in e:
- list_attr.append(i)
- list_attr.sort()
- if list_attr != attr:
- raise ValueError(_("Invalid JSON"))
- # Keep track of currencies
- currencies.add(e["currency"])
+ # Check if JSON is correct
+ attr = [
+ "what",
+ "payer_name",
+ "payer_weight",
+ "amount",
+ "currency",
+ "date",
+ "owers",
+ ]
+ attr.sort()
+ currencies = set()
+ for e in json_file:
+ # If currency is absent, empty, or explicitly set to XXX
+ # set it to project default.
+ if e.get("currency", "") in ["", "XXX"]:
+ e["currency"] = g.project.default_currency
+ if len(e) != len(attr):
+ raise ValueError(_("Invalid JSON"))
+ list_attr = []
+ for i in e:
+ list_attr.append(i)
+ list_attr.sort()
+ if list_attr != attr:
+ raise ValueError(_("Invalid JSON"))
+ # Keep track of currencies
+ currencies.add(e["currency"])
- # Additional checks if project has no default currency
- if project.default_currency == CurrencyConverter.no_currency:
- # If bills have currencies, they must be consistent
- if len(currencies - {CurrencyConverter.no_currency}) >= 2:
- raise ValueError(
- _(
- "Cannot add bills in multiple currencies to a project without default currency"
- )
+ # Additional checks if project has no default currency
+ if g.project.default_currency == CurrencyConverter.no_currency:
+ # If bills have currencies, they must be consistent
+ if len(currencies - {CurrencyConverter.no_currency}) >= 2:
+ raise ValueError(
+ _(
+ "Cannot add bills in multiple currencies to a project without default currency"
+ )
+ )
+ # Strip currency from bills (since it's the same for every bill)
+ for e in json_file:
+ e["currency"] = CurrencyConverter.no_currency
+
+ # From json : export list of members
+ members_json = get_members(json_file)
+ members = g.project.members
+ members_already_here = list()
+ for m in members:
+ members_already_here.append(str(m))
+
+ # List all members not in the project and weight associated
+ # List of tuples (name,weight)
+ members_to_add = list()
+ for i in members_json:
+ if str(i[0]) not in members_already_here:
+ members_to_add.append(i)
+
+ # List bills not in the project
+ # Same format than JSON element
+ project_bills = g.project.get_pretty_bills()
+ bill_to_add = list()
+ for j in json_file:
+ same = False
+ for p in project_bills:
+ if same_bill(p, j):
+ same = True
+ break
+ if not same:
+ bill_to_add.append(j)
+
+ # Add users to DB
+ for m in members_to_add:
+ Person(name=m[0], project=g.project, weight=m[1])
+ db.session.commit()
+
+ id_dict = {}
+ for i in g.project.members:
+ id_dict[i.name] = i.id
+
+ # Create bills
+ for b in bill_to_add:
+ owers_id = list()
+ for ower in b["owers"]:
+ owers_id.append(id_dict[ower])
+
+ bill = Bill()
+ form = get_billform_for(g.project)
+ form.what = b["what"]
+ form.amount = b["amount"]
+ form.original_currency = b["currency"]
+ form.date = parse(b["date"])
+ form.payer = id_dict[b["payer_name"]]
+ form.payed_for = owers_id
+
+ db.session.add(form.fake_form(bill, g.project))
+
+ # Add bills to DB
+ db.session.commit()
+ flash(_("Project successfully uploaded"))
+ return redirect(url_for("main.list_bills"))
+ except ValueError as e:
+ flash(e.args[0], category="danger")
+ return render_template(
+ "edit_project.html",
+ current_view="edit_project",
)
- # Strip currency from bills (since it's the same for every bill)
- for e in json_file:
- e["currency"] = CurrencyConverter.no_currency
-
- # From json : export list of members
- members_json = get_members(json_file)
- members = project.members
- members_already_here = list()
- for m in members:
- members_already_here.append(str(m))
-
- # List all members not in the project and weight associated
- # List of tuples (name,weight)
- members_to_add = list()
- for i in members_json:
- if str(i[0]) not in members_already_here:
- members_to_add.append(i)
-
- # List bills not in the project
- # Same format than JSON element
- project_bills = project.get_pretty_bills()
- bill_to_add = list()
- for j in json_file:
- same = False
- for p in project_bills:
- if same_bill(p, j):
- same = True
- break
- if not same:
- bill_to_add.append(j)
-
- # Add users to DB
- for m in members_to_add:
- Person(name=m[0], project=project, weight=m[1])
- db.session.commit()
-
- id_dict = {}
- for i in project.members:
- id_dict[i.name] = i.id
-
- # Create bills
- for b in bill_to_add:
- owers_id = list()
- for ower in b["owers"]:
- owers_id.append(id_dict[ower])
-
- bill = Bill()
- form = get_billform_for(project)
- form.what = b["what"]
- form.amount = b["amount"]
- form.original_currency = b["currency"]
- form.date = parse(b["date"])
- form.payer = id_dict[b["payer_name"]]
- form.payed_for = owers_id
-
- db.session.add(form.fake_form(bill, project))
-
- # Add bills to DB
- db.session.commit()
+ else:
+ for component, errors in form.errors.items():
+ flash(_(component + ": ") + ", ".join(errors), category="danger")
+ return redirect(url_for(".edit_project"))
@main.route("//delete", methods=["POST"])
def delete_project():
- form = DestructiveActionProjectForm(id=g.project.id)
+ form = DeleteProjectForm(id=g.project.id)
if form.validate():
g.project.remove_project()
flash(_("Project successfully deleted"))
@@ -838,7 +857,7 @@ def history():
any_ip_addresses = any(event["ip"] for event in history)
- delete_form = DestructiveActionProjectForm()
+ delete_form = DeleteProjectForm()
return render_template(
"history.html",
current_view="history",
@@ -854,7 +873,7 @@ def history():
@main.route("//erase_history", methods=["POST"])
def erase_history():
"""Erase all history entries associated with this project."""
- form = DestructiveActionProjectForm(id=g.project.id)
+ form = DeleteProjectForm(id=g.project.id)
if not form.validate():
flash(
format_form_errors(form, _("Error deleting project history")),
@@ -873,7 +892,7 @@ def erase_history():
@main.route("//strip_ip_addresses", methods=["POST"])
def strip_ip_addresses():
"""Strip ip addresses from history entries associated with this project."""
- form = DestructiveActionProjectForm(id=g.project.id)
+ form = DeleteProjectForm(id=g.project.id)
if not form.validate():
flash(
format_form_errors(form, _("Error deleting recorded IP addresses")),