Files
petitspas/database/docs/FK_POLICIES.md
T
jmartinandCursor d7783badca feat(#193): table absences_garde + drop evenements.
Vérité métier absences/congés/arrêt par placement (périodes, expire_at).
Entité TypeORM, BDD.sql, docs enums/FK, seed et verify alignés.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 11:09:39 +02: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 PtitsPas 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 **na pas de sens sans le parent**
(ex. `dossiers` dun parent, `avenants` dun contrat).
- **SET NULL** quand on veut **préserver lhistorique** mais que le référent peut disparaître
(ex. auteur dun message supprimé, créateur dun é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 lAM |
| **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 na pas de sens sans parent |
| **dossiers(id_enfant)**`enfants(id)` | **CASCADE** | Dossier na 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 lhistorique 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 lavenant sans bloquer |
| **absences_garde(id_placement)**`enfants_assistantes_maternelles(id)` | **CASCADE** | Plus de couple = plus dabsences |
| **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 lauteur |
| **notifications(id_utilisateur)**`utilisateurs(id)` | **CASCADE** | Notifications propres à lutilisateur |
| **validations(id_utilisateur)**`utilisateurs(id)` | **SET NULL** | Garder lhistorique 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 dun parent**
- Supprimer `utilisateurs(id=parentX)`
- Attendu : `parents` (CASCADE), ses `dossiers` (CASCADE), `messages` liés aux `dossiers` (CASCADE) sont supprimés.
2. **Suppression dun co-parent**
- Supprimer `utilisateurs(id=coParentY)`
- Attendu : `parents.id_co_parent` passe à **NULL**, aucun dossier supprimé.
3. **Suppression dun utilisateur auteur de messages**
- Supprimer `utilisateurs(id=uZ)`
- Attendu : les lignes `messages` **restent**, `id_expediteur` devient **NULL**.
4. **Suppression dun enfant**
- Supprimer `enfants(id=childA)`
- Attendu : `enfants_parents` (CASCADE), `dossiers` du childA (CASCADE), `absences_garde` des placements du childA (CASCADE via EAM).
5. **Suppression dun 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 daudit (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