123 lines
4.6 KiB
SQL
123 lines
4.6 KiB
SQL
-- Backfill #103 : attribuer un numero_dossier aux entrées existantes (NULL)
|
|
-- Famille = lien co_parent OU partage d'au moins un enfant (même dossier).
|
|
-- Ordre : par année, AM puis familles (une entrée par famille), séquence 000001, 000002...
|
|
-- À exécuter après 2026_numero_dossier.sql
|
|
|
|
DO $$
|
|
DECLARE
|
|
yr INT;
|
|
seq INT;
|
|
num TEXT;
|
|
r RECORD;
|
|
family_user_ids UUID[];
|
|
BEGIN
|
|
-- Réinitialiser pour rejouer le backfill (cohérence AM + familles)
|
|
UPDATE parents SET numero_dossier = NULL;
|
|
UPDATE utilisateurs SET numero_dossier = NULL
|
|
WHERE role IN ('parent', 'assistante_maternelle');
|
|
UPDATE assistantes_maternelles SET numero_dossier = NULL;
|
|
|
|
FOR yr IN
|
|
SELECT DISTINCT EXTRACT(YEAR FROM u.cree_le)::INT
|
|
FROM utilisateurs u
|
|
WHERE (
|
|
(u.role = 'assistante_maternelle' AND u.numero_dossier IS NULL)
|
|
OR EXISTS (SELECT 1 FROM parents p WHERE p.id_utilisateur = u.id AND p.numero_dossier IS NULL)
|
|
)
|
|
ORDER BY 1
|
|
LOOP
|
|
seq := 0;
|
|
|
|
-- 1) AM : par ordre de création
|
|
FOR r IN
|
|
SELECT u.id
|
|
FROM utilisateurs u
|
|
WHERE u.role = 'assistante_maternelle'
|
|
AND u.numero_dossier IS NULL
|
|
AND EXTRACT(YEAR FROM u.cree_le) = yr
|
|
ORDER BY u.cree_le
|
|
LOOP
|
|
seq := seq + 1;
|
|
num := yr || '-' || LPAD(seq::TEXT, 6, '0');
|
|
UPDATE utilisateurs SET numero_dossier = num WHERE id = r.id;
|
|
UPDATE assistantes_maternelles SET numero_dossier = num WHERE id_utilisateur = r.id;
|
|
END LOOP;
|
|
|
|
-- 2) Familles : une entrée par "dossier" (co_parent OU enfants partagés)
|
|
-- family_rep = min(id) de la composante connexe (lien co_parent + partage d'enfants)
|
|
FOR r IN
|
|
WITH RECURSIVE
|
|
links AS (
|
|
SELECT p.id_utilisateur AS p1, p.id_co_parent AS p2 FROM parents p WHERE p.id_co_parent IS NOT NULL
|
|
UNION ALL
|
|
SELECT p.id_co_parent AS p1, p.id_utilisateur AS p2 FROM parents p WHERE p.id_co_parent IS NOT NULL
|
|
UNION ALL
|
|
SELECT ep1.id_parent AS p1, ep2.id_parent AS p2
|
|
FROM enfants_parents ep1
|
|
JOIN enfants_parents ep2 ON ep2.id_enfant = ep1.id_enfant AND ep1.id_parent < ep2.id_parent
|
|
UNION ALL
|
|
SELECT ep2.id_parent AS p1, ep1.id_parent AS p2
|
|
FROM enfants_parents ep1
|
|
JOIN enfants_parents ep2 ON ep2.id_enfant = ep1.id_enfant AND ep1.id_parent < ep2.id_parent
|
|
),
|
|
rec AS (
|
|
SELECT id_utilisateur AS id, id_utilisateur AS rep FROM parents
|
|
UNION
|
|
SELECT l.p2 AS id, LEAST(rec_alias.rep, l.p2) AS rep FROM links l JOIN rec rec_alias ON rec_alias.id = l.p1
|
|
),
|
|
family_rep AS (
|
|
SELECT id, MIN(rep::text)::uuid AS rep FROM rec GROUP BY id
|
|
),
|
|
fam_ordered AS (
|
|
SELECT fr.rep AS family_rep, MIN(u.cree_le) AS cree_le
|
|
FROM family_rep fr
|
|
JOIN parents p ON p.id_utilisateur = fr.id
|
|
JOIN utilisateurs u ON u.id = p.id_utilisateur
|
|
WHERE p.numero_dossier IS NULL
|
|
AND EXTRACT(YEAR FROM u.cree_le) = yr
|
|
GROUP BY fr.rep
|
|
ORDER BY MIN(u.cree_le)
|
|
)
|
|
SELECT fo.family_rep
|
|
FROM fam_ordered fo
|
|
LOOP
|
|
seq := seq + 1;
|
|
num := yr || '-' || LPAD(seq::TEXT, 6, '0');
|
|
|
|
WITH RECURSIVE
|
|
links AS (
|
|
SELECT p.id_utilisateur AS p1, p.id_co_parent AS p2 FROM parents p WHERE p.id_co_parent IS NOT NULL
|
|
UNION ALL
|
|
SELECT p.id_co_parent AS p1, p.id_utilisateur AS p2 FROM parents p WHERE p.id_co_parent IS NOT NULL
|
|
UNION ALL
|
|
SELECT ep1.id_parent AS p1, ep2.id_parent AS p2
|
|
FROM enfants_parents ep1
|
|
JOIN enfants_parents ep2 ON ep2.id_enfant = ep1.id_enfant AND ep1.id_parent < ep2.id_parent
|
|
UNION ALL
|
|
SELECT ep2.id_parent AS p1, ep1.id_parent AS p2
|
|
FROM enfants_parents ep1
|
|
JOIN enfants_parents ep2 ON ep2.id_enfant = ep1.id_enfant AND ep1.id_parent < ep2.id_parent
|
|
),
|
|
rec AS (
|
|
SELECT id_utilisateur AS id, id_utilisateur AS rep FROM parents
|
|
UNION
|
|
SELECT l.p2 AS id, LEAST(rec_alias.rep, l.p2) AS rep FROM links l JOIN rec rec_alias ON rec_alias.id = l.p1
|
|
),
|
|
family_rep AS (
|
|
SELECT id, MIN(rep::text)::uuid AS rep FROM rec GROUP BY id
|
|
)
|
|
SELECT array_agg(DISTINCT fr.id) INTO family_user_ids
|
|
FROM family_rep fr
|
|
WHERE fr.rep = r.family_rep;
|
|
|
|
UPDATE utilisateurs SET numero_dossier = num WHERE id = ANY(family_user_ids);
|
|
UPDATE parents SET numero_dossier = num WHERE id_utilisateur = ANY(family_user_ids);
|
|
END LOOP;
|
|
|
|
INSERT INTO numero_dossier_sequence (annee, prochain)
|
|
VALUES (yr, seq + 1)
|
|
ON CONFLICT (annee) DO UPDATE
|
|
SET prochain = GREATEST(numero_dossier_sequence.prochain, seq + 1);
|
|
END LOOP;
|
|
END $$;
|