#!/usr/bin/env python3 """ scripts/sync_enums.py Génère une migration SQL non destructive pour ajouter les valeurs d'ENUM manquantes en se basant sur les CSV de `bdd/data_test`. Usage: python3 scripts/sync_enums.py > migrations/00_sync_enums.sql Relire le SQL généré avant application en production. """ from pathlib import Path import csv from collections import defaultdict import sys # Mapping colonne CSV -> nom du type enum en base # NOTE: mapping is now based on filename (more precise) CSV_DIR = Path('bdd/data_test') # Define per-file mappings: filename stem -> {column_name: enum_type} FILE_COLUMN_ENUM_MAP = { 'utilisateurs': { 'role': 'role_type', 'genre': 'genre_type', 'statut': 'statut_utilisateur_type', }, 'enfants': { 'statut': 'statut_enfant_type', 'genre': 'genre_type', }, 'contrats': { 'statut': 'statut_contrat_type', }, 'dossiers': { 'statut': 'statut_dossier_type', }, 'evenements': { 'type': 'type_evenement_type', 'statut': 'statut_evenement_type', }, 'validations': { 'statut': 'statut_validation_type', } } def quote_sql_literal(s: str) -> str: return "'" + s.replace("'", "''") + "'" def discover_values(): # heuristique : map common column names to enums enum_values = defaultdict(set) for p in sorted(CSV_DIR.glob('*.csv')): try: with p.open(newline='', encoding='utf-8') as fh: reader = csv.DictReader(fh) fname = p.stem per_file_map = FILE_COLUMN_ENUM_MAP.get(fname, {}) for row in reader: for col, enum in per_file_map.items(): if col in row and row[col] is not None: v = row[col].strip() if v != '': enum_values[enum].add(v) except Exception as e: print(f"-- Error reading {p}: {e}", file=sys.stderr) return enum_values def emit_sql(enum_values): lines = [] lines.append('-- Generated by scripts/sync_enums.py — review before applying') for enum_type, vals in enum_values.items(): if not vals: continue for v in sorted(vals): lit = quote_sql_literal(v) block = f""" DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_enum e JOIN pg_type t ON e.enumtypid = t.oid WHERE t.typname = {quote_sql_literal(enum_type)} AND e.enumlabel = {lit} ) THEN ALTER TYPE {enum_type} ADD VALUE {lit}; END IF; END$$; """ lines.append(block) return '\n'.join(lines) def main(): enum_values = discover_values() sql = emit_sql(enum_values) print(sql) if __name__ == '__main__': main()