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

144 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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