From a300db98453edd4fdcedf543b42174d654e76140 Mon Sep 17 00:00:00 2001 From: Alexis Lahouze Date: Tue, 3 Dec 2013 23:01:17 +0100 Subject: [PATCH] Cleaned up session management. --- api/controller/accounts.py | 129 +++++++++++-------------- api/controller/entries.py | 71 +++++--------- api/controller/scheduled_operations.py | 73 ++++++-------- api/model/__init__.py | 24 ++--- 4 files changed, 119 insertions(+), 178 deletions(-) diff --git a/api/controller/accounts.py b/api/controller/accounts.py index 15392fe..be78c76 100644 --- a/api/controller/accounts.py +++ b/api/controller/accounts.py @@ -15,7 +15,7 @@ along with Accountant. If not, see . """ from .. import api -from ..model import db +from ..model import db, session_scope from ..model.accounts import Account from ..model.entries import Entry from ..model.operations import Operation @@ -27,116 +27,95 @@ def get_accounts(): """ Returns accounts with their solds. """ - session = db.session + with session_scope() as session: + query = session.query( + Account.id.label("id"), + Account.name.label("name"), + Account.authorized_overdraft.label("authorized_overdraft"), + func.sum(Entry.value).label("future"), + func.sum(case([(Entry.pointed, Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("pointed"), + func.sum(case([(Entry.operation_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current") + ).outerjoin(Entry).group_by(Account.id).order_by(Account.id) - query = session.query( - Account.id.label("id"), - Account.name.label("name"), - Account.authorized_overdraft.label("authorized_overdraft"), - func.sum(Entry.value).label("future"), - func.sum(case([(Entry.pointed, Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("pointed"), - func.sum(case([(Entry.operation_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current") - ).outerjoin(Entry).group_by(Account.id).order_by(Account.id) - - return json.dumps([{ - "id": i.id, - "name": i.name, - "authorized_overdraft": i.authorized_overdraft, - "current": str(i.current), - "pointed": str(i.pointed), - "future": str(i.future) - } for i in query.all()]) + return json.dumps([{ + "id": i.id, + "name": i.name, + "authorized_overdraft": i.authorized_overdraft, + "current": str(i.current), + "pointed": str(i.pointed), + "future": str(i.future) + } for i in query.all()]) @api.route("/accounts////") def get_account_status(account_id, year, month): - session = db.session + with session_scope() as session: + query = session.query( + func.sum(case([(func.sign(Operation.value) == -1, Operation.value)], else_=0)).label("expenses"), + func.sum(case([(func.sign(Operation.value) == 1, Operation.value)], else_=0)).label("revenues"), + func.sum(Operation.value).label("balance") + ).filter( + Operation.account_id == account_id + ).filter( + func.date_trunc('month', Operation.operation_date) == "%s-%s-01" % (year, month) + ).group_by(Operation.account_id) - query = session.query( - func.sum(case([(func.sign(Operation.value) == -1, Operation.value)], else_=0)).label("expenses"), - func.sum(case([(func.sign(Operation.value) == 1, Operation.value)], else_=0)).label("revenues"), - func.sum(Operation.value).label("balance") - ).filter( - Operation.account_id == account_id - ).filter( - func.date_trunc('month', Operation.operation_date) == "%s-%s-01" % (year, month) - ).group_by(Operation.account_id) + if query.count() == 1: + result = query.one() + revenues = result.revenues + expenses = result.expenses + balance = result.balance + else: + revenues = 0.0 + expenses = 0.0 + balance = 0.0 - if query.count() == 1: - result = query.one() - revenues = result.revenues - expenses = result.expenses - balance = result.balance - else: - revenues = 0.0 - expenses = 0.0 - balance = 0.0 - - return json.dumps({ - "expenses": str(expenses), - "revenues": str(revenues), - "balance": str(balance) - }) + return json.dumps({ + "expenses": str(expenses), + "revenues": str(revenues), + "balance": str(balance) + }) @api.route("/accounts//months") def get_months(account_id): - session = db.session + with session_scope() as session: + query = session.query( + distinct(func.lpad(cast(extract("year", Entry.operation_date), db.String), 4, '0')).label("year"), + func.lpad(cast(extract("month", Entry.operation_date), db.String), 2, '0').label("month") + ).filter(Entry.account_id == account_id).order_by("year", "month") - query = session.query( - distinct(func.lpad(cast(extract("year", Entry.operation_date), db.String), 4, '0')).label("year"), - func.lpad(cast(extract("month", Entry.operation_date), db.String), 2, '0').label("month") - ).filter(Entry.account_id == account_id).order_by("year", "month") - - return json.dumps([{ - "year": i.year, - "month": i.month.rjust(2, '0') - } for i in query.all()]) + return json.dumps([{ + "year": i.year, + "month": i.month.rjust(2, '0') + } for i in query.all()]) @api.route("/accounts", methods=["PUT"]) def add_account(): - session = db.session - - try: + with session_scope() as session: account = Account(request.json['name'], request.json['authorized_overdraft']) session.add(account) - session.commit() return json.dumps("Account added.") - except: - session.rollback() - raise @api.route("/accounts/", methods=["PUT"]) def update_account(account_id): - session = db.session - - try: + with session_scope() as session: account = session.query(Account).filter(Account.id == account_id).first() account.name = request.json['name'] account.authorized_overdraft = request.json['authorized_overdraft'] session.merge(account) - session.commit() return json.dumps("Account #%s updated." % account_id) - except: - session.rollback() - raise @api.route("/accounts/", methods=["DELETE"]) def delete_account(account_id): - session = db.session - - try: + with session_scope() as session: account = session.query(Account).filter(Account.id == account_id).first() session.delete(account) - session.commit() return json.dumps("Account #%s deleted." % account_id) - except: - session.rollback() - raise diff --git a/api/controller/entries.py b/api/controller/entries.py index c4351cd..d23cbac 100644 --- a/api/controller/entries.py +++ b/api/controller/entries.py @@ -15,7 +15,7 @@ along with Accountant. If not, see . """ from .. import api -from ..model import db +from ..model import db, session_scope from ..model.entries import Entry from ..model.operations import Operation from ..model.scheduled_operations import ScheduledOperation @@ -30,37 +30,34 @@ def get_entries(account_id, year, month): """ Return entries for an account, year, and month. """ - session = db.session + with session_scope() as session: + base_query = session.query( + Operation, + case(whens={Operation.canceled: None}, else_=func.sum(Operation.value).over(partition_by="canceled", order_by="operation_date, value desc, label desc")).label("sold") + ).filter(Operation.account_id == account_id).order_by( + desc(Operation.operation_date), + Operation.value, + Operation.label, + ).subquery() - base_query = session.query( - Operation, - case(whens={Operation.canceled: None}, else_=func.sum(Operation.value).over(partition_by="canceled", order_by="operation_date, value desc, label desc")).label("sold") - ).filter(Operation.account_id == account_id).order_by( - desc(Operation.operation_date), - Operation.value, - Operation.label, - ).subquery() + query = session.query(base_query).select_from(base_query).filter(func.date_trunc('month', base_query.c.operation_date) == "%s-%s-01" % (year, month)) - query = session.query(base_query).select_from(base_query).filter(func.date_trunc('month', base_query.c.operation_date) == "%s-%s-01" % (year, month)) - - return json.dumps([{ - "id": i.id, - "pointed": i.pointed, - "operation_date": i.operation_date.strftime("%Y-%m-%d"), - "label": i.label, - "value": str(i.value), - "category": i.category, - "sold": str(i.sold) if not i.canceled else None, - "account_id": i.account_id, - "canceled": i.canceled, - "scheduled_operation_id": i.scheduled_operation_id - } for i in query.all()]) + return json.dumps([{ + "id": i.id, + "pointed": i.pointed, + "operation_date": i.operation_date.strftime("%Y-%m-%d"), + "label": i.label, + "value": str(i.value), + "category": i.category, + "sold": str(i.sold) if not i.canceled else None, + "account_id": i.account_id, + "canceled": i.canceled, + "scheduled_operation_id": i.scheduled_operation_id + } for i in query.all()]) @api.route("/entries", methods=["PUT"]) def add_entry(): - session = db.session - - try: + with session_scope() as session: entry = Entry( operation_date = request.json['operation_date'], pointed = request.json['pointed'], @@ -72,18 +69,12 @@ def add_entry(): ) session.add(entry) - session.commit() return json.dumps("Entry added.") - except: - session.rollback() - raise @api.route("/entries/", methods=["PUT"]) def update_entry(entry_id): - session = db.session - - try: + with session_scope() as session: entry = session.query(Entry).filter(Entry.id == entry_id).first() entry.id = entry_id @@ -96,25 +87,15 @@ def update_entry(entry_id): entry.scheduled_operation_id = request.json['scheduled_operation_id'] session.merge(entry) - session.commit() return json.dumps("Entry #%s updated." % entry_id) - except: - session.rollback() - raise @api.route("/entries/", methods=["DELETE"]) def delete_entry(entry_id): - session = db.session - - try: + with session_scope() as session: entry = session.query(Entry).filter(Entry.id == entry_id).first() session.delete(entry) - session.commit() return json.dumps("Entry #%s deleted." % entry_id) - except: - session.rollback() - raise diff --git a/api/controller/scheduled_operations.py b/api/controller/scheduled_operations.py index ece482e..f69148e 100644 --- a/api/controller/scheduled_operations.py +++ b/api/controller/scheduled_operations.py @@ -1,5 +1,5 @@ from .. import api -from ..model import db +from ..model import db, session_scope from ..model.scheduled_operations import ScheduledOperation from flask import json, request from sqlalchemy import func, desc @@ -12,37 +12,34 @@ def get_scheduled_operations(account_id): """ Return entries for an account, year, and month. """ - session = db.session + with session_scope() as session: + query = session.query( + ScheduledOperation + ).select_from( + session.query(ScheduledOperation) + .filter(ScheduledOperation.account_id == account_id) + .order_by( + desc(ScheduledOperation.day), + ScheduledOperation.value, + ScheduledOperation.label, + ).subquery() + ) - query = session.query( - ScheduledOperation - ).select_from( - session.query(ScheduledOperation) - .filter(ScheduledOperation.account_id == account_id) - .order_by( - desc(ScheduledOperation.day), - ScheduledOperation.value, - ScheduledOperation.label, - ).subquery() - ) - - return json.dumps([{ - "id": i.id, - "start_date": i.start_date.strftime("%Y-%m-%d"), - "stop_date": i.stop_date.strftime("%Y-%m-%d"), - "day": str(i.day), - "frequency": str(i.frequency), - "label": i.label, - "value": str(i.value), - "category": i.category, - "account_id": i.account_id - } for i in query.all()]) + return json.dumps([{ + "id": i.id, + "start_date": i.start_date.strftime("%Y-%m-%d"), + "stop_date": i.stop_date.strftime("%Y-%m-%d"), + "day": str(i.day), + "frequency": str(i.frequency), + "label": i.label, + "value": str(i.value), + "category": i.category, + "account_id": i.account_id + } for i in query.all()]) @api.route("/scheduled_operations", methods=["PUT"]) def add_scheduled_operation(): - session = db.session - - try: + with session_scope() as session: scheduledOperation = ScheduledOperation( start_date = request.json['start_date'], stop_date = request.json['stop_date'], @@ -55,18 +52,12 @@ def add_scheduled_operation(): ) session.add(scheduledOperation) - session.commit() return json.dumps("Scheduled operation added.") - except: - session.rollback() - raise @api.route("/scheduled_operations/", methods=["PUT"]) def update_scheduled_operation(scheduled_operation_id): - session = db.session - - try: + with session_scope() as session: scheduledOperation = session.query(ScheduledOperation).filter(ScheduledOperation.id == scheduled_operation_id).first() scheduledOperation.id = scheduled_operation_id @@ -80,25 +71,15 @@ def update_scheduled_operation(scheduled_operation_id): scheduledOperation.account_id = request.json['account_id'] session.merge(scheduledOperation) - session.commit() return json.dumps("Scheduled operation #%s updated." % scheduled_operation_id) - except: - session.rollback() - raise @api.route("/scheduled_operations/", methods=["DELETE"]) def delete_scheduled_operation(scheduled_operation_id): - session = db.session - - try: + with session_scope() as session: scheduledOperation = session.query(ScheduledOperation).filter(ScheduledOperation.id == scheduled_operation_id).first() session.delete(scheduledOperation) - session.commit() return json.dumps("Scheduled operation #%s deleted." % scheduled_operation_id) - except: - session.rollback() - raise diff --git a/api/model/__init__.py b/api/model/__init__.py index d54dbd0..58959f2 100644 --- a/api/model/__init__.py +++ b/api/model/__init__.py @@ -6,19 +6,19 @@ from sqlalchemy.orm import scoped_session, sessionmaker db = SQLAlchemy() @contextmanager -def session_scope(engine): - if engine: - session = scoped_session(sessionmaker(autocommit = False, autoflush = False, bind = engine)) - #Base.query = session.query_property() +def session_scope(): + #session = scoped_session(sessionmaker(autocommit = False, autoflush = False, bind = engine)) + session = db.session + #Base.query = session.query_property() - try: - yield session - session.commit() - except: - session.rollback() - raise - finally: - session.close() + try: + yield session + session.commit() + except: + session.rollback() + raise + finally: + session.close() import pkgutil