143 lines
4.0 KiB
Python
143 lines
4.0 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
|
|
|
|
from ..models.operations import Operation
|
|
|
|
from .users import requires_auth
|
|
|
|
from ..fields import Object
|
|
|
|
|
|
operation_with_sold_model = {
|
|
'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,
|
|
}
|
|
|
|
operation_model = operation_with_sold_model
|
|
|
|
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):
|
|
@requires_auth
|
|
@marshal_with_field(fields.List(Object(operation_with_sold_model)))
|
|
def get(self):
|
|
data = range_parser.parse_args()
|
|
|
|
return Operation.query(
|
|
begin=data['begin'],
|
|
end=data['end'],
|
|
).filter(
|
|
Operation.account_id == data['account']
|
|
).all(), 200
|
|
|
|
@requires_auth
|
|
@marshal_with_field(Object(operation_model))
|
|
def post(self):
|
|
data = parser.parse_args()
|
|
|
|
operation = Operation(**data)
|
|
|
|
db.session.add(operation)
|
|
|
|
return operation, 201
|
|
|
|
|
|
class OperationResource(Resource):
|
|
@requires_auth
|
|
@marshal_with_field(Object(operation_model))
|
|
def get(self, id):
|
|
"""
|
|
Get operation.
|
|
"""
|
|
operation = db.session.query(Operation).get(id)
|
|
|
|
if not operation:
|
|
return None, 404
|
|
|
|
return operation, 200
|
|
|
|
@requires_auth
|
|
@marshal_with_field(Object(operation_model))
|
|
def post(self, id):
|
|
data = parser.parse_args()
|
|
|
|
assert (id not in data or data.id is None
|
|
or data.id == id)
|
|
|
|
operation = db.session.query(Operation).get(id)
|
|
|
|
if not operation:
|
|
return None, 404
|
|
|
|
# SQLAlchemy objects ignore __dict__.update() with merge.
|
|
for k, v in data.items():
|
|
setattr(operation, k, v)
|
|
|
|
db.session.merge(operation)
|
|
|
|
return operation, 200
|
|
|
|
@requires_auth
|
|
@marshal_with_field(Object(operation_model))
|
|
def delete(self, id):
|
|
operation = db.session.query(Operation).get(id)
|
|
|
|
if not operation:
|
|
return None, 404
|
|
|
|
db.session.delete(operation)
|
|
|
|
return None, 204
|
|
|
|
|
|
api.add_resource(OperationListResource, "/operation")
|
|
api.add_resource(OperationResource, "/operation/<int:id>")
|