aboutsummaryrefslogtreecommitdiff
path: root/ihatemoney/web.py
diff options
context:
space:
mode:
authorNicolas Vanvyve <NVanvyve@users.noreply.github.com>2020-01-13 21:17:55 +0100
committerGlandos <bugs-github@antipoul.fr>2020-01-13 21:17:55 +0100
commit9aa7e62d0f77f27590dac1cae5603e8f7efb891f (patch)
treefdccec64b145d2600a18f300bfec5891acd5fc73 /ihatemoney/web.py
parent73a4d139fffe3fdbabd0a47839eacc9964810066 (diff)
downloadihatemoney-mirror-9aa7e62d0f77f27590dac1cae5603e8f7efb891f.zip
ihatemoney-mirror-9aa7e62d0f77f27590dac1cae5603e8f7efb891f.tar.gz
ihatemoney-mirror-9aa7e62d0f77f27590dac1cae5603e8f7efb891f.tar.bz2
Import previously exported json data (#518)
Fix #417 * New tab upload * Extract data from JSON * Add users * Black format * Try to add bill * Import bills * Add french translation msg * Black reformat missing * Deactivated users are supported * Test import * Remove temp file in upload_json() * Incomplete tests * tests import * Update ihatemoney/translations/fr/LC_MESSAGES/messages.po Co-Authored-By: Rémy HUBSCHER <hubscher.remy@gmail.com> * Remove useless variable and check json format * Use String.IO and test for wrong json * Remove coma Co-authored-by: Rémy HUBSCHER <hubscher.remy@gmail.com>
Diffstat (limited to 'ihatemoney/web.py')
-rw-r--r--ihatemoney/web.py105
1 files changed, 98 insertions, 7 deletions
diff --git a/ihatemoney/web.py b/ihatemoney/web.py
index fc12e9d..be39feb 100644
--- a/ihatemoney/web.py
+++ b/ihatemoney/web.py
@@ -8,8 +8,12 @@ Basically, this blueprint takes care of the authentication and provides
some shortcuts to make your life better when coding (see `pull_project`
and `add_project_id` for a quick overview)
"""
-
+import json
import os
+from functools import wraps
+from smtplib import SMTPRecipientsRefused
+
+from dateutil.parser import parse
from flask import (
abort,
Blueprint,
@@ -24,15 +28,12 @@ from flask import (
send_file,
send_from_directory,
)
-from flask_mail import Message
from flask_babel import get_locale, gettext as _
-from werkzeug.security import check_password_hash, generate_password_hash
-from smtplib import SMTPRecipientsRefused
-from werkzeug.exceptions import NotFound
+from flask_mail import Message
from sqlalchemy import orm
-from functools import wraps
+from werkzeug.exceptions import NotFound
+from werkzeug.security import check_password_hash, generate_password_hash
-from ihatemoney.models import db, Project, Person, Bill
from ihatemoney.forms import (
AdminAuthenticationForm,
AuthenticationForm,
@@ -43,12 +44,16 @@ from ihatemoney.forms import (
ResetPasswordForm,
ProjectForm,
get_billform_for,
+ UploadForm,
)
+from ihatemoney.models import db, Project, Person, Bill
from ihatemoney.utils import (
Redirect303,
list_of_dicts2json,
list_of_dicts2csv,
LoginThrottler,
+ get_members,
+ same_bill,
)
main = Blueprint("main", __name__)
@@ -391,6 +396,92 @@ def edit_project():
)
+@main.route("/<project_id>/upload_json", methods=["GET", "POST"])
+def upload_json():
+ form = UploadForm()
+ if form.validate_on_submit():
+ try:
+ import_project(form.file.data.stream, g.project)
+ flash(_("Project successfully uploaded"))
+ except ValueError:
+ flash(_("Invalid JSON"), category="error")
+ return redirect(url_for("main.list_bills"))
+
+ return render_template("upload_json.html", form=form)
+
+
+def import_project(file, project):
+ json_file = json.load(file)
+
+ # Check if JSON is correct
+ attr = ["what", "payer_name", "payer_weight", "amount", "date", "owers"]
+ attr.sort()
+ for e in json_file:
+ if len(e) != len(attr):
+ raise ValueError
+ list_attr = []
+ for i in e:
+ list_attr.append(i)
+ list_attr.sort()
+ if list_attr != attr:
+ raise ValueError
+
+ # 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.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()
+
+
@main.route("/<project_id>/delete")
def delete_project():
g.project.remove_project()