Move queries in models.
This commit is contained in:
parent
e1b5d8be43
commit
c411ce5328
@ -14,8 +14,12 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from sqlalchemy import func, case, cast
|
||||||
|
|
||||||
from accountant import db
|
from accountant import db
|
||||||
|
|
||||||
|
from .entries import Entry
|
||||||
|
|
||||||
|
|
||||||
class Account(db.Model):
|
class Account(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
@ -25,3 +29,18 @@ class Account(db.Model):
|
|||||||
def __init__(self, name, authorized_overdraft):
|
def __init__(self, name, authorized_overdraft):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.authorized_overdraft = authorized_overdraft
|
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
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
from accountant import db
|
|
||||||
|
|
||||||
from .accounts import Account
|
from sqlalchemy import distinct, func, cast, extract
|
||||||
from .scheduled_operations import ScheduledOperation
|
from accountant import db
|
||||||
|
|
||||||
|
|
||||||
class Entry(db.Model):
|
class Entry(db.Model):
|
||||||
@ -30,9 +29,9 @@ class Entry(db.Model):
|
|||||||
scheduled_operation_id = db.Column(db.Integer,
|
scheduled_operation_id = db.Column(db.Integer,
|
||||||
db.ForeignKey('scheduled_operation.id'))
|
db.ForeignKey('scheduled_operation.id'))
|
||||||
|
|
||||||
account = db.relationship(Account, backref=db.backref('entry',
|
account = db.relationship("Account", backref=db.backref('entry',
|
||||||
lazy="dynamic"))
|
lazy="dynamic"))
|
||||||
scheduled_operation = db.relationship(ScheduledOperation,
|
scheduled_operation = db.relationship("ScheduledOperation",
|
||||||
backref=db.backref('entry',
|
backref=db.backref('entry',
|
||||||
lazy="dynamic"))
|
lazy="dynamic"))
|
||||||
|
|
||||||
@ -47,3 +46,19 @@ class Entry(db.Model):
|
|||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
self.category = category
|
self.category = category
|
||||||
self.scheduled_operation_id = scheduled_operation_id
|
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
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from sqlalchemy import func, case, desc
|
||||||
|
|
||||||
from accountant import db
|
from accountant import db
|
||||||
|
|
||||||
from .accounts import Account
|
from .accounts import Account
|
||||||
@ -44,3 +46,52 @@ class Operation(db.Model):
|
|||||||
self.value = value
|
self.value = value
|
||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
self.category = category
|
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
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
from accountant import db
|
from accountant import db
|
||||||
|
|
||||||
from .accounts import Account
|
from .accounts import Account
|
||||||
@ -44,3 +46,24 @@ class ScheduledOperation(db.Model):
|
|||||||
self.value = value
|
self.value = value
|
||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
self.category = category
|
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
|
||||||
|
@ -16,11 +16,9 @@
|
|||||||
"""
|
"""
|
||||||
from flask import json, request
|
from flask import json, request
|
||||||
|
|
||||||
from sqlalchemy import func, case, cast, extract, distinct
|
|
||||||
|
|
||||||
from forms.accounts import AccountForm
|
from forms.accounts import AccountForm
|
||||||
|
|
||||||
from accountant import db, session_scope
|
from accountant import session_scope
|
||||||
|
|
||||||
from . import auth
|
from . import auth
|
||||||
from .. import api
|
from .. import api
|
||||||
@ -37,16 +35,7 @@ def get_accounts():
|
|||||||
Returns accounts with their solds.
|
Returns accounts with their solds.
|
||||||
"""
|
"""
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = Account.get_accounts(session)
|
||||||
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([{
|
return json.dumps([{
|
||||||
"id": i.id,
|
"id": i.id,
|
||||||
@ -62,19 +51,7 @@ def get_accounts():
|
|||||||
@auth.login_required
|
@auth.login_required
|
||||||
def get_account_status(account_id, year, month):
|
def get_account_status(account_id, year, month):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = Operation.get_account_status(session, account_id, year, month)
|
||||||
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:
|
if query.count() == 1:
|
||||||
result = query.one()
|
result = query.one()
|
||||||
@ -97,12 +74,7 @@ def get_account_status(account_id, year, month):
|
|||||||
@auth.login_required
|
@auth.login_required
|
||||||
def get_months(account_id):
|
def get_months(account_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = Entry.get_months_for_account(session, account_id)
|
||||||
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([{
|
return json.dumps([{
|
||||||
"year": i.year,
|
"year": i.year,
|
||||||
@ -129,10 +101,7 @@ def update_account(account_id):
|
|||||||
|
|
||||||
if account_form.validate():
|
if account_form.validate():
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(Account)
|
account = session.query(Account).get(account_id)
|
||||||
query = query.filter(Account.id == account_id)
|
|
||||||
|
|
||||||
account = query.first()
|
|
||||||
|
|
||||||
account.name = request.json['name']
|
account.name = request.json['name']
|
||||||
account.authorized_overdraft = request.json['authorized_overdraft']
|
account.authorized_overdraft = request.json['authorized_overdraft']
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
"""
|
"""
|
||||||
from flask import json, request
|
from flask import json, request
|
||||||
|
|
||||||
from sqlalchemy import func, case, desc
|
|
||||||
|
|
||||||
from accountant import session_scope
|
from accountant import session_scope
|
||||||
|
|
||||||
from .. import api
|
from .. import api
|
||||||
@ -32,23 +30,8 @@ def get_entries(account_id, year, month):
|
|||||||
Return entries for an account, year, and month.
|
Return entries for an account, year, and month.
|
||||||
"""
|
"""
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
base_query = session.query(
|
query = Operation.get_for_account_and_month(session, account_id, year,
|
||||||
Operation,
|
month)
|
||||||
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))
|
|
||||||
|
|
||||||
return json.dumps([{
|
return json.dumps([{
|
||||||
"id": i.id,
|
"id": i.id,
|
||||||
@ -85,7 +68,7 @@ def add_entry():
|
|||||||
@api.route("/entries/<entry_id>", methods=["PUT"])
|
@api.route("/entries/<entry_id>", methods=["PUT"])
|
||||||
def update_entry(entry_id):
|
def update_entry(entry_id):
|
||||||
with session_scope() as session:
|
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.id = entry_id
|
||||||
entry.operation_date = request.json['operation_date']
|
entry.operation_date = request.json['operation_date']
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
"""
|
"""
|
||||||
from flask import json, request
|
from flask import json, request
|
||||||
|
|
||||||
from sqlalchemy import desc
|
|
||||||
|
|
||||||
from accountant import session_scope
|
from accountant import session_scope
|
||||||
|
|
||||||
from .. import api
|
from .. import api
|
||||||
@ -30,17 +28,8 @@ def get_scheduled_operations(account_id):
|
|||||||
Return entries for an account, year, and month.
|
Return entries for an account, year, and month.
|
||||||
"""
|
"""
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = ScheduledOperation.get_scheduled_operations_for_account(
|
||||||
ScheduledOperation
|
session, account_id)
|
||||||
).select_from(
|
|
||||||
session.query(ScheduledOperation)
|
|
||||||
.filter(ScheduledOperation.account_id == account_id)
|
|
||||||
.order_by(
|
|
||||||
desc(ScheduledOperation.day),
|
|
||||||
ScheduledOperation.value,
|
|
||||||
ScheduledOperation.label,
|
|
||||||
).subquery()
|
|
||||||
)
|
|
||||||
|
|
||||||
return json.dumps([{
|
return json.dumps([{
|
||||||
"id": i.id,
|
"id": i.id,
|
||||||
|
Loading…
Reference in New Issue
Block a user