accountant/accountant/api/views/operations.py
2015-11-24 21:31:24 +01:00

168 lines
4.8 KiB
Python

"""
This file is part of Accountant.
Accountant is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Accountant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
"""
import dateutil.parser
from flask.ext.restful import Resource, fields, reqparse, marshal_with_field
from accountant import db
from .. import api_api
from ..models.operations import Operation
from ..fields import Object
resource_fields = {
'id': fields.Integer(default=None),
'operation_date': fields.DateTime(dt_format='iso8601'),
'label': fields.String,
'value': fields.Float,
'pointed': fields.Boolean,
'category': fields.String,
'account_id': fields.Integer,
'scheduled_operation_id': fields.Integer(default=None),
'sold': fields.Float,
'confirmed': fields.Boolean,
'canceled': fields.Boolean,
}
parser = reqparse.RequestParser()
# Must use lambda because the parser passes other parameters badly interpreted
# by dateutil.parser.parse
parser.add_argument('operation_date', type=lambda a: dateutil.parser.parse(a))
parser.add_argument('label', type=str)
parser.add_argument('value', type=float)
parser.add_argument('pointed', type=bool)
parser.add_argument('category', type=str)
parser.add_argument('account_id', type=int)
parser.add_argument('scheduled_operation_id', type=int)
parser.add_argument('confirmed', type=bool)
parser.add_argument('canceled', type=bool)
range_parser = reqparse.RequestParser()
range_parser.add_argument('account', type=int)
range_parser.add_argument('begin', type=lambda a: dateutil.parser.parse(a))
range_parser.add_argument('end', type=lambda a: dateutil.parser.parse(a))
class OperationListResource(Resource):
@marshal_with_field(fields.List(Object(resource_fields)))
def get(self):
kwargs = range_parser.parse_args()
return Operation.query(
begin=kwargs['begin'],
end=kwargs['end'],
).filter(
Operation.account_id == kwargs['account']
).all()
@marshal_with_field(Object(resource_fields))
def post(self):
kwargs = parser.parse_args()
operation = Operation(**kwargs)
db.session.add(operation)
return operation
class OperationResource(Resource):
@marshal_with_field(Object(resource_fields))
def get(self, operation_id):
"""
Get operation.
"""
operation = db.session.query(Operation).get(operation_id)
if not operation:
return None, 404
return operation
@marshal_with_field(Object(resource_fields))
def post(self, operation_id):
kwargs = parser.parse_args()
assert (id not in kwargs or kwargs.id is None
or kwargs.id == operation_id)
operation = db.session.query(Operation).get(operation_id)
if not operation:
return None, 404
# SQLAlchemy objects ignore __dict__.update() with merge.
for k, v in kwargs.items():
setattr(operation, k, v)
db.session.merge(operation)
return operation
@marshal_with_field(Object(resource_fields))
def delete(self, operation_id):
operation = db.session.query(Operation).get(operation_id)
if not operation:
return None, 404
db.session.delete(operation)
return operation
category_resource_fields = {
'category': fields.String,
'expenses': fields.Float,
'revenues': fields.Float
}
class CategoriesResource(Resource):
@marshal_with_field(fields.List(Object(category_resource_fields)))
def get(self):
kwargs = range_parser.parse_args()
return Operation.get_categories_for_range(**kwargs).all()
ohlc_resource_fields = {
'operation_date': fields.DateTime(dt_format='iso8601'),
'open': fields.Float,
'high': fields.Float,
'low': fields.Float,
'close': fields.Float
}
class SoldsResource(Resource):
@marshal_with_field(fields.List(Object(ohlc_resource_fields)))
def get(self):
kwargs = range_parser.parse_args()
return Operation.get_ohlc_per_day_for_range(**kwargs).all()
api_api.add_resource(OperationListResource, "/operations")
api_api.add_resource(OperationResource, "/operations/<int:operation_id>")
api_api.add_resource(CategoriesResource, "/categories")
api_api.add_resource(SoldsResource, "/solds")