Move queries in models.

This commit is contained in:
Alexis Lahouze 2015-06-06 23:35:31 +02:00
parent e1b5d8be43
commit c411ce5328
7 changed files with 124 additions and 75 deletions

View File

@ -14,8 +14,12 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
from sqlalchemy import func, case, cast
from accountant import db
from .entries import Entry
class Account(db.Model):
id = db.Column(db.Integer, primary_key=True)
@ -25,3 +29,18 @@ class Account(db.Model):
def __init__(self, name, authorized_overdraft):
self.name = name
self.authorized_overdraft = authorized_overdraft
@classmethod
def get_accounts(cls, session):
query = session.query(
cls.id.label("id"),
cls.name.label("name"),
cls.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(cls.id).order_by(cls.id)
return query

View File

@ -14,10 +14,9 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
from accountant import db
from .accounts import Account
from .scheduled_operations import ScheduledOperation
from sqlalchemy import distinct, func, cast, extract
from accountant import db
class Entry(db.Model):
@ -30,9 +29,9 @@ class Entry(db.Model):
scheduled_operation_id = db.Column(db.Integer,
db.ForeignKey('scheduled_operation.id'))
account = db.relationship(Account, backref=db.backref('entry',
lazy="dynamic"))
scheduled_operation = db.relationship(ScheduledOperation,
account = db.relationship("Account", backref=db.backref('entry',
lazy="dynamic"))
scheduled_operation = db.relationship("ScheduledOperation",
backref=db.backref('entry',
lazy="dynamic"))
@ -47,3 +46,19 @@ class Entry(db.Model):
self.account_id = account_id
self.category = category
self.scheduled_operation_id = scheduled_operation_id
@classmethod
def get_months_for_account(cls, session, account):
if isinstance(account, int) or isinstance(account, str):
account_id = account
else:
account_id = account.id
query = session.query(
distinct(func.lpad(cast(extract("year", cls.operation_date),
db.String), 4, '0')).label("year"),
func.lpad(cast(extract("month", cls.operation_date),
db.String), 2, '0').label("month")
).filter(cls.account_id == account_id).order_by("year", "month")
return query

View File

@ -14,6 +14,8 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
from sqlalchemy import func, case, desc
from accountant import db
from .accounts import Account
@ -44,3 +46,52 @@ class Operation(db.Model):
self.value = value
self.account_id = account_id
self.category = category
@classmethod
def get_for_account_and_month(cls, session, account, year, month):
if isinstance(account, int) or isinstance(account, str):
account_id = account
else:
account_id = account.id
base_query = session.query(
cls,
case(
whens={cls.canceled: None},
else_=func.sum(cls.value).over(
partition_by="canceled",
order_by=["operation_date", desc("value"), desc("label")])
).label("sold")
).filter(cls.account_id == account_id).order_by(
desc(cls.operation_date),
cls.value,
cls.label,
).subquery()
query = session.query(base_query).select_from(base_query)
query = query.filter(func.date_trunc(
'month', base_query.c.operation_date) == "%s-%s-01" % (year, month))
return query
@classmethod
def get_account_status(cls, session, account, year, month):
if isinstance(account, int) or isinstance(account, str):
account_id = account
else:
account_id = account.id
query = session.query(
func.sum(case([(func.sign(cls.value) == -1, cls.value)],
else_=0)).label("expenses"),
func.sum(case([(func.sign(cls.value) == 1, cls.value)],
else_=0)).label("revenues"),
func.sum(cls.value).label("balance")
).filter(
cls.account_id == account_id
).filter(
func.date_trunc('month',
cls.operation_date) == "%s-%s-01" % (year, month)
).group_by(cls.account_id)
return query

View File

@ -14,6 +14,8 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
from sqlalchemy import desc
from accountant import db
from .accounts import Account
@ -44,3 +46,24 @@ class ScheduledOperation(db.Model):
self.value = value
self.account_id = account_id
self.category = category
@classmethod
def get_scheduled_operations_for_account(cls, session, account):
if isinstance(account, int) or isinstance(account, str):
account_id = account
else:
account_id = account.id
query = session.query(
cls
).select_from(
session.query(cls)
.filter(cls.account_id == account_id)
.order_by(
desc(cls.day),
cls.value,
cls.label,
).subquery()
)
return query

View File

@ -16,11 +16,9 @@
"""
from flask import json, request
from sqlalchemy import func, case, cast, extract, distinct
from forms.accounts import AccountForm
from accountant import db, session_scope
from accountant import session_scope
from . import auth
from .. import api
@ -37,16 +35,7 @@ def get_accounts():
Returns accounts with their solds.
"""
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 = Account.get_accounts(session)
return json.dumps([{
"id": i.id,
@ -62,19 +51,7 @@ def get_accounts():
@auth.login_required
def get_account_status(account_id, year, month):
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 = Operation.get_account_status(session, account_id, year, month)
if query.count() == 1:
result = query.one()
@ -97,12 +74,7 @@ def get_account_status(account_id, year, month):
@auth.login_required
def get_months(account_id):
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 = Entry.get_months_for_account(session, account_id)
return json.dumps([{
"year": i.year,
@ -129,10 +101,7 @@ def update_account(account_id):
if account_form.validate():
with session_scope() as session:
query = session.query(Account)
query = query.filter(Account.id == account_id)
account = query.first()
account = session.query(Account).get(account_id)
account.name = request.json['name']
account.authorized_overdraft = request.json['authorized_overdraft']

View File

@ -16,8 +16,6 @@
"""
from flask import json, request
from sqlalchemy import func, case, desc
from accountant import session_scope
from .. import api
@ -32,23 +30,8 @@ def get_entries(account_id, year, month):
Return entries for an account, year, and month.
"""
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", desc("value"), desc("label")])
).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)
query = query.filter(func.date_trunc(
'month', base_query.c.operation_date) == "%s-%s-01" % (year, month))
query = Operation.get_for_account_and_month(session, account_id, year,
month)
return json.dumps([{
"id": i.id,
@ -85,7 +68,7 @@ def add_entry():
@api.route("/entries/<entry_id>", methods=["PUT"])
def update_entry(entry_id):
with session_scope() as session:
entry = session.query(Entry).filter(Entry.id == entry_id).first()
entry = session.query(Entry).get(entry_id)
entry.id = entry_id
entry.operation_date = request.json['operation_date']

View File

@ -16,8 +16,6 @@
"""
from flask import json, request
from sqlalchemy import desc
from accountant import session_scope
from .. import api
@ -30,17 +28,8 @@ def get_scheduled_operations(account_id):
Return entries for an account, year, and month.
"""
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 = ScheduledOperation.get_scheduled_operations_for_account(
session, account_id)
return json.dumps([{
"id": i.id,