from flask import Flask from flask_sqlalchemy import SQLAlchemy import tomllib import os import sqlalchemy as sa db = SQLAlchemy() def _migrate_db(app): """Applique les migrations de schéma manquantes (pas d'Alembic).""" import sqlite3 db_path = os.path.join(app.instance_path, "worklog.db") if not os.path.exists(db_path): return # Nouvelle DB, create_all() s'en charge conn = sqlite3.connect(db_path) tables = {row[0] for row in conn.execute("SELECT name FROM sqlite_master WHERE type='table'")} if "work_entries" not in tables: conn.close() return # Table pas encore créée, create_all() s'en charge columns = {row[1] for row in conn.execute("PRAGMA table_info(work_entries)").fetchall()} conn.close() with app.app_context(): engine = db.get_engine() if "motor_vehicle_id" not in columns: with engine.connect() as conn: conn.execute(sa.text( "ALTER TABLE work_entries ADD COLUMN motor_vehicle_id VARCHAR(64)" )) conn.commit() 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(): _migrate_db(app) db.create_all() return app