diff --git a/accountant/models/accounts.py b/accountant/models/accounts.py index 27d7647..d5924d5 100644 --- a/accountant/models/accounts.py +++ b/accountant/models/accounts.py @@ -124,6 +124,84 @@ class Account(db.Model): return query + def daily_balances(self, begin=None, end=None): + """Return a query for daily balances with expenses, revenues, income + and balance per day for this account and an optional specifir range.""" + + #end = end if end else arrow.now().ceil('month').date() + + query = db.session.query( + Operation.operation_date, + db.func.coalesce( + db.func.sum( + Operation.value + ).filter( + db.func.sign(Operation.value) == -1 + ).over( + partition_by=[ + Operation.account_id, + Operation.operation_date + ], + ), + 0 + ).label("expenses"), + db.func.coalesce( + db.func.sum( + Operation.value + ).filter( + db.func.sign(Operation.value) == 1 + ).over( + partition_by=[ + Operation.account_id, + Operation.operation_date + ], + ), + 0 + ).label("revenues"), + db.func.coalesce( + db.func.sum( + Operation.value + ).over( + partition_by=[ + Operation.account_id, + Operation.operation_date + ], + ) + ).label("income"), + db.func.coalesce( + db.func.sum( + Operation.value + ).over( + partition_by=Operation.account_id, + order_by=Operation.operation_date + ) + ).label("balance") + ).distinct( + ).order_by( + Operation.operation_date + ).filter( + Operation.account_id == self.id + ) + + if begin: + base_query = query.subquery() + + query = db.session.query( + base_query + ).filter( + base_query.c.operation_date >= str(begin) + ).order_by( + base_query.c.operation_date + ) + + if end: + query = query.filter(query.c.operation_date <= str(end)) + + elif end: + query = query.filter(Operation.operation_date <= str(end)) + + return query + @db.validates('authorized_overdraft') def validate_authorized_overdraft(self, key, authorized_overdraft): """Validator for authorized_overdraft : must be negative.""" diff --git a/accountant/models/operations.py b/accountant/models/operations.py index ae8ff06..fb90f46 100644 --- a/accountant/models/operations.py +++ b/accountant/models/operations.py @@ -132,77 +132,3 @@ class Operation(db.Model): ) return query - - @classmethod - def query_daily_balances(cls, account, begin=None, end=None): - """Get expenses, revenues, income and balance per day for a specific - range and a specific account.""" - if isinstance(account, (int, str)): - account_id = account - else: - account_id = account.id - - end = end if end else arrow.now().ceil('month').date() - - query = db.session.query( - cls.operation_date, - db.func.coalesce( - db.func.sum( - cls.value - ).filter( - db.func.sign(cls.value) == -1 - ).over( - partition_by=[cls.account_id, cls.operation_date], - ), - 0 - ).label("expenses"), - db.func.coalesce( - db.func.sum( - cls.value - ).filter( - db.func.sign(cls.value) == 1 - ).over( - partition_by=[cls.account_id, cls.operation_date], - ), - 0 - ).label("revenues"), - db.func.coalesce( - db.func.sum( - cls.value - ).over( - partition_by=[cls.account_id, cls.operation_date], - ) - ).label("income"), - db.func.coalesce( - db.func.sum( - cls.value - ).over( - partition_by=cls.account_id, - order_by=cls.operation_date - ) - ).label("balance") - ).distinct( - ).order_by( - cls.operation_date - ).filter( - cls.account_id == account_id - ) - - if begin: - base_query = query.subquery() - - query = db.session.query( - base_query - ).filter( - base_query.c.operation_date >= str(begin) - ).order_by( - base_query.c.operation_date - ) - - if end: - query = query.filter(query.c.operation_date <= str(end)) - - elif end: - query = query.filter(cls.operation_date <= str(end)) - - return query diff --git a/accountant/views/accounts.py b/accountant/views/accounts.py index f769c7d..5cc89d4 100644 --- a/accountant/views/accounts.py +++ b/accountant/views/accounts.py @@ -9,7 +9,6 @@ from flask_restplus import Namespace, Resource, fields from ..models import db, row_as_dict, result_as_dicts from ..models.accounts import Account -from ..models.operations import Operation # pylint: disable=invalid-name @@ -361,6 +360,11 @@ class DailyBalancesResource(Resource): data = range_parser.parse_args() + account = Account.query().get(account_id) + + if not account: + ns.abort(404, 'Account with id %d not found.' % account_id) + return list(result_as_dicts( - Operation.query_daily_balances(account_id, **data) + account.daily_balances(account_id, **data) )), 200