-- Migration : import du planning de patching annuel depuis Excel -- Tables : -- patch_planning_imports : 1 ligne par fichier xlsx importe -- patch_planning_import_rows : 1 ligne par serveur d'une feuille (semaine) -- Idempotent -- 1) Table parente : entête du fichier importé CREATE TABLE IF NOT EXISTS public.patch_planning_imports ( id SERIAL PRIMARY KEY, filename text NOT NULL, year integer, sheet_count integer NOT NULL DEFAULT 0, row_count integer NOT NULL DEFAULT 0, uploaded_by integer REFERENCES public.users(id) ON DELETE SET NULL, uploaded_at timestamptz NOT NULL DEFAULT now(), note text ); CREATE INDEX IF NOT EXISTS idx_pp_imports_year ON public.patch_planning_imports(year); CREATE INDEX IF NOT EXISTS idx_pp_imports_uploaded_at ON public.patch_planning_imports(uploaded_at DESC); -- 2) Table fille : 1 ligne = 1 serveur dans une feuille (S02, S03...) -- On stocke les colonnes connues + raw_data JSONB pour rester souple CREATE TABLE IF NOT EXISTS public.patch_planning_import_rows ( id SERIAL PRIMARY KEY, import_id integer NOT NULL REFERENCES public.patch_planning_imports(id) ON DELETE CASCADE, sheet_name text NOT NULL, -- 'S02', 'S03'... week_number integer, -- extrait de sheet_name (ex 2, 3...) row_index integer NOT NULL, -- position dans la feuille (1 = 1ere ligne data) asset_name text, intervenant text, environnement text, domaine text, os text, os_version text, application_name text, valideur_ra text, description text, assistant text, commentaire text, duree_coupure text, jour date, heure text, pb_espace_disque boolean, date_patch_realise date, raw_data jsonb, -- toutes les colonnes brutes (filet de sécurité) server_id integer REFERENCES public.servers(id) ON DELETE SET NULL, -- résolu si match hostname created_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_pp_import_rows_import ON public.patch_planning_import_rows(import_id); CREATE INDEX IF NOT EXISTS idx_pp_import_rows_sheet ON public.patch_planning_import_rows(import_id, sheet_name); CREATE INDEX IF NOT EXISTS idx_pp_import_rows_asset ON public.patch_planning_import_rows(asset_name); CREATE INDEX IF NOT EXISTS idx_pp_import_rows_week ON public.patch_planning_import_rows(week_number); -- 3) GRANT pour le user applicatif GRANT SELECT, INSERT, UPDATE, DELETE ON public.patch_planning_imports TO patchcenter; GRANT SELECT, INSERT, UPDATE, DELETE ON public.patch_planning_import_rows TO patchcenter; GRANT USAGE, SELECT ON SEQUENCE public.patch_planning_imports_id_seq TO patchcenter; GRANT USAGE, SELECT ON SEQUENCE public.patch_planning_import_rows_id_seq TO patchcenter;