Téléverser les fichiers vers "/"
This commit is contained in:
parent
96ae868cf4
commit
a36da6a5f3
142
FK_POLICIES.md
Normal file
142
FK_POLICIES.md
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
|
||||||
|
# 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 |
|
||||||
|
| **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 |
|
||||||
|
| **evenements(id_enfant)** → `enfants(id)` | **CASCADE** | Événements n’ont plus de sens |
|
||||||
|
| **evenements(id_am)** → `utilisateurs(id)` | **SET NULL** | Garder la trace même si AM supprimée |
|
||||||
|
| **evenements(id_parent)** → `parents(id_utilisateur)` | **SET NULL** | Garder la trace si parent supprimé |
|
||||||
|
| **evenements(cree_par)** → `utilisateurs(id)` | **SET NULL** | Conserver l’historique de création |
|
||||||
|
| **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 |
|
||||||
|
|
||||||
|
> **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
|
||||||
|
- `evenements.id_enfant` → **CASCADE**
|
||||||
|
- `evenements.id_am` → **SET NULL**
|
||||||
|
- `evenements.id_parent` → **SET NULL**
|
||||||
|
- `evenements.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**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 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), `evenements` du childA (CASCADE).
|
||||||
|
|
||||||
|
5. **Suppression d’un utilisateur AM**
|
||||||
|
- Supprimer `utilisateurs(id=amB)`
|
||||||
|
- Attendu : `evenements.id_am` devient **NULL** (historique conservé).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠 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
|
||||||
Loading…
x
Reference in New Issue
Block a user