import sys, os sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) from app import create_app from sqlalchemy import text import sqlite3 SQLITE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'aufmass.db') # Tables in FK-safe order (parents first) TABLE_ORDER = [ 'companies', 'users', 'licenses', 'contracts', 'modules', 'aufmass_typen', 'projekte', 'custom_modules', 'company_modules', 'license_modules', 'aufmass', 'lv_positionen', 'positionen', 'project_access', 'custom_module_assignments', 'user_module_permissions', 'view_profiles', ] def main(): print("=" * 60) print("SQLite -> PostgreSQL Migration v2") print("=" * 60) if not os.path.exists(SQLITE_PATH): print(f"SQLite DB nicht gefunden: {SQLITE_PATH}") return # Read all SQLite data print("\n1. Lese SQLite-Daten...") conn = sqlite3.connect(SQLITE_PATH) conn.row_factory = sqlite3.Row c = conn.cursor() sqlite_data = {} for table_name in TABLE_ORDER: c.execute(f'SELECT * FROM "{table_name}"') rows = [dict(r) for r in c.fetchall()] sqlite_data[table_name] = rows print(f" {table_name}: {len(rows)} Zeilen") conn.close() # Create Flask app -> creates PG tables + seed defaults print("\n2. Starte Flask-App mit PostgreSQL...") app = create_app() with app.app_context(): from app import db # Delete all existing data in reverse FK order print(" Entferne vorhandene Daten...") with db.engine.connect() as c: for table_name in reversed(TABLE_ORDER): c.execute(text(f'DELETE FROM "{table_name}"')) c.commit() # Import in FK-safe order print("\n3. Importiere Daten in FK-Reihenfolge...") meta = __import__('sqlalchemy', fromlist=['MetaData']).MetaData() meta.reflect(bind=db.engine) total_ok = 0 total_fail = 0 for table_name in TABLE_ORDER: rows = sqlite_data.get(table_name, []) if not rows: print(f" -- {table_name}: keine Daten") continue table = __import__('sqlalchemy', fromlist=['Table']).Table(table_name, meta, autoload_with=db.engine) pg_cols = {c.name for c in table.columns} ok = 0 fail = 0 with db.engine.connect() as pg_conn: for row in rows: filtered = {k: v for k, v in row.items() if k in pg_cols} try: pg_conn.execute(table.insert().values(**filtered)) ok += 1 except Exception as e: fail += 1 if fail <= 2: print(f" Fehler {table_name} ID={row.get('id','?')}: {e}") pg_conn.commit() total_ok += ok total_fail += fail status = "+" if ok else " " print(f" {status} {table_name}: {ok}/{len(rows)} OK" + (f" ({fail} Fehler)" if fail else "")) print(f"\nErgebnis: {total_ok} Zeilen importiert" + (f", {total_fail} Fehler" if total_fail else "")) print("\nFertig! Starte Flask-App neu -> _seed_defaults() ergaenzt Seed-Daten via Upsert.") print("PostgreSQL ist bereit fuer AufmassWeb.") if __name__ == '__main__': main()