""" Migration idempotente per sandbox. Base.metadata.create_all() crea solo tabelle mancanti, non colonne aggiuntive. Qui gestiamo ALTER TABLE ADD COLUMN IF NOT EXISTS per l'evoluzione dello schema. Ogni migration รจ una stringa SQL che puo essere eseguita piu volte senza errori. """ from sqlalchemy import text import logging log = logging.getLogger("rendicontazione-api.migrations") MIGRATIONS = [ # 2026-04-18: colonne file upload su remission_invoice """ ALTER TABLE gepafin_rendic.remission_invoice ADD COLUMN IF NOT EXISTS storage_path varchar(1024), ADD COLUMN IF NOT EXISTS mime varchar(128), ADD COLUMN IF NOT EXISTS size_bytes bigint, ADD COLUMN IF NOT EXISTS sha256 varchar(64), ADD COLUMN IF NOT EXISTS uploaded_by integer, ADD COLUMN IF NOT EXISTS uploaded_at timestamptz; """, # 2026-04-18: colonne file upload su remission_ula_employee """ ALTER TABLE gepafin_rendic.remission_ula_employee ADD COLUMN IF NOT EXISTS storage_path varchar(1024), ADD COLUMN IF NOT EXISTS mime varchar(128), ADD COLUMN IF NOT EXISTS size_bytes bigint, ADD COLUMN IF NOT EXISTS sha256 varchar(64), ADD COLUMN IF NOT EXISTS uploaded_by integer, ADD COLUMN IF NOT EXISTS uploaded_at timestamptz; """, # 2026-04-18: colonne file upload su remission_document """ ALTER TABLE gepafin_rendic.remission_document ADD COLUMN IF NOT EXISTS storage_path varchar(1024), ADD COLUMN IF NOT EXISTS mime varchar(128), ADD COLUMN IF NOT EXISTS size_bytes bigint, ADD COLUMN IF NOT EXISTS sha256 varchar(64), ADD COLUMN IF NOT EXISTS uploaded_by integer; """, ] def run_migrations(engine) -> None: """Esegue tutte le migration in transazione. Log su ciascuna.""" with engine.begin() as conn: for i, sql in enumerate(MIGRATIONS, 1): try: conn.execute(text(sql)) log.info(f"migration {i}/{len(MIGRATIONS)} OK") except Exception as e: log.error(f"migration {i} FAILED: {e}") raise