""" 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. Foobar 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 . """ from .. import api from ..model import db, session_scope from ..model.accounts import Account from ..model.entries import Entry from ..model.operations import Operation from flask import json, request from sqlalchemy import func, case, cast, extract, distinct @api.route("/accounts", methods=["GET"]) def get_accounts(): """ Returns accounts with their solds. """ with session_scope() as session: query = session.query( 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([{ "id": i.id, "name": i.name, "authorized_overdraft": i.authorized_overdraft, "current": str(i.current), "pointed": str(i.pointed), "future": str(i.future) } for i in query.all()]) @api.route("/accounts////") def get_account_status(account_id, year, month): with session_scope() as session: query = session.query( 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: result = query.one() revenues = result.revenues expenses = result.expenses balance = result.balance else: revenues = 0.0 expenses = 0.0 balance = 0.0 return json.dumps({ "expenses": str(expenses), "revenues": str(revenues), "balance": str(balance) }) @api.route("/accounts//months") def get_months(account_id): with session_scope() as session: query = session.query( 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([{ "year": i.year, "month": i.month.rjust(2, '0') } for i in query.all()]) @api.route("/accounts", methods=["PUT"]) def add_account(): with session_scope() as session: account = Account(request.json['name'], request.json['authorized_overdraft']) session.add(account) return json.dumps("Account added.") @api.route("/accounts/", methods=["PUT"]) def update_account(account_id): with session_scope() as session: account = session.query(Account).filter(Account.id == account_id).first() account.name = request.json['name'] account.authorized_overdraft = request.json['authorized_overdraft'] session.merge(account) return json.dumps("Account #%s updated." % account_id) @api.route("/accounts/", methods=["DELETE"]) def delete_account(account_id): with session_scope() as session: account = session.query(Account).filter(Account.id == account_id).first() session.delete(account) return json.dumps("Account #%s deleted." % account_id)