Rewrote operations with cumulated balance.

This commit is contained in:
Alexis Lahouze 2017-05-25 22:07:56 +02:00
parent 69d5f57b90
commit d2c08c2fb3
2 changed files with 61 additions and 42 deletions

View File

@ -95,41 +95,59 @@ class Operation(db.Model):
self.canceled = canceled self.canceled = canceled
@classmethod @classmethod
def query(cls, begin=None, end=None): def query(cls):
"""Return query for this class.""" """Return query for this class."""
# We have to use a join because the sold is not computed from the
# begining.
base_query = db.session.query(
cls.id,
cls.sold
).subquery()
query = db.session.query( query = db.session.query(
cls.id, cls
cls.operation_date, )
cls.label,
cls.value, return query
base_query.c.sold,
cls.category, @classmethod
cls.scheduled_operation_id, def get_with_balance(cls, account_id, begin=None, end=None):
cls.account_id, """Get operations with cumulated balance for a speciific account,
cls.pointed, optionally for a specific time period."""
cls.confirmed, query = db.session.query(
cls.canceled *cls.__table__.columns.keys(),
).join( db.func.sum(
base_query, base_query.c.id == cls.id cls.value
).order_by( ).filter(
db.desc(cls.operation_date), db.not_(cls.canceled)
cls.value, ).over(
cls.label, partition_by=[cls.account_id],
order_by=[
cls.operation_date,
db.desc(cls.value),
db.desc(cls.label),
cls.id
]
).label("balance")
).filter(
cls.account_id == account_id
) )
if begin: if begin:
query = query.filter(cls.operation_date >= str(begin)) base_query = query.subquery()
query = db.session.query(
base_query
).filter(
cls.operation_date >= str(begin)
).join(
cls, base_query.c.id == cls.id
)
if end: if end:
query = query.filter(cls.operation_date <= str(end)) query = query.filter(cls.operation_date <= str(end))
query = query.order_by(
cls.operation_date,
db.desc(cls.value),
db.desc(cls.label),
cls.id
)
return query return query
@classmethod @classmethod

View File

@ -7,7 +7,7 @@ import dateutil.parser
from flask_jwt_extended import jwt_required from flask_jwt_extended import jwt_required
from flask_restplus import Namespace, Resource, fields from flask_restplus import Namespace, Resource, fields
from ..models import db from ..models import db, result_as_dicts
from ..models.accounts import Account from ..models.accounts import Account
from ..models.operations import Operation from ..models.operations import Operation
@ -21,7 +21,7 @@ operation_model = ns.model('Operation', {
default=None, default=None,
readonly=True, readonly=True,
description='Id of the operation'), description='Id of the operation'),
'operation_date': fields.DateTime( 'operation_date': fields.Date(
dt_format='iso8601', dt_format='iso8601',
required=True, required=True,
description='Date of the operation'), description='Date of the operation'),
@ -52,11 +52,11 @@ operation_model = ns.model('Operation', {
description='Canceled status of the operation (for a scheduled one)') description='Canceled status of the operation (for a scheduled one)')
}) })
operation_with_sold_model = ns.clone( operation_with_balance_model = ns.clone(
'OperationWithSold', operation_model, { 'OperationWithBalance', operation_model, {
'sold': fields.Float( 'balance': fields.Float(
readonly=True, readonly=True,
description='Cumulated sold' description='Cumulated balance'
), ),
} }
) )
@ -99,21 +99,22 @@ account_range_parser.add_argument(
class OperationListResource(Resource): class OperationListResource(Resource):
"""Resource to handle operation lists.""" """Resource to handle operation lists."""
@ns.response(200, 'OK', [operation_with_sold_model]) @ns.response(200, 'OK', [operation_with_balance_model])
@ns.expect(parser=account_range_parser) @ns.expect(account_range_parser)
@ns.marshal_list_with(operation_with_sold_model) @ns.marshal_list_with(operation_with_balance_model)
@jwt_required #@jwt_required
def get(self): def get(self):
"""Get operations with solds for a specific account.""" """Get operations with cumulated balance for a specific account."""
data = account_range_parser.parse_args() data = account_range_parser.parse_args()
return Operation.query( account_id = data['account_id']
begin=data['begin'], begin = data['begin']
end=data['end'] end = data['end']
).filter(
Operation.account_id == data['account_id'] return list(result_as_dicts(
).all(), 200 Operation.get_with_balance(account_id, begin=begin, end=end)
)), 200
@ns.response(201, 'Operation created', operation_model) @ns.response(201, 'Operation created', operation_model)
@ns.response(404, 'Account not found') @ns.response(404, 'Account not found')