feat(#131): fiches parent/AM éditable, placement AM↔enfant, statuts garde/sans_garde

Squash merge develop → master.

- Fiche parent éditable (co-parent, PATCH fiche, GET /parents)
- Fiche AM 3 onglets (PATCH fiche, rattacher/détacher enfants)
- Table enfants_assistantes_maternelles + enum garde/sans_garde
- Migration SQL + BDD.sql canonique
- Correctifs recette : @Get() parents, DTO fiche AM, fix NIR

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-11 22:49:57 +02:00
co-authored by Cursor
parent b99745e0fe
commit 003fe6b762
69 changed files with 6290 additions and 417 deletions
+3 -2
View File
@@ -36,6 +36,7 @@ Ce fichier sert d'index pour naviguer dans toute la documentation du projet.
- [**23 - Liste des Tickets**](./23_LISTE-TICKETS.md) - 61 tickets Phase 1 détaillés
- [**24 - Décisions Projet**](./24_DECISIONS-PROJET.md) - Décisions architecturales et fonctionnelles
- [**25 - Backlog Phase 2**](./25_PHASE-2-BACKLOG.md) - Fonctionnalités techniques reportées
- [**28 - Évolution famille et responsables**](./28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md) - Modèle dossier/famille, recompositions, v1.0.0 vs post-1.0.0
- [**26 - API Gitea**](./26_GITEA-API.md) - Procédure d'utilisation de l'API Gitea (issues, PR, branches, labels)
- [**27 - Briefing frontend**](./27_BRIEFING-FRONTEND.md) - Accès Git, priorités, scripts Gitea (token)
@@ -49,7 +50,7 @@ Fichiers **sans préfixe numérique** encore à la racine par **héritage** ou
références outils (`.cursorrules`, etc.) — **à renommer** en `NN_` quand
possible :
- `CHARTE_GRAPHIQUE.md`
- `EVOLUTIONS_CDC.md`
- [`EVOLUTIONS_CDC.md`](./EVOLUTIONS_CDC.md) — écarts CDC / app ; voir aussi [**28 - Évolution famille**](./28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md)
- `SuperNounou_Cahier_Des_Charges_Complet_V1.1.md`
- `SuperNounou_SSS-001.md`
@@ -89,5 +90,5 @@ PgAdmin: https://app.ptits-pas.fr/pgadmin
Cette documentation est maintenue par Julien Martin (julien.martin@ptits-pas.fr).
Dernière mise à jour : Novembre 2025
Dernière mise à jour : Juin 2026
+28 -4
View File
@@ -1,7 +1,7 @@
# 📋 Décisions Projet - P'titsPas
**Version** : 1.1
**Date** : 9 Février 2026
**Version** : 1.2
**Date** : 16 Juin 2026
**Auteur** : Équipe PtitsPas
---
@@ -122,6 +122,27 @@ ptitspas-app/
---
### 5bis. Familles recomposées — contournement v1.0.0
**Décision** : ✅ **Second compte / second email pour les cas multi-contextes en v1.0.0** ; évolution structurelle reportée post-1.0.0
**Contexte** :
- Le numéro de dossier et le graphe « famille » (co-parent + enfants partagés) conviennent aux cas simples (un couple, N enfants).
- Ils ne couvrent pas proprement une même personne responsable dans **plusieurs unités familiales** (recompositions, plusieurs co-responsables successifs, tuteur/GP sur plusieurs contextes).
**Décision v1.0.0** :
- **Contournement opérationnel** : créer un **second compte** avec **email distinct** et un **second numéro de dossier** (souvent via le gestionnaire).
- Le numéro de dossier reste la **norme** pour les cas simples, **sans obligation absolue** pour les cas complexes.
- Rôle applicatif unique **`parent`** pour tous les responsables (tuteur, GP inclus) ; qualification juridique = évolution ultérieure.
**Évolution post-1.0.0** :
- **Parcours gestionnaire « famille complexe »** (§ 7.5 doc 28) : N responsables, **M un seul compte** avec tous ses enfants ; **A / B** limités à leur enfant via `enfants_parents`.
- Visibilité et workflows **sans fusion graphe familial** ; numéro de dossier optionnel ; qualification du lien responsableenfant.
**Référence** : [28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md](./28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md) — § 4.4, § 7.5
---
### 6. Genre enfant obligatoire (H/F)
**Décision** : ✅ **Genre obligatoire (H/F uniquement)**
@@ -562,6 +583,7 @@ docs/
| 14 | Migration données | ❌ Rejeté | N/A |
| 15 | Doc utilisateur | ⏸️ Phase 2 | Formation |
| 31 | Logs Winston | ✅ Phase 1 | Monitoring |
| 5bis | Familles recomposées — 2ᵉ compte v1.0.0 | ✅ v1.0.0 | Métier / dossier |
---
@@ -571,10 +593,12 @@ docs/
|------|---------|---------------|
| 25/11/2025 | 1.0 | Création du document - Toutes les décisions initiales |
| 09/02/2026 | 1.1 | Configuration initiale : un seul panneau Paramètres (3 sections) dans le dashboard, plus de Setup Wizard dédié ; navigation bloquée jusqu'à sauvegarde |
| 16/06/2026 | 1.2 | Décision 5bis — familles recomposées, contournement v1.0.0 ; lien doc [28](./28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md) |
| 16/06/2026 | 1.3 | Précision 5bis — cible post-1.0.0 : parcours gestionnaire § 7.5 (#139), visibilité par enfant |
---
**Dernière mise à jour** : 9 Février 2026
**Version** : 1.1
**Dernière mise à jour** : 16 Juin 2026
**Version** : 1.2
**Statut** : ✅ Document validé
@@ -0,0 +1,331 @@
# Évolution — Modèle famille, responsables légaux et dossiers
**Version** : 1.1
**Date** : 16 juin 2026
**Statut** : Réflexions produit / architecture — complément au [CDC](./01_CAHIER-DES-CHARGES.md)
**Documents liés** : [EVOLUTIONS_CDC.md](./EVOLUTIONS_CDC.md), [24_DECISIONS-PROJET.md](./24_DECISIONS-PROJET.md), [23_LISTE-TICKETS.md](./23_LISTE-TICKETS.md)
---
## 1. Objet de ce document
Ce document **trace les réflexions** menées en 2026 sur :
- les **limites du modèle « famille / numéro de dossier »** en v1.0.0 ;
- les **contournements** acceptés pour la release **1.0.0** ;
- les **évolutions** envisagées post-1.0.0 (unités de dossier, affiliation parentenfant, terminologie).
Il ne remplace pas le CDC : il documente l**écart assumé** entre le modèle idéal long terme et ce qui est livré en **1.0.0**, ainsi que la **feuille de route** pour aller plus loin.
---
## 2. Modèle actuel (v1.0.0) — rappel
| Concept | Implémentation |
|--------|----------------|
| **Responsable inscrit** | Rôle applicatif `parent` + entité `parents` |
| **Second adulte** | Co-parent optionnel (`id_co_parent`) — **un seul** |
| **Enfant** | Entité `enfants` |
| **Affiliation** | Table `enfants_parents` (liens many-to-many) |
| **Dossier famille** | `dossier_famille` + `dossier_famille_enfants` (motivation, etc.) |
| **Numéro de dossier** | Format `AAAA-NNNNNN`, sur `utilisateurs` et `parents` |
| **« Famille » calculée** | Graphe : co-parent **ou** enfants partagés (`getFamilyUserIds`) |
| **Workflows** | Validation, refus, reprise : souvent **par `numero_dossier`** ou par ce graphe |
Le numéro de dossier est aujourdhui une **aide forte** pour les cas simples (un couple, N enfants, une motivation), mais il tend à devenir **lidentifiant métier** de la famille — ce qui pose problème dans les cas complexes.
---
## 3. Limitation connue v1.0.0 — familles recomposées et multi-contextes
### 3.1 Exemple type (illustration)
```
Année 1 : Responsable M + co-responsable A → enfant α
Année 2 : Responsable M + co-responsable B → enfant β
```
Même personne **M** au centre, **deux contextes de vie** distincts. **A** nest pas parent de β ; **B** nest pas parent de α.
### 3.2 Autres cas couverts par la même limitation
Les exemples « maman / papa » sont **illustratifs**. La limitation sapplique **à toute configuration** :
| Configuration | Même règle |
|---------------|------------|
| Couple **HH** ou **FF** | Oui |
| **Père** avec deux partenaires et deux enfants (même ville, écarts d’âge courts) | Oui |
| **Grand-parent** en tutelle ou **tuteur légal** | Oui *(voir § 5)* |
| Recomposition, demi-fratrie, garde alternée complexe | Oui |
### 3.3 Pourquoi le modèle casse
1. **Un `numero_dossier` par user** — M ne peut pas appartenir proprement à deux unités.
2. **Un seul co-parent** par fiche `parents`.
3. **Graphe famille trop large** — M liée à A (via α) et à B (via β) → A, B et M peuvent être fusionnés en **une seule « famille »** pour validation/refus/reprise.
4. **`dossier_famille`** — une motivation / une ancre par numéro, pas deux contextes pour la même personne.
---
## 4. Décision v1.0.0 — contournement opérationnel
### 4.1 Principe
> **Le numéro de dossier reste la norme pour les cas simples, pas une obligation absolue.**
> Pour les cas trop complexes, le **gestionnaire** compose manuellement (création admin, rattachements) ou applique le contournement ci-dessous.
### 4.2 Contournement accepté pour la 1.0.0
**Créer un second compte** avec une **adresse e-mail distincte** et un **second dossier** (second `numero_dossier`).
| Dossier | Compte | Co-responsable | Enfant |
|---------|--------|----------------|--------|
| 1 | `m.personne@…` | A | α |
| 2 | `m.personne.famille2@…` *(ou alias)* | B | β |
**Conséquences assumées :**
- Une **même personne physique** peut avoir **deux identités** dans lapp.
- Pas de vue unifiée « une personne, deux contextes » en v1.0.0.
- Procédure interne gestionnaire recommandée (note « même personne physique »).
- Emails distincts **volontaires** (alias, +tag, boîte dédiée selon infra mail).
### 4.3 Nuance — inscription publique
Si le **dossier 1** existe déjà avec lemail de P (titulaire ou co-parent), une **2ᵉ inscription publique** où lon saisit **le même email** comme co-parent est **bloquée** (*email déjà utilisé*).
Le **2ᵉ dossier** passe donc surtout par :
- **création / composition par le gestionnaire** (tickets admin #129+), ou
- **2ᵉ email** dès le départ pour la même personne physique.
### 4.4 Piste cible — parcours gestionnaire « famille complexe » *(réflexion juin 2026)*
Le contournement § 4.2 reste valable en **v1.0.0**. La **solution produit visée** pour les cas complexes est différente :
> **Seul le gestionnaire** dispose dun **parcours de création dédié** permettant de constituer une configuration avec **plus de deux responsables** (parents, co-parents, tuteurs…) **sans** se limiter au seul champ `co_parent`, en sappuyant sur **`enfants_parents`** comme vérité de visibilité.
**Exemple M / A / B / α / β :**
| Compte | Enfants visibles / rattachés |
|--------|------------------------------|
| **M** (un seul compte, un email) | α **et** β |
| **A** | α uniquement |
| **B** | β uniquement |
```
α ─── M ─── β
│ │
A B
```
- **M** voit et gère **ses deux enfants** sur **le même compte** (plus besoin dun 2ᵉ email pour M).
- **A** et **B** ne voient **que** lenfant qui leur est rattaché via `enfants_parents` — pas de fusion « famille » qui mélange A et B.
- Le parcours nest **pas** proposé à linscription publique (trop error-prone) : **réservé au gestionnaire** (#129+ ou ticket dédié « famille complexe »).
**Conséquences techniques (post-1.0.0) :**
1. **Visibilité** : filtrer listes, fiches et actions parent par **liens `enfants_parents`**, pas par `getFamilyUserIds` / co-parent.
2. **Workflows** (validation, refus, reprise) : périmètre par **enfant** ou **soumission**, pas par graphe familial élargi.
3. **`co_parent`** : reste utile pour le cas simple (couple + N enfants communs) ; **insuffisant seul** pour les cas complexes — le gestionnaire compose les liens enfant par enfant.
4. **Numéro de dossier** : optionnel ou secondaire ; peut rester sur M ou sur une « unité » admin, sans imposer un numéro par co-responsable.
*Détail : § 7.5.*
---
## 5. Terminologie — « parent » aujourdhui, qualification demain
### 5.1 v1.0.0
- Rôle technique : **`parent`** pour tout responsable inscrit (y compris tuteur, grand-parent tutrice, etc.).
- UI : « Parent 1 », « co-parent », parfois exemples maman/papa — **pas de statut juridique distinct**.
### 5.2 Évolution post-1.0.0 (piste)
Séparer deux niveaux :
| Niveau | Évolution |
|--------|-----------|
| **Rôle applicatif** | Conserver `parent` = « responsable du dossier » (auth, API) |
| **Qualification métier** | Nouveau champ, ex. `qualite_responsable` / `lien_avec_enfant` |
**Valeurs possibles (exemples)** : parent biologique ou adoptif, co-parent, tuteur légal, grand-parent exerçant la garde, autre responsable légal.
**Emplacement recommandé** : sur le **lien** `enfants_parents` (par enfant), pas seulement sur le user global.
**UI** :
- Libellés neutres : « Responsable 1 / 2 », « 2ᵉ responsable » ;
- **Combobox** pour qualifier le lien (admin + éventuellement inscription).
---
## 6. Évolutions UI / fonctionnelles liées (backlog)
Réflexions dashboard admin / gestionnaire (complément CDC §4.5.24.5.3).
> **Statut implémentation (juin 2026)** : §6.1 et §6.2 **en cours de livraison** (tickets #130#131, #115#116, #137#138). §6.3 reporté post-1.0.0 (#129).
### 6.1 Fiche parent (#131)
- Modale **éditable** dès louverture (pas lecture seule + « Modifier » factice).
- **Retirer lID** UUID ; option : **n° de dossier** en lecture seule.
- **Statut** en combobox (règles métier à cadrer vs validation/refus #110).
- Bas de modale :
- `Nombre d'enfants : N` (lecture seule) ;
- **Liste des prénoms/noms** (cadre) — consultation, clic → fiche enfant (#138).
### 6.2 Affiliation parent ↔ enfant (#115, #116, #138)
- **Vérité métier** : `enfants_parents`.
- **Modifier laffiliation** ≠ modifier le téléphone : gestion des **liens** (détacher / rattacher), avec garde-fous :
- ne pas supprimer lenfant pour retirer un lien ;
- au moins un responsable par enfant ;
- prudence sur fusion « famille » et co-parents.
- **Création enfant** : prioritaire depuis **fiche parent** (contexte famille) ; onglet **Enfants** (#137) pour vue globale + rattachement.
### 6.3 Création admin sans numéro (tickets #129+)
Le gestionnaire doit pouvoir **tout créer** depuis linterface ; le numéro reste **généré si utile**, **optionnel** si le cas est trop complexe — **objectif post-1.0.0** (unité de dossier).
---
## 7. Évolution structurelle post-1.0.0 — « unité de dossier »
### 7.1 Principe cible
| Aujourdhui | Cible |
|-------------|--------|
| `numero_dossier` = clé de la famille | **Liens parent↔enfant** = vérité |
| Famille déduite du graphe | **Unité de dossier** = regroupement **optionnel** |
| Un numéro par inscription | Numéro **optionnel** ; plusieurs unités par personne possibles |
### 7.2 Exemple cible (cas M / A / B) — deux approches
**Approche A — unités de dossier séparées** *(piste initiale § 7)* :
```
Unité 1 : numero 2026-000021 — M, A, α
Unité 2 : sans numéro (ou 2026-000089) — M, B, β
```
M appartient à **deux unités** ; A et B ne partagent pas la même unité. Peut impliquer **deux contextes de connexion** ou une agrégation côté M.
**Approche B — parcours gestionnaire « famille complexe »** *(préférée, § 4.4)* :
```
Compte M → enfants α, β
Compte A → enfant α
Compte B → enfant β
(liens enfants_parents ; pas de fusion A↔B)
```
- **Un seul compte pour M** avec **les deux enfants**.
- **A** et **B** isolés sur **leur** enfant respectif.
- Création **uniquement** par le gestionnaire ; inscription publique inchangée (couple + co-parent classique).
Les deux approches supposent de **cesser de déduire une « famille » unique** pour les workflows lorsque les liens enfant par enfant divergent. Lapproche B maximise lUX du responsable central (M) sans dupliquer son identité.
### 7.5 Parcours gestionnaire — création « famille complexe »
#### 7.5.1 Objectif
Permettre au **gestionnaire** de monter un dossier où :
- **N responsables** (≥ 2, parents ou tuteurs) sont créés ou rattachés ;
- chaque enfant est lié **explicitement** à un ou plusieurs responsables via `enfants_parents` ;
- un responsable (ex. **M**) peut être lié à **plusieurs enfants** dont les **autres** responsables (A, B) ne partagent **pas** la garde.
#### 7.5.2 Règles produit
| Règle | Détail |
|-------|--------|
| **Accès** | Parcours **gestionnaire uniquement** (dashboard), pas inscription publique |
| **Responsables** | Création ou rattachement de comptes `parent` ; qualification future sur le lien (§ 5) |
| **Visibilité** | Chaque responsable ne voit que **ses** enfants (liens `enfants_parents`) |
| **Co-parent UI** | Ne pas forcer « Parent 1 + co-parent unique » ; composition libre côté staff |
| **Garde-fous** | Au moins un responsable par enfant ; pas de suppression enfant pour retirer un lien |
#### 7.5.3 Esquisse du parcours UI (gestionnaire)
1. **Créer ou identifier** le responsable principal (ex. M).
2. **Ajouter dautres responsables** (A, B, tuteur…) — comptes distincts.
3. **Créer les enfants** (α, β…) et, pour chaque enfant, **cocher les responsables** rattachés.
4. **Motivation / dossier** : texte global ou par enfant (à cadrer).
5. **Validation** : par soumission ou par enfant, sans valider « toute la famille » dun coup si A et B ne doivent pas être fusionnés.
#### 7.5.4 Impacts techniques majeurs
| Domaine | Changement |
|---------|------------|
| **Auth / API parent** | `GET` enfants, dashboard parent : filtre `enfants_parents` pour lutilisateur courant |
| **`getFamilyUserIds`** | Ne plus utiliser pour visibilité parent ; réservé au cas simple ou deprecated progressivement |
| **Validation / refus** | Périmètre enfant ou responsable, pas fusion A+B via graphe |
| **Reprise (#112)** | Token / périmètre = enfants liés au compte refusé, pas toute la composante connexe |
| **Admin (#115#138)** | Prérequis : rattachement/détachement déjà en place ; ce parcours **compose** ces briques |
#### 7.5.5 Lien avec v1.0.0
| Phase | Comportement |
|-------|--------------|
| **v1.0.0** | Contournement § 4.2 (2ᵉ email M) + composition manuelle gestionnaire (#115#138) |
| **Post-1.0.0** | Parcours § 7.5 + refonte visibilité / workflows |
### 7.3 Impacts workflows
| Flux | Adaptation future |
|------|-------------------|
| Validation / refus (#110) | Par **enfant / soumission**, pas par graphe global |
| Reprise (#112) | Périmètre = enfants liés au compte, pas composante connexe |
| Liste « à valider » | Par soumission ou par enfant |
| Recherche gestionnaire | Numéro **ou** nom **ou** enfant |
| Visibilité parent | **Uniquement** enfants via `enfants_parents` (approche B § 7.2) |
### 7.4 Migration
- **Court terme** : contournement § 4 + tickets admin.
- **Moyen terme** : table **unité de dossier**, `numero_dossier` nullable.
- **Long terme** : workflows branchés sur lunité.
- Dossiers **existants** (couple + enfants) : une unité = un numéro → **comportement actuel préservé**.
---
## 8. Tickets Gitea associés
| Ticket | Sujet |
|--------|--------|
| #110 | Refus dossier (token reprise) — livré |
| #112 | Reprise après refus — livré |
| #115 / #116 | Rattachement parent — backend / front |
| #129+ | Création dossier admin (parent / AM) |
| #131 | Fiche parent éditable (dashboard) |
| #137 | Onglet Enfants — liste globale |
| #138 | Fiche enfant + liste dans fiche parent |
| *(à créer)* | Epic « Unité de dossier / numéro optionnel » |
| #139 | **Parcours gestionnaire « famille complexe »** (§ 7.5) — N responsables, visibilité par enfant |
| *(à créer)* | Qualification responsable légal (combobox sur lien enfant) |
---
## 9. Formulation type — release notes / doc gestionnaire (v1.0.0)
> **Familles recomposées ou responsabilités multiples**
> Une même personne ne peut pas gérer proprement deux unités familiales distinctes (recompositions, plusieurs co-responsables successifs, tuteur/GP pour plusieurs contextes) avec **un seul compte**.
> **Contournement v1.0.0** : second compte avec **email distinct** et second numéro de dossier.
> Sapplique à **tous les responsables inscrits** (couples HH/FF, tuteurs, grands-parents, etc.).
> **Évolution post-1.0.0** : parcours **gestionnaire** « famille complexe » (un compte M, enfants α+β ; A et B limités à leur enfant) ; visibilité par `enfants_parents` ; workflows sans fusion graphe familial.
---
## 10. Historique des mises à jour
| Date | Auteur | Modification |
|------|--------|--------------|
| 2026-06-16 | Équipe / session produit | Création — synthèse réflexions famille, tutelle, v1.0.0 vs post-1.0.0 |
| 2026-06-16 | Implémentation ch.6 | Back : `PATCH /parents/:id/fiche`, attach/detach enfant. Front : modale parent éditable, onglet Enfants, fiche enfant |
| 2026-06-16 | Réflexion produit | § 4.4 / § 7.5 — parcours gestionnaire famille complexe : M un compte (α+β), A/B visibilité restreinte par enfant |
---
*Ce document sera enrichi au fil des décisions. Pour les décisions formelles archivées, voir aussi [24_DECISIONS-PROJET.md](./24_DECISIONS-PROJET.md).*
+28 -1
View File
@@ -2,6 +2,8 @@
Ce document liste les modifications à apporter au cahier des charges original pour le rendre conforme à l'application développée.
> **Document complémentaire (juin 2026)** — réflexions sur le **modèle famille / numéro de dossier**, familles recomposées, tuteurs et responsables légaux : voir **[28 - Évolution famille et responsables](./28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md)**.
## 1. Gestion des Enfants
### Modifications à apporter dans la section "Création de compte parent"
@@ -275,4 +277,29 @@ Pour chaque évolution identifiée, ce document suivra la structure suivante :
- Évolution du modèle de données vers un RBAC intra-RPE.
- Adaptation des écrans d'administration pour gérer les rôles locaux.
- Renforcement des contrôles d'accès backend et des règles métier.
- Clarification des workflows décisionnels dans l'application.
- Clarification des workflows décisionnels dans l'application.
## 9. Modèle famille, numéro de dossier et responsables légaux
### 9.1 Situation actuelle (v1.0.0)
- Un **numéro de dossier** par inscription (`AAAA-NNNNNN`), fortement utilisé dans les workflows (validation, refus, reprise).
- **Un co-parent** par fiche `parents` ; affiliation réelle via `enfants_parents`.
- La « famille » est **déduite** du graphe (co-parent + enfants partagés) — fusion parfois trop large en cas de recompositions.
### 9.2 Limitation v1.0.0 — familles recomposées
Cas type : même responsable M avec co-responsable A (enfant α) puis co-responsable B (enfant β). Le modèle actuel ne permet pas de séparer proprement **deux unités familiales** pour une même personne.
**Contournement accepté pour la release 1.0.0** : second compte avec **email distinct** et second numéro de dossier (procédure gestionnaire). S'applique aussi aux couples HH/FF, tuteurs, grands-parents, etc.
### 9.3 Évolutions post-1.0.0 (pistes)
| Sujet | Piste |
|-------|--------|
| **Unité de dossier** | Numéro **optionnel** ; plusieurs unités par personne |
| **Affiliation** | Gestion admin des liens parent↔enfant (#115, #116, #138) |
| **Qualification** | Combobox « lien responsableenfant » (tuteur, GP, parent…) sur `enfants_parents` |
| **UI admin** | Fiche parent éditable (#131), liste enfants en bas de fiche |
**Détail complet, scénarios, tickets et formulation release notes** : [28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md](./28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md).
@@ -0,0 +1,127 @@
# #131 — En-tête fiche parent : co-parent (note front → back)
**Ticket :** #131 (fiche parent dashboard, doc `28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md` §6.1)
**Date :** 2026-06-01
**Statut front :** livré (en-tête dynamique)
**Modif backend demandée :** **aucune fonctionnelle** — ce document fixe le contrat attendu ; le back valide `co_parent` et masque les champs sensibles.
---
## 1. Comportement UI (front)
Dans la modale **fiche parent** (`AdminParentEditModal`) :
| Zone | Contenu |
|------|---------|
| **Titre** | `prenom` + `nom` du parent affiché (plus le libellé fixe « Fiche parent ») |
| **Sous-titre** | `Co-parent : {prenom} {nom}` — affiché **uniquement** si un co-parent est connu |
Le titre se met à jour en direct pendant l’édition des champs nom/prénom.
Le sous-titre provient du co-parent **chargé depuis lAPI** (pas saisi à la main dans la modale).
---
## 2. Endpoints consommés
| Méthode | Route | Usage front |
|---------|-------|-------------|
| `GET` | `/api/v1/parents` | Liste parents (onglet Parents) |
| `GET` | `/api/v1/parents/:userId` | Rechargement fiche après rattachement/détachement enfant |
| `PATCH` | `/api/v1/parents/:userId/fiche` | Sauvegarde identité + statut (inchangé) |
Rôles : `super_admin`, `gestionnaire`, `administrateur` (selon route).
---
## 3. Contrat JSON attendu pour `co_parent`
Le front parse `ParentModel.fromJson` avec la clé **`co_parent`** (snake_case), objet utilisateur imbriqué.
### Champs minimum utilisés pour le sous-titre
| Clé JSON | Usage |
|----------|--------|
| `co_parent` | Objet ou absent/`null` |
| `co_parent.id` | Identifiant (futur lien cliquable éventuel) |
| `co_parent.prenom` | Affichage |
| `co_parent.nom` | Affichage |
Affichage front : `'{prenom} {nom}'.trim()` → libellé `Co-parent : …`.
### Exemple de fragment de réponse (`GET /parents/:id`)
```json
{
"user_id": "33333333-3333-3333-3333-333333333333",
"numero_dossier": "2026-000042",
"user": {
"id": "33333333-3333-3333-3333-333333333333",
"email": "parent1@example.com",
"prenom": "Paul",
"nom": "PARENT",
"statut": "actif",
"telephone": "0601020304"
},
"co_parent": {
"id": "44444444-4444-4444-4444-444444444444",
"email": "coparent1@example.com",
"prenom": "Clara",
"nom": "COPARENT",
"role": "parent",
"statut": "actif"
},
"parentChildren": []
}
```
> **Note :** le front lit `user` (pas `utilisateur`). La doc `11_API.md` § Parents mentionne encore `utilisateur` / `id_co_parent` seul — le contrat **effectif** côté Nest/TypeORM est lentité `Parents` sérialisée (`user`, `co_parent`, `parentChildren`, …).
---
## 4. État backend
### Relations (déjà en place)
- `findAll()` et `findOne(user_id)` chargent **`co_parent`** ;
- FK : `parents.id_co_parent``utilisateurs.id` ;
- inscription couple : les deux sens renseignés en principe (`auth.service.ts`).
### Livraison back (#131)
- `mapParentForApi` / `sanitizeUserForApi` : réponses `GET/PATCH/POST/DELETE` parents **sans** `password`, `token_creation_mdp`, `password_reset_*` sur `user` et `co_parent`.
**Checklist validation :**
- [x] `GET /parents/:id` renvoie `co_parent` peuplé quand `id_co_parent` est non null
- [x] `GET /parents` (liste) inclut `co_parent`
- [x] `prenom` / `nom` du co-parent présents
- [x] Pas de fuite `password` / tokens sur `user` ni `co_parent`
---
## 5. Points dattention (hors périmètre immédiat)
| Sujet | Détail |
|-------|--------|
| **Lien inverse** | Si B est co-parent de A (`A.id_co_parent = B`) mais `B.id_co_parent` est `null`, le sous-titre **ne saffichera pas** sur la fiche de B. Pas de résolution inverse côté front. |
| **Familles > 2 adultes** | Sous-titre = co-parent direct (`id_co_parent`) uniquement. |
| **Trou AM ↔ enfants en garde** | Pas de lien AMenfant aujourdhui (à documenter / traiter plus tard). |
---
## 6. Fichiers back concernés
| Fichier | Rôle |
|---------|------|
| `backend/src/routes/parents/parents.service.ts` | `findOne`, `findAll` + relations |
| `backend/src/routes/parents/parents.controller.ts` | `mapParentForApi` sur les réponses |
| `backend/src/routes/parents/parents.mapper.ts` | Sérialisation API |
| `backend/src/common/utils/sanitize-user-for-api.ts` | Masquage secrets |
| `backend/src/entities/parents.entity.ts` | relation `co_parent` |
---
## 7. Références
- `docs/28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md` §6.1
- Ticket Gitea **#131**
@@ -0,0 +1,244 @@
# #112 — Alignement front après évolution back (reprise dossier complet)
**Branche déployée :** `feature/112-reprise-apres-refus-front`
**Commit back :** `d70577b1``feat(#112): reprise après refus — dossier complet GET/PATCH`
**Date :** 2026-06-16
Ce document décrit le **contrat API réel** après extension du back, et ce que le front doit encore brancher pour exploiter le dossier complet (au-delà de lidentité seule).
---
## 1. Endpoints (inchangés côté URL)
| Méthode | Route | Auth |
|---------|-------|------|
| `GET` | `/api/v1/auth/reprise-dossier?token={uuid}` | Public |
| `PATCH` | `/api/v1/auth/reprise-resoumettre` | Public |
| `POST` | `/api/v1/auth/reprise-identify` | Public (inchangé) |
> **Note :** le ticket #111 parlait de `PUT` ; limplémentation reste en **`PATCH`** (comme avant).
---
## 2. `GET /auth/reprise-dossier` — réponse enrichie
### Champs communs (toujours présents)
Identiques à avant : `id`, `email`, `prenom`, `nom`, `telephone`, `adresse`, `ville`, `code_postal`, `numero_dossier`, `role`, `photo_url`, `genre`, `situation_familiale`.
### Rôle `parent` (+ champs #119)
Alignés sur `DossierFamilleCompletDto` :
```json
{
"parents": [
{
"user_id": "uuid",
"email": "…",
"prenom": "…",
"nom": "…",
"telephone": "…",
"adresse": "…",
"ville": "…",
"code_postal": "…",
"statut": "refuse",
"co_parent_id": "uuid-parent-entity"
}
],
"enfants": [
{
"id": "uuid-enfant",
"first_name": "Emma",
"last_name": "MARTIN",
"genre": "F",
"status": "actif",
"birth_date": "2023-02-15T00:00:00.000Z",
"due_date": null,
"photo_url": "/uploads/photos/…",
"consent_photo": true,
"est_multiple": false
}
],
"texte_motivation": "Nous recherchons…"
}
```
**Mapping front suggéré :**
| JSON back | Modèle / wizard parent |
|-----------|-------------------------|
| `parents[]` | `UserRegistrationData.parent1` + `parent2` (matcher par `email` ou ordre : titulaire = `id` du GET racine) |
| `enfants[].first_name` / `last_name` | `ChildData.firstName` / `lastName` |
| `enfants[].birth_date` | `ChildData.birthDate` (ISO → `DateTime`) |
| `enfants[].due_date` | `ChildData.dueDate` (enfant `a_naitre`) |
| `enfants[].status` | `actif` = né, `a_naitre` = à naître |
| `enfants[].photo_url` | `ApiConfig.absoluteMediaUrl()` + conserver pour reprise sans re-upload |
| `enfants[].id` | **Obligatoire** pour le PATCH (update par id) |
| `enfants[].est_multiple` | `grossesse_multiple` si utilisé |
| `texte_motivation` | étape présentation / motivation |
Si `numero_dossier` absent : pas de `parents[]` / `enfants[]` / `texte_motivation` (identité seule).
### Rôle `assistante_maternelle`
Champs racine + fiche pro (structure **aplatie**, pas de sous-objet `user`) :
```json
{
"consentement_photo": true,
"date_naissance": "1985-03-12T00:00:00.000Z",
"lieu_naissance_ville": "Paris",
"lieu_naissance_pays": "France",
"numero_agrement": "AGR-2024-12345",
"nir": "123456789012345",
"date_agrement": "2024-06-01T00:00:00.000Z",
"nb_max_enfants": 4,
"place_disponible": 2,
"biographie": "…"
}
```
**Mapping `AmRegistrationData` :**
| JSON back | Champ front |
|-----------|-------------|
| `nb_max_enfants` | `capaciteAccueil` |
| `place_disponible` | `placesDisponibles` |
| `numero_agrement` | `numeroAgrement` |
| `biographie` | `biographie` / présentation |
| `photo_url` | déjà géré via `RepriseSession.photoUrl` |
---
## 3. `PATCH /auth/reprise-resoumettre` — body étendu
### Commun
```json
{ "token": "uuid-reprise" }
```
### Parent — champs à envoyer depuis le wizard
| Champ PATCH | Source wizard | Notes |
|-------------|---------------|-------|
| `prenom`, `nom`, `telephone`, `adresse`, `ville`, `code_postal` | Parent 1 (titulaire token) | Champs racine |
| `co_parent_prenom`, `co_parent_nom`, `co_parent_telephone` | Parent 2 | |
| `co_parent_meme_adresse`, `co_parent_adresse`, `co_parent_code_postal`, `co_parent_ville` | Parent 2 adresse | |
| `texte_motivation` **ou** `presentation_dossier` | Étape motivation | Les deux alias acceptés |
| `enfants[]` | Liste enfants | Voir ci-dessous |
**Structure `enfants[]` (miroir inscription + `id` obligatoire) :**
```json
{
"id": "uuid-enfant-existant",
"prenom": "Emma",
"nom": "MARTIN",
"date_naissance": "2023-02-15",
"date_previsionnelle_naissance": null,
"genre": "F",
"photo_base64": "data:image/jpeg;base64,…",
"photo_filename": "emma.jpg",
"grossesse_multiple": false
}
```
- **v1 back :** update par `id` uniquement — pas de création/suppression denfant.
- Si `id` inconnu pour ce dossier → **400** `Enfant inconnu pour ce dossier : {id}`.
- Sans nouvelle photo : ne pas envoyer `photo_base64` (lexistant est conservé).
### AM — champs à envoyer
| Champ PATCH | Source |
|-------------|--------|
| Identité + `photo_url` ou `photo_base64` + `photo_filename` | Étapes 12 |
| `consentement_photo`, `date_naissance`, `lieu_naissance_ville`, `lieu_naissance_pays` | Identité |
| `numero_agrement`, `nir`, `date_agrement` | Pro |
| `capacite_accueil`, `places_disponibles` | Pro |
| `biographie` | Présentation |
Validation NIR identique à linscription si `nir` fourni.
### Réponse succès (nouveau format)
```json
{
"message": "Dossier resoumis avec succès. Il est de nouveau en attente de validation.",
"statut": "en_attente",
"user_id": "uuid",
"numero_dossier": "2026-000021"
}
```
Code HTTP : **200** (pas de corps `Users` brut comme lancien back).
### Effet métier
- **Parent :** tous les users `role=parent` avec le même `numero_dossier` passent en `en_attente` ; `token_reprise` invalidé sur **tous** (symétrique refus #110).
- **AM :** un seul user.
### E-mail accusé resoumission (parent)
Après `PATCH` réussi, un e-mail est envoyé à **chaque parent** du dossier (`sendResoumissionPendingEmail`) :
- confirmation de resoumission ;
- rappel du **numéro de dossier** ;
- mention « en attente de validation ».
Échec SMTP : logué, **ne bloque pas** la resoumission (même règle que l'inscription initiale).
---
## 4. Fichiers front à modifier (checklist)
### Modèles
- [ ] `lib/models/reprise_dossier.dart` — parser `parents[]`, `enfants[]`, `texte_motivation`, champs AM
- [ ] Réutiliser ou mapper vers `DossierFamilleEnfant` / structures existantes (#119 admin) si possible
### Session / préremplissage
- [ ] `lib/services/reprise_session.dart`
- `applyToParent` : remplir parent1/parent2 depuis `parents[]`, enfants, motivation
- `applyToAm` : remplir tous les champs AM
### API
- [ ] `lib/services/auth_service.dart``resoumettreReprise()` : accepter body complet (parent + AM), pas seulement identité
- [ ] Étendre `UserRegistrationData` / `AmRegistrationData` helpers `toReprisePatchBody()` si utile
### Écrans fin de parcours
- [ ] `parent_register_step5_screen.dart` — PATCH avec co-parent, enfants, motivation
- [ ] `am_register_step4_screen.dart` — PATCH avec fiche AM complète
### Hors scope back (inchangé)
RIB / IBAN / attestation CAF (étape 5 wizard parent) : **non persistés** — rien à envoyer en reprise.
### Non implémenté front (ticket #112 initial)
- [ ] Modale login « Jai un numéro de dossier » → `POST /auth/reprise-identify` (back prêt, front absent)
---
## 5. Tests manuels suggérés
1. Refuser un dossier parent complet (≥1 enfant + co-parent + motivation).
2. Ouvrir le lien mail `/reprise?token=…`.
3. Vérifier dans DevTools que le GET contient `enfants[]` et `texte_motivation`.
4. Après branchement front : wizard prérempli sur toutes les étapes.
5. Resoumettre → statut `en_attente` pour les deux parents ; dossier visible file validation admin (#119).
---
## 6. Références code back
```
backend/src/routes/auth/dto/reprise-dossier.dto.ts
backend/src/routes/auth/dto/resoumettre-reprise.dto.ts
backend/src/routes/auth/dto/enfant-reprise.dto.ts
backend/src/routes/auth/auth.service.ts → getRepriseDossier, resoumettreReprise
backend/src/routes/parents/dto/dossier-famille-complet.dto.ts
```
@@ -0,0 +1,132 @@
# #131 — Fiche AM éditable + affiliation enfants (note front → back)
**Ticket :** #131 (partie AM, doc `28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md` §6.1)
**Date :** 2026-06-01
**Statut front :** modale livrée (2 onglets) — **API affiliation AM↔enfant à implémenter**
---
## 1. Comportement UI (front)
Modale `AdminAmEditModal` — même shell que la fiche parent (~930 px) :
| Onglet | Contenu |
|--------|---------|
| **Identité & professionnel** | `IdentityBlock` éditable + grille pro (agrément, ville résidence, capacité, places, NIR/agrément date en lecture seule, biographie, switch disponible) + gélule statut |
| **Enfants accueillis** | Liste cartes enfants (réutilise `AdminChildrenAffiliationPanel` / `AdminEnfantUserCard`) + rattacher / détacher |
En-tête : prénom nom · sous-titre `Zone · Agrément · Dossier`.
---
## 2. Endpoints consommés
### Déjà existants (partiels)
| Méthode | Route | Usage |
|---------|-------|-------|
| `GET` | `/api/v1/assistantes-maternelles` | Liste AM |
| `GET` | `/api/v1/assistantes-maternelles/:userId` | Détail (403 possible pour `administrateur` → fallback liste) |
| `PATCH` | `/api/v1/users/:userId` | Identité + statut (admin / super_admin uniquement) |
| `PATCH` | `/api/v1/assistantes-maternelles/:userId` | Champs pro (gestionnaire / super_admin) |
### À créer (recommandé — miroir parent #131 / #115)
| Méthode | Route | Rôle |
|---------|-------|------|
| `PATCH` | `/api/v1/assistantes-maternelles/:userId/fiche` | Mise à jour unifiée identité + pro + statut (`super_admin`, `gestionnaire`, `administrateur`) |
| `POST` | `/api/v1/assistantes-maternelles/:userId/enfants/:enfantId` | Rattacher un enfant |
| `DELETE` | `/api/v1/assistantes-maternelles/:userId/enfants/:enfantId` | Détacher un enfant |
| `GET` | `/api/v1/assistantes-maternelles/:userId` | Inclure `amChildren[]` (relation enfant) |
Le front appelle déjà ces routes ; en labsence de `PATCH …/fiche`, il tente un fallback `PATCH users` + `PATCH assistantes-maternelles` (échoue selon le rôle connecté).
---
## 3. Modèle de données affiliation AM ↔ enfant
**À définir côté BDD** (pas de table dédiée aujourdhui, contrairement à `enfants_parents`) :
Proposition alignée parent :
```sql
-- Piste : enfants_assistantes_maternelles
CREATE TABLE enfants_assistantes_maternelles (
id_am UUID NOT NULL REFERENCES utilisateurs(id) ON DELETE CASCADE,
id_enfant UUID NOT NULL REFERENCES enfants(id) ON DELETE CASCADE,
PRIMARY KEY (id_am, id_enfant)
);
```
Réponse API attendue sur `GET /assistantes-maternelles/:id` :
```json
{
"user_id": "uuid-am",
"user": { "id": "…", "prenom": "Claire", "nom": "MARTIN", "statut": "actif" },
"approval_number": "AGR-2024-12345",
"residence_city": "Bezons",
"max_children": 4,
"places_available": 2,
"available": true,
"amChildren": [
{
"child": {
"id": "uuid-enfant",
"first_name": "Emma",
"last_name": "MARTIN",
"status": "actif",
"birth_date": "2023-02-15"
}
}
]
}
```
Le front parse `amChildren` / `am_children` / `assistanteChildren` (même logique que `parentChildren`).
---
## 4. Body `PATCH …/fiche` suggéré
```json
{
"nom": "MARTIN",
"prenom": "Claire",
"email": "claire@example.com",
"telephone": "0612345678",
"adresse": "5 place Bellecour",
"ville": "Lyon",
"code_postal": "69002",
"statut": "actif",
"approval_number": "AGR-2024-12345",
"residence_city": "Lyon",
"max_children": 4,
"places_available": 2,
"biography": "…",
"available": true
}
```
NIR et date dagrément : lecture seule dans la modale (modification hors périmètre admin v1).
---
## 5. Fichiers front concernés
| Fichier | Rôle |
|---------|------|
| `frontend/lib/widgets/admin/common/admin_am_edit_modal.dart` | Modale 2 onglets |
| `frontend/lib/widgets/admin/common/admin_children_affiliation_panel.dart` | Liste enfants partagée parent/AM |
| `frontend/lib/widgets/admin/common/admin_status_capsule.dart` | Gélule statut partagée |
| `frontend/lib/models/assistante_maternelle_model.dart` | Parse champs pro + `amChildren` |
| `frontend/lib/services/user_service.dart` | `getAssistanteMaternelle`, `updateAmFiche`, `attachEnfantToAm`, `detachEnfantFromAm` |
| `frontend/lib/widgets/admin/assistante_maternelle_management_widget.dart` | Ouverture modale au clic Modifier |
---
## 6. Références
- Fiche parent : `PATCH /parents/:id/fiche`, `POST|DELETE /parents/:id/enfants/:enfantId`
- Ticket Gitea **#131**, **#115**
- `docs/archive/temporaires/TEMP_131-back-fiche-parent-co-parent.md`
@@ -0,0 +1,124 @@
# #131 — En-tête fiche parent : co-parent (note front → back)
**Ticket :** #131 (fiche parent dashboard, doc `28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md` §6.1)
**Date :** 2026-06-01
**Statut front :** livré (en-tête dynamique)
**Modif backend demandée :** **aucune** — ce document fixe le contrat attendu et invite à valider que lexistant le couvre.
---
## 1. Comportement UI (front)
Dans la modale **fiche parent** (`AdminParentEditModal`) :
| Zone | Contenu |
|------|---------|
| **Titre** | `prenom` + `nom` du parent affiché (plus le libellé fixe « Fiche parent ») |
| **Sous-titre** | `Co-parent : {prenom} {nom}` — affiché **uniquement** si un co-parent est connu |
Le titre se met à jour en direct pendant l’édition des champs nom/prénom.
Le sous-titre provient du co-parent **chargé depuis lAPI** (pas saisi à la main dans la modale).
---
## 2. Endpoints consommés
| Méthode | Route | Usage front |
|---------|-------|-------------|
| `GET` | `/api/v1/parents` | Liste parents (onglet Parents) |
| `GET` | `/api/v1/parents/:userId` | Rechargement fiche après rattachement/détachement enfant |
| `PATCH` | `/api/v1/parents/:userId/fiche` | Sauvegarde identité + statut (inchangé) |
Rôles : `super_admin`, `gestionnaire`, `administrateur` (selon route).
---
## 3. Contrat JSON attendu pour `co_parent`
Le front parse `ParentModel.fromJson` avec la clé **`co_parent`** (snake_case), objet utilisateur imbriqué.
### Champs minimum utilisés pour le sous-titre
| Clé JSON | Usage |
|----------|--------|
| `co_parent` | Objet ou absent/`null` |
| `co_parent.id` | Identifiant (futur lien cliquable éventuel) |
| `co_parent.prenom` | Affichage |
| `co_parent.nom` | Affichage |
Affichage front : `'{prenom} {nom}'.trim()` → libellé `Co-parent : …`.
### Exemple de fragment de réponse (`GET /parents/:id`)
```json
{
"user_id": "33333333-3333-3333-3333-333333333333",
"numero_dossier": "2026-000042",
"user": {
"id": "33333333-3333-3333-3333-333333333333",
"email": "parent1@example.com",
"prenom": "Paul",
"nom": "PARENT",
"statut": "actif",
"telephone": "0601020304"
},
"co_parent": {
"id": "44444444-4444-4444-4444-444444444444",
"email": "coparent1@example.com",
"prenom": "Clara",
"nom": "COPARENT",
"role": "parent",
"statut": "actif"
},
"parentChildren": []
}
```
> **Note :** le front lit `user` (pas `utilisateur`). La doc `11_API.md` § Parents mentionne encore `utilisateur` / `id_co_parent` seul — le contrat **effectif** côté Nest/TypeORM est lentité `Parents` sérialisée (`user`, `co_parent`, `parentChildren`, …).
---
## 4. État backend (à valider, pas à refaire)
Daprès le code actuel (`parents.service.ts`) :
- `findAll()` et `findOne(user_id)` chargent déjà la relation **`co_parent`** ;
- la FK métier est `parents.id_co_parent``utilisateurs.id` ;
- à linscription couple, les deux sens sont en principe renseignés (`auth.service.ts`).
**Checklist validation back :**
- [ ] `GET /parents/:id` renvoie bien `co_parent` peuplé quand `id_co_parent` est non null
- [ ] `GET /parents` (liste) inclut aussi `co_parent` (sous-titre disponible dès louverture sans re-fetch)
- [ ] Les champs `prenom` / `nom` du co-parent sont présents dans la réponse JSON
Si ces trois points passent en recette, **aucun changement backend nest nécessaire** pour cette fonctionnalité.
---
## 5. Points dattention (hors périmètre immédiat)
| Sujet | Détail |
|-------|--------|
| **Lien inverse** | Si le parent B est le co-parent de A (`A.id_co_parent = B`) mais que `B.id_co_parent` est `null`, le sous-titre **ne saffichera pas** sur la fiche de B. Le front ne fait pas de résolution inverse. À traiter côté back **seulement si** des données legacy ont un lien à sens unique. |
| **Familles > 2 adultes** | Le sous-titre naffiche que le co-parent direct (`id_co_parent`). Les autres responsables liés uniquement via `enfants_parents` ne sont pas listés ici (cf. doc 28 §6). |
| **Données sensibles** | Vérifier que la sérialisation de `co_parent` nexpose pas `password` / tokens (même remarque que pour `user`). |
---
## 6. Fichiers front concernés
| Fichier | Rôle |
|---------|------|
| `frontend/lib/models/parent_model.dart` | Parse `co_parent``AppUser? coParent` |
| `frontend/lib/widgets/admin/common/admin_parent_edit_modal.dart` | Titre + sous-titre |
| `frontend/lib/services/user_service.dart` | `getParents()` / `getParent()` |
---
## 7. Références
- `docs/28_EVOLUTION-FAMILLE-ET-RESPONSABLES.md` §6.1
- `backend/src/routes/parents/parents.service.ts``findOne`, `findAll`
- `backend/src/entities/parents.entity.ts` — relation `co_parent`
- Ticket Gitea **#131**
+7
View File
@@ -0,0 +1,7 @@
{
"folders": [
{
"path": "."
}
]
}