Refactoring.
This commit is contained in:
parent
6c24fb27be
commit
069fbe8f8e
@ -14,27 +14,40 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from .api import api
|
|
||||||
#from api.controller import login_manager
|
|
||||||
from .api.model import db
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask.ext.sqlalchemy import SQLAlchemy
|
from flask.ext.sqlalchemy import SQLAlchemy
|
||||||
from .frontend import frontend
|
|
||||||
from sqlalchemy.orm import sessionmaker
|
|
||||||
from . import config
|
from . import config
|
||||||
|
|
||||||
# The app
|
# The app
|
||||||
app = Flask(__name__, static_folder = None)
|
app = Flask(__name__, static_folder=None)
|
||||||
|
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = config.db_uri
|
app.config['SQLALCHEMY_DATABASE_URI'] = config.db_uri
|
||||||
app.config['SQLALCHEMY_RECORD_QUERIES'] = config.debug
|
app.config['SQLALCHEMY_RECORD_QUERIES'] = config.debug
|
||||||
app.config['WTF_CSRF_ENABLED'] = False
|
app.config['WTF_CSRF_ENABLED'] = False
|
||||||
app.config['SECRET_KEY'] = 'my_secret_key'
|
app.config['SECRET_KEY'] = 'my_secret_key'
|
||||||
|
|
||||||
db.init_app(app)
|
db = SQLAlchemy(app)
|
||||||
#login_manager.init_app(app)
|
|
||||||
|
@contextmanager
|
||||||
|
def session_scope():
|
||||||
|
from accountant import db
|
||||||
|
session = db.session
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield session
|
||||||
|
session.commit()
|
||||||
|
except:
|
||||||
|
session.rollback()
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
# Must be after db declaration because the blueprints may need it.
|
||||||
|
from .api import api
|
||||||
|
from .frontend import frontend
|
||||||
|
|
||||||
app.register_blueprint(frontend, url_prefix='')
|
app.register_blueprint(frontend, url_prefix='')
|
||||||
app.register_blueprint(api, url_prefix='/api')
|
app.register_blueprint(api, url_prefix='/api')
|
||||||
|
|
||||||
|
@ -1,6 +1,22 @@
|
|||||||
|
"""
|
||||||
|
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/>.
|
||||||
|
"""
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
|
||||||
api = Blueprint('api', __name__)
|
api = Blueprint('api', __name__)
|
||||||
|
|
||||||
|
# Load all views.
|
||||||
from .controller import *
|
from .controller import *
|
||||||
|
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
"""
|
||||||
|
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 pkgutil
|
import pkgutil
|
||||||
from flask.ext.httpauth import HTTPBasicAuth
|
from flask.ext.httpauth import HTTPBasicAuth
|
||||||
|
|
||||||
@ -7,6 +23,3 @@ __all__ = []
|
|||||||
|
|
||||||
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
|
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
|
||||||
__all__.append(module_name)
|
__all__.append(module_name)
|
||||||
|
|
||||||
from . import *
|
|
||||||
|
|
||||||
|
@ -14,15 +14,21 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from flask import json, request
|
||||||
|
|
||||||
|
from sqlalchemy import func, case, cast, extract, distinct
|
||||||
|
|
||||||
|
from forms.accounts import AccountForm
|
||||||
|
|
||||||
|
from accountant import db, session_scope
|
||||||
|
|
||||||
from . import auth
|
from . import auth
|
||||||
from .. import api
|
from .. import api
|
||||||
from ..model import db, session_scope
|
|
||||||
from ..model.accounts import Account
|
from ..model.accounts import Account
|
||||||
from ..model.entries import Entry
|
from ..model.entries import Entry
|
||||||
from ..model.operations import Operation
|
from ..model.operations import Operation
|
||||||
from flask import json, request
|
|
||||||
from sqlalchemy import func, case, cast, extract, distinct
|
|
||||||
from forms.accounts import AccountIdForm, AccountForm
|
|
||||||
|
|
||||||
@api.route("/accounts", methods=["GET"])
|
@api.route("/accounts", methods=["GET"])
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
@ -32,12 +38,14 @@ def get_accounts():
|
|||||||
"""
|
"""
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = session.query(
|
||||||
Account.id.label("id"),
|
Account.id.label("id"),
|
||||||
Account.name.label("name"),
|
Account.name.label("name"),
|
||||||
Account.authorized_overdraft.label("authorized_overdraft"),
|
Account.authorized_overdraft.label("authorized_overdraft"),
|
||||||
func.sum(Entry.value).label("future"),
|
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.pointed, Entry.value,)],
|
||||||
func.sum(case([(Entry.operation_date < func.now(), Entry.value,)], else_=cast(0, db.Numeric(15, 2)))).label("current")
|
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)
|
).outerjoin(Entry).group_by(Account.id).order_by(Account.id)
|
||||||
|
|
||||||
return json.dumps([{
|
return json.dumps([{
|
||||||
@ -49,18 +57,23 @@ def get_accounts():
|
|||||||
"future": str(i.future)
|
"future": str(i.future)
|
||||||
} for i in query.all()])
|
} for i in query.all()])
|
||||||
|
|
||||||
|
|
||||||
@api.route("/accounts/<account_id>/<year>/<month>/")
|
@api.route("/accounts/<account_id>/<year>/<month>/")
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
def get_account_status(account_id, year, month):
|
def get_account_status(account_id, year, month):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
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)],
|
||||||
func.sum(case([(func.sign(Operation.value) == 1, Operation.value)], else_=0)).label("revenues"),
|
else_=0)).label("expenses"),
|
||||||
|
func.sum(case([(func.sign(Operation.value) == 1, Operation.value)],
|
||||||
|
else_=0)).label("revenues"),
|
||||||
func.sum(Operation.value).label("balance")
|
func.sum(Operation.value).label("balance")
|
||||||
).filter(
|
).filter(
|
||||||
Operation.account_id == account_id
|
Operation.account_id == account_id
|
||||||
).filter(
|
).filter(
|
||||||
func.date_trunc('month', Operation.operation_date) == "%s-%s-01" % (year, month)
|
func.date_trunc('month',
|
||||||
|
Operation.operation_date) == "%s-%s-01" % (year,
|
||||||
|
month)
|
||||||
).group_by(Operation.account_id)
|
).group_by(Operation.account_id)
|
||||||
|
|
||||||
if query.count() == 1:
|
if query.count() == 1:
|
||||||
@ -79,13 +92,16 @@ def get_account_status(account_id, year, month):
|
|||||||
"balance": str(balance)
|
"balance": str(balance)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@api.route("/accounts/<account_id>/months")
|
@api.route("/accounts/<account_id>/months")
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
def get_months(account_id):
|
def get_months(account_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = session.query(
|
||||||
distinct(func.lpad(cast(extract("year", Entry.operation_date), db.String), 4, '0')).label("year"),
|
distinct(func.lpad(cast(extract("year", Entry.operation_date),
|
||||||
func.lpad(cast(extract("month", Entry.operation_date), db.String), 2, '0').label("month")
|
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")
|
).filter(Entry.account_id == account_id).order_by("year", "month")
|
||||||
|
|
||||||
return json.dumps([{
|
return json.dumps([{
|
||||||
@ -93,11 +109,13 @@ def get_months(account_id):
|
|||||||
"month": i.month.rjust(2, '0')
|
"month": i.month.rjust(2, '0')
|
||||||
} for i in query.all()])
|
} for i in query.all()])
|
||||||
|
|
||||||
|
|
||||||
@api.route("/accounts", methods=["PUT"])
|
@api.route("/accounts", methods=["PUT"])
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
def add_account():
|
def add_account():
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
account = Account(request.json['name'], request.json['authorized_overdraft'])
|
account = Account(request.json['name'],
|
||||||
|
request.json['authorized_overdraft'])
|
||||||
|
|
||||||
session.add(account)
|
session.add(account)
|
||||||
|
|
||||||
@ -111,7 +129,10 @@ def update_account(account_id):
|
|||||||
|
|
||||||
if account_form.validate():
|
if account_form.validate():
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
account = session.query(Account).filter(Account.id == account_id).first()
|
query = session.query(Account)
|
||||||
|
query = query.filter(Account.id == account_id)
|
||||||
|
|
||||||
|
account = query.first()
|
||||||
|
|
||||||
account.name = request.json['name']
|
account.name = request.json['name']
|
||||||
account.authorized_overdraft = request.json['authorized_overdraft']
|
account.authorized_overdraft = request.json['authorized_overdraft']
|
||||||
@ -120,15 +141,22 @@ def update_account(account_id):
|
|||||||
|
|
||||||
return json.dumps("Account #%s updated." % account_id)
|
return json.dumps("Account #%s updated." % account_id)
|
||||||
else:
|
else:
|
||||||
return json.dumps({'ok': False, 'error_type': 'validation', 'errors': account_form.errors})
|
return json.dumps({
|
||||||
|
'ok': False,
|
||||||
|
'error_type': 'validation',
|
||||||
|
'errors': account_form.errorsi
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@api.route("/accounts/<account_id>", methods=["DELETE"])
|
@api.route("/accounts/<account_id>", methods=["DELETE"])
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
def delete_account(account_id):
|
def delete_account(account_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
account = session.query(Account).filter(Account.id == account_id).first()
|
query = session.query(Account)
|
||||||
|
query = query.filter(Account.id == account_id)
|
||||||
|
|
||||||
|
account = query.first()
|
||||||
|
|
||||||
session.delete(account)
|
session.delete(account)
|
||||||
|
|
||||||
return json.dumps("Account #%s deleted." % account_id)
|
return json.dumps("Account #%s deleted." % account_id)
|
||||||
|
|
||||||
|
@ -14,16 +14,17 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from flask import json, request
|
||||||
|
|
||||||
|
from sqlalchemy import func, case, desc
|
||||||
|
|
||||||
|
from accountant import session_scope
|
||||||
|
|
||||||
from .. import api
|
from .. import api
|
||||||
from ..model import db, session_scope
|
|
||||||
from ..model.entries import Entry
|
from ..model.entries import Entry
|
||||||
from ..model.operations import Operation
|
from ..model.operations import Operation
|
||||||
from ..model.scheduled_operations import ScheduledOperation
|
|
||||||
from flask import json, request
|
|
||||||
from sqlalchemy import func, desc
|
|
||||||
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
|
|
||||||
from sqlalchemy.orm import sessionmaker, column_property, aliased
|
|
||||||
from sqlalchemy.sql import func, select, case
|
|
||||||
|
|
||||||
@api.route("/entries/<account_id>/<year>/<month>")
|
@api.route("/entries/<account_id>/<year>/<month>")
|
||||||
def get_entries(account_id, year, month):
|
def get_entries(account_id, year, month):
|
||||||
@ -33,45 +34,54 @@ def get_entries(account_id, year, month):
|
|||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
base_query = session.query(
|
base_query = session.query(
|
||||||
Operation,
|
Operation,
|
||||||
case(whens={Operation.canceled: None}, else_=func.sum(Operation.value).over(partition_by="canceled", order_by="operation_date, value desc, label desc")).label("sold")
|
case(
|
||||||
|
whens={Operation.canceled: None},
|
||||||
|
else_=func.sum(Operation.value).over(
|
||||||
|
partition_by="canceled",
|
||||||
|
order_by="operation_date, value desc, label desc")
|
||||||
|
).label("sold")
|
||||||
).filter(Operation.account_id == account_id).order_by(
|
).filter(Operation.account_id == account_id).order_by(
|
||||||
desc(Operation.operation_date),
|
desc(Operation.operation_date),
|
||||||
Operation.value,
|
Operation.value,
|
||||||
Operation.label,
|
Operation.label,
|
||||||
).subquery()
|
).subquery()
|
||||||
|
|
||||||
query = session.query(base_query).select_from(base_query).filter(func.date_trunc('month', base_query.c.operation_date) == "%s-%s-01" % (year, month))
|
query = session.query(base_query).select_from(base_query)
|
||||||
|
query = query.filter(func.date_trunc(
|
||||||
|
'month', base_query.c.operation_date) == "%s-%s-01" % (year, month))
|
||||||
|
|
||||||
return json.dumps([{
|
return json.dumps([{
|
||||||
"id": i.id,
|
"id": i.id,
|
||||||
"pointed": i.pointed,
|
"pointed": i.pointed,
|
||||||
"operation_date": i.operation_date.strftime("%Y-%m-%d"),
|
"operation_date": i.operation_date.strftime("%Y-%m-%d"),
|
||||||
"label": i.label,
|
"label": i.label,
|
||||||
"value": str(i.value),
|
"value": str(i.value),
|
||||||
"category": i.category,
|
"category": i.category,
|
||||||
"sold": str(i.sold) if not i.canceled else None,
|
"sold": str(i.sold) if not i.canceled else None,
|
||||||
"account_id": i.account_id,
|
"account_id": i.account_id,
|
||||||
"canceled": i.canceled,
|
"canceled": i.canceled,
|
||||||
"scheduled_operation_id": i.scheduled_operation_id
|
"scheduled_operation_id": i.scheduled_operation_id
|
||||||
} for i in query.all()])
|
} for i in query.all()])
|
||||||
|
|
||||||
|
|
||||||
@api.route("/entries", methods=["PUT"])
|
@api.route("/entries", methods=["PUT"])
|
||||||
def add_entry():
|
def add_entry():
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
entry = Entry(
|
entry = Entry(
|
||||||
operation_date = request.json['operation_date'],
|
operation_date=request.json['operation_date'],
|
||||||
pointed = request.json['pointed'],
|
pointed=request.json['pointed'],
|
||||||
label = request.json['label'],
|
label=request.json['label'],
|
||||||
value = request.json['value'],
|
value=request.json['value'],
|
||||||
category = request.json['category'],
|
category=request.json['category'],
|
||||||
account_id = request.json['account_id'],
|
account_id=request.json['account_id'],
|
||||||
scheduled_operation_id = request.json['scheduled_operation_id']
|
scheduled_operation_id=request.json['scheduled_operation_id']
|
||||||
)
|
)
|
||||||
|
|
||||||
session.add(entry)
|
session.add(entry)
|
||||||
|
|
||||||
return json.dumps("Entry added.")
|
return json.dumps("Entry added.")
|
||||||
|
|
||||||
|
|
||||||
@api.route("/entries/<entry_id>", methods=["PUT"])
|
@api.route("/entries/<entry_id>", methods=["PUT"])
|
||||||
def update_entry(entry_id):
|
def update_entry(entry_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
@ -90,6 +100,7 @@ def update_entry(entry_id):
|
|||||||
|
|
||||||
return json.dumps("Entry #%s updated." % entry_id)
|
return json.dumps("Entry #%s updated." % entry_id)
|
||||||
|
|
||||||
|
|
||||||
@api.route("/entries/<entry_id>", methods=["DELETE"])
|
@api.route("/entries/<entry_id>", methods=["DELETE"])
|
||||||
def delete_entry(entry_id):
|
def delete_entry(entry_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
@ -98,4 +109,3 @@ def delete_entry(entry_id):
|
|||||||
session.delete(entry)
|
session.delete(entry)
|
||||||
|
|
||||||
return json.dumps("Entry #%s deleted." % entry_id)
|
return json.dumps("Entry #%s deleted." % entry_id)
|
||||||
|
|
||||||
|
@ -1,11 +1,28 @@
|
|||||||
from .. import api
|
"""
|
||||||
from ..model import db, session_scope
|
This file is part of Accountant.
|
||||||
from ..model.scheduled_operations import ScheduledOperation
|
|
||||||
|
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/>.
|
||||||
|
"""
|
||||||
from flask import json, request
|
from flask import json, request
|
||||||
from sqlalchemy import func, desc
|
|
||||||
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
|
from sqlalchemy import desc
|
||||||
from sqlalchemy.orm import sessionmaker, column_property
|
|
||||||
from sqlalchemy.sql import func, select
|
from accountant import session_scope
|
||||||
|
|
||||||
|
from .. import api
|
||||||
|
from ..model.scheduled_operations import ScheduledOperation
|
||||||
|
|
||||||
|
|
||||||
@api.route("/scheduled_operations/<account_id>")
|
@api.route("/scheduled_operations/<account_id>")
|
||||||
def get_scheduled_operations(account_id):
|
def get_scheduled_operations(account_id):
|
||||||
@ -14,51 +31,56 @@ def get_scheduled_operations(account_id):
|
|||||||
"""
|
"""
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
query = session.query(
|
query = session.query(
|
||||||
ScheduledOperation
|
ScheduledOperation
|
||||||
).select_from(
|
).select_from(
|
||||||
session.query(ScheduledOperation)
|
session.query(ScheduledOperation)
|
||||||
.filter(ScheduledOperation.account_id == account_id)
|
.filter(ScheduledOperation.account_id == account_id)
|
||||||
.order_by(
|
.order_by(
|
||||||
desc(ScheduledOperation.day),
|
desc(ScheduledOperation.day),
|
||||||
ScheduledOperation.value,
|
ScheduledOperation.value,
|
||||||
ScheduledOperation.label,
|
ScheduledOperation.label,
|
||||||
).subquery()
|
).subquery()
|
||||||
)
|
)
|
||||||
|
|
||||||
return json.dumps([{
|
return json.dumps([{
|
||||||
"id": i.id,
|
"id": i.id,
|
||||||
"start_date": i.start_date.strftime("%Y-%m-%d"),
|
"start_date": i.start_date.strftime("%Y-%m-%d"),
|
||||||
"stop_date": i.stop_date.strftime("%Y-%m-%d"),
|
"stop_date": i.stop_date.strftime("%Y-%m-%d"),
|
||||||
"day": str(i.day),
|
"day": str(i.day),
|
||||||
"frequency": str(i.frequency),
|
"frequency": str(i.frequency),
|
||||||
"label": i.label,
|
"label": i.label,
|
||||||
"value": str(i.value),
|
"value": str(i.value),
|
||||||
"category": i.category,
|
"category": i.category,
|
||||||
"account_id": i.account_id
|
"account_id": i.account_id
|
||||||
} for i in query.all()])
|
} for i in query.all()])
|
||||||
|
|
||||||
|
|
||||||
@api.route("/scheduled_operations", methods=["PUT"])
|
@api.route("/scheduled_operations", methods=["PUT"])
|
||||||
def add_scheduled_operation():
|
def add_scheduled_operation():
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
scheduledOperation = ScheduledOperation(
|
scheduledOperation = ScheduledOperation(
|
||||||
start_date = request.json['start_date'],
|
start_date=request.json['start_date'],
|
||||||
stop_date = request.json['stop_date'],
|
stop_date=request.json['stop_date'],
|
||||||
day = request.json['day'],
|
day=request.json['day'],
|
||||||
frequency = request.json['frequency'],
|
frequency=request.json['frequency'],
|
||||||
label = request.json['label'],
|
label=request.json['label'],
|
||||||
value = request.json['value'],
|
value=request.json['value'],
|
||||||
category = request.json['category'],
|
category=request.json['category'],
|
||||||
account_id = request.json['account_id']
|
account_id=request.json['account_id']
|
||||||
)
|
)
|
||||||
|
|
||||||
session.add(scheduledOperation)
|
session.add(scheduledOperation)
|
||||||
|
|
||||||
return json.dumps("Scheduled operation added.")
|
return json.dumps("Scheduled operation added.")
|
||||||
|
|
||||||
|
|
||||||
@api.route("/scheduled_operations/<scheduled_operation_id>", methods=["PUT"])
|
@api.route("/scheduled_operations/<scheduled_operation_id>", methods=["PUT"])
|
||||||
def update_scheduled_operation(scheduled_operation_id):
|
def update_scheduled_operation(scheduled_operation_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
scheduledOperation = session.query(ScheduledOperation).filter(ScheduledOperation.id == scheduled_operation_id).first()
|
query = session.query(ScheduledOperation)
|
||||||
|
query = query.filter(ScheduledOperation.id == scheduled_operation_id)
|
||||||
|
|
||||||
|
scheduledOperation = query.first()
|
||||||
|
|
||||||
scheduledOperation.id = scheduled_operation_id
|
scheduledOperation.id = scheduled_operation_id
|
||||||
scheduledOperation.start_date = request.json['start_date'],
|
scheduledOperation.start_date = request.json['start_date'],
|
||||||
@ -72,14 +94,18 @@ def update_scheduled_operation(scheduled_operation_id):
|
|||||||
|
|
||||||
session.merge(scheduledOperation)
|
session.merge(scheduledOperation)
|
||||||
|
|
||||||
return json.dumps("Scheduled operation #%s updated." % scheduled_operation_id)
|
return json.dumps(
|
||||||
|
"Scheduled operation #%s updated." % scheduled_operation_id)
|
||||||
|
|
||||||
|
|
||||||
@api.route("/scheduled_operations/<scheduled_operation_id>", methods=["DELETE"])
|
@api.route("/scheduled_operations/<scheduled_operation_id>", methods=["DELETE"])
|
||||||
def delete_scheduled_operation(scheduled_operation_id):
|
def delete_scheduled_operation(scheduled_operation_id):
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
scheduledOperation = session.query(ScheduledOperation).filter(ScheduledOperation.id == scheduled_operation_id).first()
|
query = session.query(ScheduledOperation)
|
||||||
|
query = query.filter(ScheduledOperation.id == scheduled_operation_id)
|
||||||
|
scheduledOperation = query.first()
|
||||||
|
|
||||||
session.delete(scheduledOperation)
|
session.delete(scheduledOperation)
|
||||||
|
|
||||||
return json.dumps("Scheduled operation #%s deleted." % scheduled_operation_id)
|
return json.dumps(
|
||||||
|
"Scheduled operation #%s deleted." % scheduled_operation_id)
|
||||||
|
@ -14,10 +14,11 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
#from accountant import session_scope
|
||||||
|
|
||||||
from . import auth
|
from . import auth
|
||||||
from .. import api
|
#from .. import api
|
||||||
from ..model import db, session_scope
|
|
||||||
|
|
||||||
@auth.verify_password
|
@auth.verify_password
|
||||||
def verify_password(username, password):
|
def verify_password(username, password):
|
||||||
|
@ -1,25 +1,19 @@
|
|||||||
from contextlib import contextmanager
|
"""
|
||||||
from flask.ext.sqlalchemy import SQLAlchemy
|
This file is part of Accountant.
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
|
||||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
|
||||||
|
|
||||||
db = SQLAlchemy()
|
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.
|
||||||
|
|
||||||
@contextmanager
|
Accountant is distributed in the hope that it will be useful,
|
||||||
def session_scope():
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
#session = scoped_session(sessionmaker(autocommit = False, autoflush = False, bind = engine))
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
session = db.session
|
GNU Affero General Public License for more details.
|
||||||
#Base.query = session.query_property()
|
|
||||||
|
|
||||||
try:
|
|
||||||
yield session
|
|
||||||
session.commit()
|
|
||||||
except:
|
|
||||||
session.rollback()
|
|
||||||
raise
|
|
||||||
finally:
|
|
||||||
session.close()
|
|
||||||
|
|
||||||
|
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 pkgutil
|
import pkgutil
|
||||||
|
|
||||||
__all__ = []
|
__all__ = []
|
||||||
@ -27,5 +21,4 @@ __all__ = []
|
|||||||
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
|
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
|
||||||
__all__.append(module_name)
|
__all__.append(module_name)
|
||||||
|
|
||||||
from . import *
|
#from . import *
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
from . import db
|
from accountant import db
|
||||||
|
|
||||||
|
|
||||||
class Account(db.Model):
|
class Account(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key = True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(200), nullable = False)
|
name = db.Column(db.String(200), nullable=False)
|
||||||
authorized_overdraft = db.Column(db.Integer, nullable = True, default = 0)
|
authorized_overdraft = db.Column(db.Integer, nullable=True, default=0)
|
||||||
|
|
||||||
def __init__(self, name, authorized_overdraft):
|
def __init__(self, name, authorized_overdraft):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.authorized_overdraft = authorized_overdraft
|
self.authorized_overdraft = authorized_overdraft
|
||||||
|
|
||||||
|
@ -14,28 +14,32 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
from . import db
|
from accountant import db
|
||||||
|
|
||||||
from .accounts import Account
|
from .accounts import Account
|
||||||
from .scheduled_operations import ScheduledOperation
|
from .scheduled_operations import ScheduledOperation
|
||||||
from sqlalchemy import func, desc
|
|
||||||
from sqlalchemy.orm import column_property
|
|
||||||
from sqlalchemy.sql import func, select
|
|
||||||
|
|
||||||
class Entry(db.Model):
|
class Entry(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
pointed = db.Column(db.Boolean, nullable = False, default = False)
|
pointed = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
operation_date = db.Column(db.Date, nullable = False)
|
operation_date = db.Column(db.Date, nullable=False)
|
||||||
label = db.Column(db.String(500), nullable = False)
|
label = db.Column(db.String(500), nullable=False)
|
||||||
value = db.Column(db.Numeric(15, 2), nullable = False)
|
value = db.Column(db.Numeric(15, 2), nullable=False)
|
||||||
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
|
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
|
||||||
scheduled_operation_id = db.Column(db.Integer, db.ForeignKey('scheduled_operation.id'))
|
scheduled_operation_id = db.Column(db.Integer,
|
||||||
|
db.ForeignKey('scheduled_operation.id'))
|
||||||
|
|
||||||
account = db.relationship(Account, backref = db.backref('entry', lazy="dynamic"))
|
account = db.relationship(Account, backref=db.backref('entry',
|
||||||
scheduled_operation = db.relationship(ScheduledOperation, backref = db.backref('entry', lazy="dynamic"))
|
lazy="dynamic"))
|
||||||
|
scheduled_operation = db.relationship(ScheduledOperation,
|
||||||
|
backref=db.backref('entry',
|
||||||
|
lazy="dynamic"))
|
||||||
|
|
||||||
category = db.Column(db.String(100), nullable = True)
|
category = db.Column(db.String(100), nullable=True)
|
||||||
|
|
||||||
def __init__(self, pointed, label, value, account_id, operation_date = None, category = None, scheduled_operation_id = None):
|
def __init__(self, pointed, label, value, account_id, operation_date=None,
|
||||||
|
category=None, scheduled_operation_id=None):
|
||||||
self.pointed = pointed
|
self.pointed = pointed
|
||||||
self.operation_date = operation_date
|
self.operation_date = operation_date
|
||||||
self.label = label
|
self.label = label
|
||||||
@ -43,4 +47,3 @@ class Entry(db.Model):
|
|||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
self.category = category
|
self.category = category
|
||||||
self.scheduled_operation_id = scheduled_operation_id
|
self.scheduled_operation_id = scheduled_operation_id
|
||||||
|
|
||||||
|
@ -14,35 +14,33 @@
|
|||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
along with Accountant. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
from . import db
|
from accountant import db
|
||||||
|
|
||||||
from .accounts import Account
|
from .accounts import Account
|
||||||
from .scheduled_operations import ScheduledOperation
|
|
||||||
|
|
||||||
from sqlalchemy import func, desc
|
|
||||||
from sqlalchemy.orm import column_property
|
|
||||||
from sqlalchemy.sql import func, select
|
|
||||||
|
|
||||||
class Operation(db.Model):
|
class Operation(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
pointed = db.Column(db.Boolean, nullable = False, default = False)
|
pointed = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
operation_date = db.Column(db.Date, nullable = False)
|
operation_date = db.Column(db.Date, nullable=False)
|
||||||
label = db.Column(db.String(500), nullable = False)
|
label = db.Column(db.String(500), nullable=False)
|
||||||
value = db.Column(db.Numeric(15, 2), nullable = False)
|
value = db.Column(db.Numeric(15, 2), nullable=False)
|
||||||
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
|
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
|
||||||
scheduled_operation_id = db.Column(db.Integer, db.ForeignKey('scheduled_operation.id'))
|
scheduled_operation_id = db.Column(db.Integer,
|
||||||
|
db.ForeignKey('scheduled_operation.id'))
|
||||||
|
|
||||||
account = db.relationship(Account, backref = db.backref('operation', lazy="dynamic"))
|
account = db.relationship(Account, backref=db.backref('operation',
|
||||||
|
lazy="dynamic"))
|
||||||
|
|
||||||
category = db.Column(db.String(100), nullable = True)
|
category = db.Column(db.String(100), nullable=True)
|
||||||
|
|
||||||
canceled = db.Column(db.Boolean, nullable = False)
|
canceled = db.Column(db.Boolean, nullable=False)
|
||||||
|
|
||||||
def __init__(self, pointed, label, value, account_id, operation_date = None, category = None):
|
def __init__(self, pointed, label, value, account_id, operation_date=None,
|
||||||
|
category=None):
|
||||||
self.pointed = pointed
|
self.pointed = pointed
|
||||||
self.operation_date = operation_date
|
self.operation_date = operation_date
|
||||||
self.label = label
|
self.label = label
|
||||||
self.value = value
|
self.value = value
|
||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
self.category = category
|
self.category = category
|
||||||
|
|
||||||
|
@ -1,24 +1,41 @@
|
|||||||
from . import db
|
"""
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
from accountant import db
|
||||||
|
|
||||||
from .accounts import Account
|
from .accounts import Account
|
||||||
from sqlalchemy import func, desc
|
|
||||||
from sqlalchemy.orm import column_property
|
|
||||||
from sqlalchemy.sql import func, select
|
|
||||||
|
|
||||||
class ScheduledOperation(db.Model):
|
class ScheduledOperation(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
start_date = db.Column(db.Date, nullable = False)
|
start_date = db.Column(db.Date, nullable=False)
|
||||||
stop_date = db.Column(db.Date, nullable = False)
|
stop_date = db.Column(db.Date, nullable=False)
|
||||||
day = db.Column(db.Integer, nullable = False)
|
day = db.Column(db.Integer, nullable=False)
|
||||||
frequency = db.Column(db.Integer, nullable = False)
|
frequency = db.Column(db.Integer, nullable=False)
|
||||||
label = db.Column(db.String(500), nullable = False)
|
label = db.Column(db.String(500), nullable=False)
|
||||||
value = db.Column(db.Numeric(15, 2), nullable = False)
|
value = db.Column(db.Numeric(15, 2), nullable=False)
|
||||||
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
|
account_id = db.Column(db.Integer, db.ForeignKey('account.id'))
|
||||||
|
|
||||||
account = db.relationship(Account, backref = db.backref('scheduled_operation', lazy="dynamic"))
|
account = db.relationship(Account, backref=db.backref('scheduled_operation',
|
||||||
|
lazy="dynamic"))
|
||||||
|
|
||||||
category = db.Column(db.String(100), nullable = True)
|
category = db.Column(db.String(100), nullable=True)
|
||||||
|
|
||||||
def __init__(self, start_date, stop_date, day, frequency, label, value, account_id, category = None):
|
def __init__(self, start_date, stop_date, day, frequency, label, value,
|
||||||
|
account_id, category=None):
|
||||||
self.start_date = start_date
|
self.start_date = start_date
|
||||||
self.stop_date = stop_date
|
self.stop_date = stop_date
|
||||||
self.day = day
|
self.day = day
|
||||||
@ -27,4 +44,3 @@ class ScheduledOperation(db.Model):
|
|||||||
self.value = value
|
self.value = value
|
||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
self.category = category
|
self.category = category
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user