diff --git a/api/__init__.py b/api/__init__.py
index e69de29..c1bb42d 100644
--- a/api/__init__.py
+++ b/api/__init__.py
@@ -0,0 +1,6 @@
+from flask import Blueprint
+
+api = Blueprint('api', __name__)
+
+from .controller import *
+
diff --git a/api/controller/__init__.py b/api/controller/__init__.py
index e69de29..252bd63 100644
--- a/api/controller/__init__.py
+++ b/api/controller/__init__.py
@@ -0,0 +1,9 @@
+import pkgutil
+
+__all__ = []
+
+for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
+ __all__.append(module_name)
+
+from . import *
+
diff --git a/api/controller/accounts.py b/api/controller/accounts.py
index dbdb403..15392fe 100644
--- a/api/controller/accounts.py
+++ b/api/controller/accounts.py
@@ -14,18 +14,15 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see .
"""
-from app import app
-from app import db
-
-from api.model.accounts import Account
-from api.model.entries import Entry
-from api.model.operations import Operation
-
+from .. import api
+from ..model import db
+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
-@app.route("/api/accounts", methods=["GET"])
+@api.route("/accounts", methods=["GET"])
def get_accounts():
"""
Returns accounts with their solds.
@@ -50,7 +47,7 @@ def get_accounts():
"future": str(i.future)
} for i in query.all()])
-@app.route("/api/accounts////")
+@api.route("/accounts////")
def get_account_status(account_id, year, month):
session = db.session
@@ -80,7 +77,7 @@ def get_account_status(account_id, year, month):
"balance": str(balance)
})
-@app.route("/api/accounts//months")
+@api.route("/accounts//months")
def get_months(account_id):
session = db.session
@@ -94,7 +91,7 @@ def get_months(account_id):
"month": i.month.rjust(2, '0')
} for i in query.all()])
-@app.route("/api/accounts", methods=["PUT"])
+@api.route("/accounts", methods=["PUT"])
def add_account():
session = db.session
@@ -110,7 +107,7 @@ def add_account():
raise
-@app.route("/api/accounts/", methods=["PUT"])
+@api.route("/accounts/", methods=["PUT"])
def update_account(account_id):
session = db.session
@@ -128,16 +125,16 @@ def update_account(account_id):
session.rollback()
raise
-@app.route("/api/accounts/", methods=["DELETE"])
+@api.route("/accounts/", methods=["DELETE"])
def delete_account(account_id):
session = db.session
try:
account = session.query(Account).filter(Account.id == account_id).first()
-
+
session.delete(account)
session.commit()
-
+
return json.dumps("Account #%s deleted." % account_id)
except:
session.rollback()
diff --git a/api/controller/entries.py b/api/controller/entries.py
index 3151380..c4351cd 100644
--- a/api/controller/entries.py
+++ b/api/controller/entries.py
@@ -14,23 +14,18 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see .
"""
-from app import app
-from app import db
-
-from api.model.entries import Entry
-from api.model.operations import Operation
-from api.model.scheduled_operations import ScheduledOperation
-
+from .. import api
+from ..model import db
+from ..model.entries import Entry
+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
-#from sqlalchemy import *
-
-from flask import json, request
-
-@app.route("/api/entries///")
+@api.route("/entries///")
def get_entries(account_id, year, month):
"""
Return entries for an account, year, and month.
@@ -61,7 +56,7 @@ def get_entries(account_id, year, month):
"scheduled_operation_id": i.scheduled_operation_id
} for i in query.all()])
-@app.route("/api/entries", methods=["PUT"])
+@api.route("/entries", methods=["PUT"])
def add_entry():
session = db.session
@@ -75,22 +70,22 @@ def add_entry():
account_id = request.json['account_id'],
scheduled_operation_id = request.json['scheduled_operation_id']
)
-
+
session.add(entry)
session.commit()
-
+
return json.dumps("Entry added.")
except:
session.rollback()
raise
-@app.route("/api/entries/", methods=["PUT"])
+@api.route("/entries/", methods=["PUT"])
def update_entry(entry_id):
session = db.session
try:
entry = session.query(Entry).filter(Entry.id == entry_id).first()
-
+
entry.id = entry_id
entry.operation_date = request.json['operation_date']
entry.pointed = request.json['pointed']
@@ -99,25 +94,25 @@ def update_entry(entry_id):
entry.category = request.json['category']
entry.account_id = request.json['account_id']
entry.scheduled_operation_id = request.json['scheduled_operation_id']
-
+
session.merge(entry)
session.commit()
-
+
return json.dumps("Entry #%s updated." % entry_id)
except:
session.rollback()
raise
-@app.route("/api/entries/", methods=["DELETE"])
+@api.route("/entries/", methods=["DELETE"])
def delete_entry(entry_id):
session = db.session
try:
entry = session.query(Entry).filter(Entry.id == entry_id).first()
-
+
session.delete(entry)
session.commit()
-
+
return json.dumps("Entry #%s deleted." % entry_id)
except:
session.rollback()
diff --git a/api/controller/scheduled_operations.py b/api/controller/scheduled_operations.py
index 517f0ba..ece482e 100644
--- a/api/controller/scheduled_operations.py
+++ b/api/controller/scheduled_operations.py
@@ -1,16 +1,13 @@
-from app import app
-from app import db
-
-from api.model.scheduled_operations import ScheduledOperation
-
+from .. import api
+from ..model import db
+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
from sqlalchemy.sql import func, select
-from flask import json, request
-
-@app.route("/api/scheduled_operations/")
+@api.route("/scheduled_operations/")
def get_scheduled_operations(account_id):
"""
Return entries for an account, year, and month.
@@ -41,7 +38,7 @@ def get_scheduled_operations(account_id):
"account_id": i.account_id
} for i in query.all()])
-@app.route("/api/scheduled_operations", methods=["PUT"])
+@api.route("/scheduled_operations", methods=["PUT"])
def add_scheduled_operation():
session = db.session
@@ -56,22 +53,22 @@ def add_scheduled_operation():
category = request.json['category'],
account_id = request.json['account_id']
)
-
+
session.add(scheduledOperation)
session.commit()
-
+
return json.dumps("Scheduled operation added.")
except:
session.rollback()
raise
-@app.route("/api/scheduled_operations/", methods=["PUT"])
+@api.route("/scheduled_operations/", methods=["PUT"])
def update_scheduled_operation(scheduled_operation_id):
session = db.session
try:
scheduledOperation = session.query(ScheduledOperation).filter(ScheduledOperation.id == scheduled_operation_id).first()
-
+
scheduledOperation.id = scheduled_operation_id
scheduledOperation.start_date = request.json['start_date'],
scheduledOperation.stop_date = request.json['stop_date'],
@@ -81,25 +78,25 @@ def update_scheduled_operation(scheduled_operation_id):
scheduledOperation.value = request.json['value']
scheduledOperation.category = request.json['category']
scheduledOperation.account_id = request.json['account_id']
-
+
session.merge(scheduledOperation)
session.commit()
-
+
return json.dumps("Scheduled operation #%s updated." % scheduled_operation_id)
except:
session.rollback()
raise
-@app.route("/api/scheduled_operations/", methods=["DELETE"])
+@api.route("/scheduled_operations/", methods=["DELETE"])
def delete_scheduled_operation(scheduled_operation_id):
session = db.session
try:
scheduledOperation = session.query(ScheduledOperation).filter(ScheduledOperation.id == scheduled_operation_id).first()
-
+
session.delete(scheduledOperation)
session.commit()
-
+
return json.dumps("Scheduled operation #%s deleted." % scheduled_operation_id)
except:
session.rollback()
diff --git a/api/model/__init__.py b/api/model/__init__.py
index e69de29..d54dbd0 100644
--- a/api/model/__init__.py
+++ b/api/model/__init__.py
@@ -0,0 +1,31 @@
+from contextlib import contextmanager
+from flask.ext.sqlalchemy import SQLAlchemy
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import scoped_session, sessionmaker
+
+db = SQLAlchemy()
+
+@contextmanager
+def session_scope(engine):
+ if engine:
+ session = scoped_session(sessionmaker(autocommit = False, autoflush = False, bind = engine))
+ #Base.query = session.query_property()
+
+ try:
+ yield session
+ session.commit()
+ except:
+ session.rollback()
+ raise
+ finally:
+ session.close()
+
+import pkgutil
+
+__all__ = []
+
+for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
+ __all__.append(module_name)
+
+from . import *
+
diff --git a/api/model/accounts.py b/api/model/accounts.py
index c0a7439..1bbbaf1 100644
--- a/api/model/accounts.py
+++ b/api/model/accounts.py
@@ -14,8 +14,7 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see .
"""
-from app import app
-from app import db
+from . import db
class Account(db.Model):
id = db.Column(db.Integer, primary_key = True)
diff --git a/api/model/entries.py b/api/model/entries.py
index bbb7ade..e6f81a2 100644
--- a/api/model/entries.py
+++ b/api/model/entries.py
@@ -14,12 +14,9 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see .
"""
-from app import app
-from app import db
-
-from api.model.accounts import Account
-from api.model.scheduled_operations import ScheduledOperation
-
+from . import db
+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
diff --git a/api/model/operations.py b/api/model/operations.py
index 49e02b9..a9f6f1a 100644
--- a/api/model/operations.py
+++ b/api/model/operations.py
@@ -14,11 +14,10 @@
You should have received a copy of the GNU Affero General Public License
along with Accountant. If not, see .
"""
-from app import app
-from app import db
+from . import db
-from api.model.accounts import Account
-from api.model.scheduled_operations import ScheduledOperation
+from .accounts import Account
+from .scheduled_operations import ScheduledOperation
from sqlalchemy import func, desc
from sqlalchemy.orm import column_property
diff --git a/api/model/scheduled_operations.py b/api/model/scheduled_operations.py
index 163791d..e1bafa1 100644
--- a/api/model/scheduled_operations.py
+++ b/api/model/scheduled_operations.py
@@ -1,8 +1,5 @@
-from app import app
-from app import db
-
-from api.model.accounts import Account
-
+from . import db
+from .accounts import Account
from sqlalchemy import func, desc
from sqlalchemy.orm import column_property
from sqlalchemy.sql import func, select
diff --git a/app.py b/app.py
index 82c12cf..5b0bedb 100644
--- a/app.py
+++ b/app.py
@@ -18,13 +18,19 @@
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy.orm import sessionmaker
+from frontend import frontend
+from api import api
+from api.model import db
import config
# The app
-app = Flask(__name__)
+app = Flask(__name__, static_folder = None)
app.config['SQLALCHEMY_DATABASE_URI'] = config.db_uri
app.config['SQLALCHEMY_RECORD_QUERIES'] = config.debug
-db = SQLAlchemy(app)
+db.init_app(app)
+
+app.register_blueprint(frontend, url_prefix='')
+app.register_blueprint(api, url_prefix='/api')
diff --git a/main.py b/main.py
deleted file mode 100644
index 6f0e483..0000000
--- a/main.py
+++ /dev/null
@@ -1,43 +0,0 @@
-"""
- 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 app import app
-
-from api.controller.entries import *
-from api.controller.accounts import *
-from api.controller.scheduled_operations import *
-
-from flask import redirect, render_template, jsonify
-
-@app.route('/')
-def root():
- return redirect('index.html')
-
-@app.route('/index.html')
-def index():
- return render_template('index.html')
-
-@app.route('/scheduler.html')
-def scheduler():
- return render_template('scheduler.html')
-
-@app.errorhandler(BaseException)
-def default_errorhandler(error):
- return jsonify(title="Error", text="Error %s" % str(error)), 500
-
-if __name__ == '__main__':
- app.run(debug=True)
-
diff --git a/manage.py b/manage.py
new file mode 100644
index 0000000..4bfd013
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,10 @@
+from flask.ext.script import Manager
+from flask.ext.migrate import Migrate, MigrateCommand
+
+from app import app
+
+manager = Manager(app)
+manager.add_command('db', MigrateCommand)
+
+if __name__ == "__main__":
+ manager.run()