Files
petitspas/database/docs/FK_POLICIES.md
T
2026-09-24 09:09:57 +00:00

6.7 KiB
Raw Blame History

FK_POLICIES.md

Politique des clés étrangères (ON DELETE / ON UPDATE) – Sprint 1

🎯 Objectif

Documenter, de façon unique et partagée, les règles de suppression/mise à jour appliquées aux clés étrangères de la base P’titsPas pour :

  • préserver l’intégrité référentielle ;
  • conserver l’historique utile (messages, événements…) ;
  • respecter les exigences RGPD (suppression en cascade lorsque pertinent).

Par défaut, ON UPDATE = NO ACTION (UUID immuables).
Ce document couvre ON DELETE table par table.


🧭 Principes généraux

  • CASCADE quand la donnée fille n’a pas de sens sans le parent
    (ex. dossiers d’un parent, avenants d’un contrat).
  • SET NULL quand on veut préserver l’historique mais que le référent peut disparaître
    (ex. auteur d’un message supprimé, créateur d’un événement).
  • RESTRICT/NO ACTION non utilisé ici pour éviter des blocages au nettoyage.

📚 Récapitulatif rapide (matrice)

Table (colonne FK) → Référence ON DELETE Raison
assistantes_maternelles(id_utilisateur) → utilisateurs(id) CASCADE Profil AM supprimé avec son compte
parents(id_utilisateur) → utilisateurs(id) CASCADE Extension parent supprimée avec son compte
parents(id_co_parent) → utilisateurs(id) SET NULL Conserver le parent principal si co-parent disparaît
enfants_parents(id_parent) → parents(id_utilisateur) CASCADE Nettoyage liaisons N:N
enfants_parents(id_enfant) → enfants(id) CASCADE Idem
enfants_assistantes_maternelles(id_am) → assistantes_maternelles(id_utilisateur) CASCADE Placement supprimé avec l’AM
enfants_assistantes_maternelles(id_enfant) → enfants(id) CASCADE Idem
enfants_assistantes_maternelles(cree_par) → utilisateurs(id) SET NULL Historique placement conservé
dossiers(id_parent) → parents(id_utilisateur) CASCADE Dossier n’a pas de sens sans parent
dossiers(id_enfant) → enfants(id) CASCADE Dossier n’a pas de sens sans enfant
messages(id_dossier) → dossiers(id) CASCADE Messages détruits avec le dossier
messages(id_expediteur) → utilisateurs(id) SET NULL Garder l’historique des échanges
contrats(id_dossier) → dossiers(id) CASCADE 1:1, contrat détruit si dossier supprimé
avenants_contrats(id_contrat) → contrats(id) CASCADE Avenants détruits avec le contrat
avenants_contrats(initie_par) → utilisateurs(id) SET NULL Historiser l’avenant sans bloquer
absences_garde(id_placement) → enfants_assistantes_maternelles(id) CASCADE Plus de couple = plus d’absences
absences_garde(cree_par) → utilisateurs(id) SET NULL Conserver la période si user supprimé
signalements_bugs(id_utilisateur) → utilisateurs(id) SET NULL Conserver le ticket même si compte supprimé
uploads(id_utilisateur) → utilisateurs(id) SET NULL Fichier reste référencé sans l’auteur
notifications(id_utilisateur) → utilisateurs(id) CASCADE Notifications propres à l’utilisateur
validations(id_utilisateur) → utilisateurs(id) SET NULL Garder l’historique de décision
validations(valide_par) → utilisateurs(id) SET NULL Décideur supprimé : la ligne reste

ON UPDATE : NO ACTION partout (les UUID ne changent pas).


🔎 Détail par domaine

Utilisateurs & extensions

  • assistantes_maternelles.id_utilisateur → CASCADE
  • parents.id_utilisateur → CASCADE
  • parents.id_co_parent → SET NULL (interdit d’être co-parent de soi-même via CHECK déjà posé)

Enfants & liaisons

  • enfants_parents.id_parent → CASCADE
  • enfants_parents.id_enfant → CASCADE

Dossiers & échanges

  • dossiers.id_parent → CASCADE
  • dossiers.id_enfant → CASCADE
  • messages.id_dossier → CASCADE
  • messages.id_expediteur → SET NULL

Contrats & avenants

  • contrats.id_dossier → CASCADE (unique 1:1)
  • avenants_contrats.id_contrat → CASCADE
  • avenants_contrats.initie_par → SET NULL

Événements

  • absences_garde.id_placement → CASCADE
  • absences_garde.cree_par → SET NULL

Divers

  • signalements_bugs.id_utilisateur → SET NULL
  • uploads.id_utilisateur → SET NULL
  • notifications.id_utilisateur → CASCADE
  • validations.id_utilisateur → SET NULL
  • validations.valide_par → SET NULL

🧪 Scénarios de test (exemples)

  1. Suppression d’un parent

    • Supprimer utilisateurs(id=parentX)
    • Attendu : parents (CASCADE), ses dossiers (CASCADE), messages liés aux dossiers (CASCADE) sont supprimés.
  2. Suppression d’un co-parent

    • Supprimer utilisateurs(id=coParentY)
    • Attendu : parents.id_co_parent passe à NULL, aucun dossier supprimé.
  3. Suppression d’un utilisateur auteur de messages

    • Supprimer utilisateurs(id=uZ)
    • Attendu : les lignes messages restent, id_expediteur devient NULL.
  4. Suppression d’un enfant

    • Supprimer enfants(id=childA)
    • Attendu : enfants_parents (CASCADE), dossiers du childA (CASCADE), absences_garde des placements du childA (CASCADE via EAM).
  5. Suppression d’un utilisateur AM

    • Supprimer utilisateurs(id=amB)
    • Attendu : absences liées via placement AM (CASCADE si le lien EAM est retiré).

🛠 Migrations associées

Les ajustements sont implémentés dans :

  • /bdd/migrations/04_fk_policies.sql
    – redéfinition des contraintes FK avec les bonnes politiques (DROP puis ADD CONSTRAINT), de façon idempotente.

📄 Notes & futures évolutions

  • RGPD (Sprint 2) : si vous activez le soft delete (deleted_at) côté tables métier, ces politiques restent valides (les suppressions logiques se gèrent au niveau applicatif).
  • Audit : si vous voulez tracer les suppressions, ajoutez des triggers d’audit (voir ticket Sprint 2 – Audit log).
  • Performance : chaque FK doit être indexée côté enfant (cf. 02_indexes.sql).

✅ Checklist de conformité

  • Toutes les FK listées existent dans la base
  • Politique ON DELETE conforme au tableau ci-dessus
  • ON UPDATE = NO ACTION partout
  • Tests de suppression réalisés sur une base seedée
  • 04_fk_policies.sql appliqué sans erreur

Mainteneur : Équipe BDD
Dernière mise à jour : Sprint 1 – Politique FK consolidée