diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..b9200be --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,39 @@ +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +import tomllib +import os + +db = SQLAlchemy() + + +def create_app(config_path=None): + app = Flask(__name__, instance_relative_config=True) + + os.makedirs(app.instance_path, exist_ok=True) + + app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{os.path.join(app.instance_path, 'worklog.db')}" + app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False + app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", "dev-secret-change-in-prod") + + # Load TOML config + if config_path is None: + config_path = os.path.join(os.path.dirname(app.root_path), "config.toml") + if os.path.exists(config_path): + with open(config_path, "rb") as f: + app.config["TOML"] = tomllib.load(f) + else: + app.config["TOML"] = {} + + db.init_app(app) + + from app.routes.dashboard import bp as dashboard_bp + from app.routes.entries import bp as entries_bp + from app.routes.reports import bp as reports_bp + app.register_blueprint(dashboard_bp) + app.register_blueprint(entries_bp) + app.register_blueprint(reports_bp) + + with app.app_context(): + db.create_all() + + return app diff --git a/app/__pycache__/__init__.cpython-314.pyc b/app/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..18f3f04 Binary files /dev/null and b/app/__pycache__/__init__.cpython-314.pyc differ diff --git a/app/routes/__init__.py b/app/routes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/routes/__pycache__/__init__.cpython-314.pyc b/app/routes/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000..6646206 Binary files /dev/null and b/app/routes/__pycache__/__init__.cpython-314.pyc differ diff --git a/app/routes/__pycache__/dashboard.cpython-314.pyc b/app/routes/__pycache__/dashboard.cpython-314.pyc new file mode 100644 index 0000000..a77957a Binary files /dev/null and b/app/routes/__pycache__/dashboard.cpython-314.pyc differ diff --git a/app/routes/__pycache__/entries.cpython-314.pyc b/app/routes/__pycache__/entries.cpython-314.pyc new file mode 100644 index 0000000..79abadc Binary files /dev/null and b/app/routes/__pycache__/entries.cpython-314.pyc differ diff --git a/app/routes/__pycache__/reports.cpython-314.pyc b/app/routes/__pycache__/reports.cpython-314.pyc new file mode 100644 index 0000000..b396342 Binary files /dev/null and b/app/routes/__pycache__/reports.cpython-314.pyc differ diff --git a/app/routes/dashboard.py b/app/routes/dashboard.py new file mode 100644 index 0000000..4d4aeca --- /dev/null +++ b/app/routes/dashboard.py @@ -0,0 +1,3 @@ +from flask import Blueprint + +bp = Blueprint("dashboard", __name__) diff --git a/app/routes/entries.py b/app/routes/entries.py new file mode 100644 index 0000000..43e234f --- /dev/null +++ b/app/routes/entries.py @@ -0,0 +1,3 @@ +from flask import Blueprint + +bp = Blueprint("entries", __name__) diff --git a/app/routes/reports.py b/app/routes/reports.py new file mode 100644 index 0000000..3d64de4 --- /dev/null +++ b/app/routes/reports.py @@ -0,0 +1,3 @@ +from flask import Blueprint + +bp = Blueprint("reports", __name__) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8729b75 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +flask>=3.0 +flask-sqlalchemy>=3.1 +pytest>=8.0 +pytest-flask>=1.3 +gunicorn>=22.0 diff --git a/run.py b/run.py new file mode 100644 index 0000000..488dae9 --- /dev/null +++ b/run.py @@ -0,0 +1,6 @@ +from app import create_app + +app = create_app() + +if __name__ == "__main__": + app.run(debug=True) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..baaeee7 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,60 @@ +import pytest +from app import create_app, db as _db + + +@pytest.fixture +def app(tmp_path): + config_path = tmp_path / "config.toml" + config_path.write_text(""" +[vehicles.voiture] +name = "Peugeot 308" +fuel = "diesel" +co2_per_km = 142 +cv = 5 + +[vehicles.velo] +name = "Vélo" +fuel = "none" +co2_per_km = 0 + +[journeys.voiture_seule] +name = "Voiture seule" +distances = { voiture = 25 } + +[journeys.voiture_velo] +name = "Voiture + Vélo" +distances = { voiture = 14, velo = 8 } + +[journeys.velo_seul] +name = "Vélo seul" +distances = { velo = 24 } + +[[bareme_kilometrique.2025.cv_5.tranches]] +km_max = 3000 +taux = 0.548 +forfait = 0 + +[[bareme_kilometrique.2025.cv_5.tranches]] +km_max = 6000 +taux = 0.316 +forfait = 699 + +[[bareme_kilometrique.2025.cv_5.tranches]] +km_max = 0 +taux = 0.364 +forfait = 0 +""", encoding="utf-8") + + application = create_app(config_path=str(config_path)) + application.config["TESTING"] = True + application.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:" + + with application.app_context(): + _db.create_all() + yield application + _db.drop_all() + + +@pytest.fixture +def client(app): + return app.test_client()