# 📋 Documentation Technique - Workflow de Création de Compte

**Version** : 1.0  
**Date** : 24 Novembre 2025  
**Auteur** : Équipe PtitsPas  
**Référence CDC** : Cahier des Charges P'titsPas V1.3

---

## 📖 Table des matières

1. [Vue d'ensemble](#vue-densemble)
2. [Acteurs](#acteurs)
3. [Workflow détaillé](#workflow-détaillé)
4. [Diagrammes de séquence](#diagrammes-de-séquence)
5. [Spécifications techniques](#spécifications-techniques)
6. [APIs utilisées](#apis-utilisées)
7. [Modèles de données](#modèles-de-données)
8. [Templates d'emails](#templates-demails)
9. [Tests et validation](#tests-et-validation)

---

## 🎯 Vue d'ensemble

### Objectif

Implémenter le workflow complet de création et validation des comptes utilisateurs pour l'application P'titsPas, permettant :
- La création de gestionnaires par le super administrateur
- L'inscription autonome des parents et assistantes maternelles
- La validation des comptes par les gestionnaires
- La notification par email des décisions

### Périmètre fonctionnel

Ce workflow couvre la **Phase 1** du projet, correspondant au premier use case critique :
> "Permettre au super admin de créer des gestionnaires, qui pourront ensuite valider les inscriptions des parents et assistantes maternelles."

### Référence CDC

**Section 3.1** : Gestion des utilisateurs  
**Section 3.2** : Processus de validation  
**Section 4.5** : Notifications email

---

## 👥 Acteurs

### 1. Super Administrateur (`super_admin`)

**Rôle** : Administrateur système avec tous les droits  
**Identifiants initiaux** :
- Email : `admin@ptits-pas.fr`
- Mot de passe : `4dm1n1strateur`

**Responsabilités** :
- Créer les comptes gestionnaires
- Accéder au panneau d'administration
- Gérer la configuration système

**Référence** : Table `utilisateurs` avec `role = 'super_admin'` et `statut = 'actif'`

---

### 2. Gestionnaire (`gestionnaire`)

**Rôle** : Validateur des inscriptions  
**Création** : Par le super administrateur uniquement

**Responsabilités** :
- Consulter les demandes d'inscription en attente
- Valider ou refuser les comptes parents
- Valider ou refuser les comptes assistantes maternelles
- Consulter les informations des demandeurs

**Référence** : Table `utilisateurs` avec `role = 'gestionnaire'` et `statut = 'actif'`

---

### 3. Parent (`parent`)

**Rôle** : Utilisateur final cherchant une assistante maternelle  
**Création** : Inscription autonome via formulaire public

**Workflow** :
1. S'inscrit via le formulaire public
2. Statut initial : `en_attente`
3. Attend la validation d'un gestionnaire
4. Reçoit un email de notification (validé/refusé)
5. Si validé : peut se connecter et accéder à l'application

**Référence** : 
- Table `utilisateurs` avec `role = 'parent'`
- Table `parents` (relation 1:1 avec `utilisateurs`)

---

### 4. Assistante Maternelle (`assistante_maternelle`)

**Rôle** : Professionnelle proposant ses services de garde  
**Création** : Inscription autonome via formulaire public

**Workflow** : Identique aux parents
1. S'inscrit via le formulaire public
2. Statut initial : `en_attente`
3. Attend la validation d'un gestionnaire
4. Reçoit un email de notification (validé/refusé)
5. Si validée : peut se connecter et accéder à l'application

**Référence** :
- Table `utilisateurs` avec `role = 'assistante_maternelle'`
- Table `assistantes_maternelles` (relation 1:1 avec `utilisateurs`)

---

## ⚠️ Points d'attention - Conformité CDC

Avant de détailler le workflow, voici les points critiques pour assurer la conformité avec le Cahier des Charges :

### Inscription Parent (CDC 3.1)
- ✅ **6 étapes obligatoires** : Parent 1, Parent 2 (opt), Enfant, Présentation, CGU, Récapitulatif
- ✅ **Photo obligatoire** si enfant déjà né
- ✅ **Acceptation CGU** avec horodatage
- ✅ **Notification** : Email **OU** SMS après validation

### Inscription Assistante Maternelle (CDC 3.2)
- ✅ **NIR obligatoire** (Numéro de Sécurité sociale - 15 chiffres)
- ✅ **Photo obligatoire** (si option activée)
- ✅ **Consentement photo** avec horodatage (RGPD)
- ✅ **Date et lieu de naissance** obligatoires
- ✅ **Acceptation CGU** avec horodatage
- ✅ **Notification** : Email **OU** SMS après validation

### Création Gestionnaire (CDC 3.3)
- ✅ **Changement de mot de passe obligatoire** à la première connexion
- ✅ Créé par un administrateur uniquement

### Création Administrateur (CDC 3.4)
- ✅ **Changement de mot de passe obligatoire** à la première connexion
- ✅ Créé par un administrateur existant uniquement

### Champs Base de Données Manquants
Les champs suivants doivent être ajoutés à la base de données :
- `nir_chiffre` (assistantes_maternelles) - **OBLIGATOIRE**
- `ville_naissance` (utilisateurs)
- `pays_naissance` (utilisateurs)
- `date_acceptation_cgu` (utilisateurs)
- `presentation_dossier` (parents ou table dédiée)
- `date_consentement_photo` (utilisateurs) - **Existe déjà** ✅

---

## 🔄 Workflow détaillé

### Étape 1 : Initialisation du système

**Prérequis** : Base de données initialisée avec le super admin

```sql
-- Seed initial (01_init.sql)
INSERT INTO utilisateurs (email, password, prenom, nom, role, statut)
VALUES (
    'admin@ptits-pas.fr',
    '$2b$12$Fo5ly1YlTj3O6lXf.IUgoeUqEebBGpmoM5zLbzZx.CueorSE7z2E2', -- Hash de "4dm1n1strateur"
    'Admin',
    'Système',
    'super_admin',
    'actif'
);
```

**État** : ✅ Implémenté

---

### Étape 2 : Création d'un gestionnaire

**Acteur** : Super Administrateur  
**Interface** : Panneau d'administration - Section "Créer un gestionnaire"

#### 2.1 Interface utilisateur

**Écran** : Formulaire ultra-simple avec les champs suivants :

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Nom | Text | 2-100 caractères | ✅ |
| Prénom | Text | 2-100 caractères | ✅ |
| Email | Email | Format email valide | ✅ |
| Mot de passe | Password | Min 8 caractères, 1 majuscule, 1 chiffre | ✅ |

**Bouton** : "Soumettre"

**Wireframe** :
```
┌─────────────────────────────────────────┐
│  Créer un Gestionnaire                  │
├─────────────────────────────────────────┤
│                                         │
│  Nom :        [________________]        │
│                                         │
│  Prénom :     [________________]        │
│                                         │
│  Email :      [________________]        │
│               (personnel ou collectivité)│
│                                         │
│  Mot de passe : [________________]      │
│                                         │
│           [ Soumettre ]                 │
│                                         │
└─────────────────────────────────────────┘
```

#### 2.2 Flux technique

**Frontend → Backend**

```typescript
// Frontend (Flutter)
POST /api/v1/gestionnaires
Headers: {
  Authorization: Bearer <super_admin_token>
  Content-Type: application/json
}
Body: {
  "email": "lucas.moreau@ptits-pas.fr",
  "password": "password",
  "prenom": "Lucas",
  "nom": "MOREAU",
  "telephone": "06 87 23 45 67"
}
```

**Backend → Database**

```typescript
// Backend (NestJS)
// 1. Validation du token (AuthGuard)
// 2. Vérification du rôle (RolesGuard - super_admin uniquement)
// 3. Validation des données (DTO)
// 4. Hash du mot de passe (bcrypt, 12 rounds)
// 5. Création de l'utilisateur

INSERT INTO utilisateurs (
  email, password, prenom, nom, telephone, role, statut, 
  changement_mdp_obligatoire, cree_le
) VALUES (
  'lucas.moreau@ptits-pas.fr',
  '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5iIdYvYvOYvOy', -- Hash bcrypt de "password"
  'Lucas',
  'MOREAU',
  '06 87 23 45 67',
  'gestionnaire',
  'actif', -- Statut actif immédiatement
  TRUE, -- Changement de mot de passe obligatoire à la première connexion (CDC 3.3)
  NOW()
);
```

**Réponse**

```json
{
  "id": "uuid-lucas-moreau",
  "email": "lucas.moreau@ptits-pas.fr",
  "prenom": "Lucas",
  "nom": "MOREAU",
  "telephone": "06 87 23 45 67",
  "role": "gestionnaire",
  "statut": "actif",
  "cree_le": "2025-11-24T10:30:00Z"
}
```

**État** : 🟠 Backend implémenté, Frontend à créer

---

### Étape 3 : Inscription d'un parent

**Acteur** : Parent (non authentifié)  
**Interface** : Page publique d'inscription parent  
**Référence CDC** : Section 3.1

Le processus d'inscription parent se déroule en **6 étapes** conformément au cahier des charges.

#### 3.1 Étape 1 : Informations Parent 1

**Écran** : Formulaire d'identité du parent principal

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Nom | Text | 2-100 caractères | ✅ |
| Prénom | Text | 2-100 caractères | ✅ |
| Adresse postale | Text | Adresse complète | ✅ |
| Code postal | Text | 5 chiffres | ✅ |
| Ville | Text | 2-150 caractères | ✅ |
| Téléphone | Tel | Format français | ✅ |
| Email | Email | Format email valide | ✅ |

**Note importante** : Le Parent 1 ne définit **pas** de mot de passe lors de l'inscription. Il recevra un email avec un lien pour créer son mot de passe après validation du gestionnaire.

**Bouton** : "Suivant"

---

#### 3.2 Étape 2 : Informations Parent 2 (facultatif)

**Écran** : Ajout d'un co-parent (optionnel)

**Question** : "Souhaitez-vous ajouter un second parent ?"
- ⭕ Oui
- ⭕ Non

**Si Oui** :

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Nom | Text | 2-100 caractères | ✅ |
| Prénom | Text | 2-100 caractères | ✅ |
| Email | Email | Format email valide | ✅ |
| Téléphone | Tel | Format français | ✅ |
| Même adresse que Parent 1 | Checkbox | - | - |

**Si "Même adresse" non coché** : Afficher les champs adresse, code postal, ville

**Note importante** : Le Parent 2 ne définit **pas** de mot de passe lors de l'inscription. Il recevra un email avec un lien pour créer son mot de passe après validation du gestionnaire. Cette approche est particulièrement adaptée aux situations de parents séparés ou divorcés où la communication peut être difficile.

**Bouton** : "Suivant"

---

#### 3.3 Étape 3 : Informations sur l'enfant

**Écran** : Fiche enfant

**Question** : "L'enfant est-il déjà né ?"
- ⭕ Oui → Afficher "Date de naissance"
- ⭕ Non → Afficher "Date prévisionnelle de naissance"

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Prénom | Text | 2-100 caractères | ❌ (si à naître) |
| Nom | Text | Hérité des parents | Auto |
| Date de naissance | Date | Format JJ/MM/AAAA | ✅ (si né) |
| Date prévisionnelle | Date | Format JJ/MM/AAAA | ✅ (si à naître) |
| Genre | Select | H / F | ✅ |
| Photo | File | Image (JPEG/PNG), max 5MB | ✅ (si né) |
| Grossesse multiple | Checkbox | Jumeaux, triplés, etc. | ❌ |

**Bouton** : "Ajouter un autre enfant" (optionnel)  
**Bouton** : "Suivant"

**Note** : Rattachement automatique aux deux parents si Parent 2 renseigné.

---

#### 3.4 Étape 4 : Présentation du dossier

**Écran** : Zone de texte libre

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Présentation | Textarea | Max 2000 caractères | ⚙️ Configurable |

**Exemple de texte d'aide** :
> "Décrivez votre situation familiale, vos besoins de garde, vos contraintes horaires, etc. Cette présentation sera visible par les assistantes maternelles et le gestionnaire."

**Bouton** : "Suivant"

---

#### 3.5 Étape 5 : Acceptation des CGU

**Écran** : Conditions Générales d'Utilisation

| Élément | Type | Obligatoire |
|---------|------|-------------|
| CGU | Checkbox | ✅ |

**Texte** :
☐ J'ai lu et j'accepte les [Conditions Générales d'Utilisation](./cgu.pdf) et la [Politique de confidentialité](./privacy.pdf)

**Comportement** :
- Les liens ouvrent les documents PDF dans un nouvel onglet
- Le refus bloque la création de compte
- La date d'acceptation est enregistrée en base

**Bouton** : "Suivant"

---

#### 3.6 Étape 6 : Récapitulatif et validation

**Écran** : Résumé de toutes les informations saisies

**Sections affichées** :
1. **Parent 1** : Nom, prénom, email, téléphone, adresse
2. **Parent 2** (si renseigné) : Nom, prénom, email, téléphone
3. **Enfant(s)** : Prénom, date de naissance/prévisionnelle, photo
4. **Présentation** : Extrait du texte (100 premiers caractères)

**Boutons** :
- "Modifier" (retour aux étapes précédentes)
- "Valider et envoyer ma demande"

**Message de confirmation** :
> "Votre demande d'inscription a été envoyée. Elle sera examinée par un gestionnaire. Vous recevrez un email ou un SMS une fois votre compte validé."

**Bouton** : "Terminer"

#### 3.2 Flux technique

**Frontend → Backend**

```typescript
// Frontend (Flutter) - Route publique
// Exemple : Claire MARTIN (parent avec triplés)
// Note : Pas de mot de passe lors de l'inscription
POST /api/v1/auth/register
Headers: {
  Content-Type: application/json
}
Body: {
  "email": "claire.martin@ptits-pas.fr",
  "prenom": "Claire",
  "nom": "MARTIN",
  "telephone": "06 89 56 78 90",
  "role": "parent"
}
```

**Backend → Database**

```typescript
// Backend (NestJS)
// 1. Validation des données (DTO)
// 2. Vérification que l'email n'existe pas déjà
// 3. Génération d'un token de création de mot de passe (UUID)
// 4. Transaction : Créer utilisateur + entité métier

BEGIN TRANSACTION;

-- Création de l'utilisateur (sans mot de passe)
INSERT INTO utilisateurs (
  email, password, prenom, nom, telephone, role, statut, 
  adresse, code_postal, ville, profession, situation_familiale, date_naissance, 
  password_reset_token, password_reset_expires, cree_le
) VALUES (
  'claire.martin@ptits-pas.fr',
  NULL, -- Pas de mot de passe lors de l'inscription
  'Claire',
  'MARTIN',
  '06 89 56 78 90',
  'parent',
  'en_attente', -- Statut en attente de validation
  '5 Avenue du Général de Gaulle',
  '95870',
  'Bezons',
  'Infirmière',
  'Mariée',
  '1990-04-03',
  gen_random_uuid(), -- Token de création de mot de passe
  NOW() + INTERVAL '7 days', -- Expiration du token (7 jours)
  NOW()
) RETURNING id;

-- Création de l'entité métier parent
-- Note : id_co_parent sera renseigné plus tard si Thomas MARTIN s'inscrit
INSERT INTO parents (id_utilisateur, id_co_parent)
VALUES ('uuid-claire-martin', NULL);

COMMIT;
```

**Réponse**

```json
{
  "message": "Inscription réussie. Votre compte est en attente de validation par un gestionnaire. Vous recevrez un email une fois votre compte validé.",
  "userId": "uuid-claire-martin"
}
```

**État** : 🔴 À implémenter complètement selon CDC

---

### Étape 3bis : Inscription d'une assistante maternelle

**Acteur** : Assistante Maternelle (non authentifiée)  
**Interface** : Page publique d'inscription assistante maternelle  
**Référence CDC** : Section 3.2

Le processus d'inscription assistante maternelle se déroule en **5 étapes** avec 2 panneaux principaux.

#### 3bis.1 Panneau 1 : Informations d'identité

**Écran** : Formulaire d'identité

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Nom | Text | 2-100 caractères | ✅ |
| Prénom | Text | 2-100 caractères | ✅ |
| Adresse postale | Text | Adresse complète | ✅ |
| Code postal | Text | 5 chiffres | ✅ |
| Ville | Text | 2-150 caractères | ✅ |
| Téléphone | Tel | Format français | ✅ |
| Email | Email | Format email valide | ✅ |
| Photo de profil | File | Image (JPEG/PNG), max 5MB | ⚙️ Configurable |

**Consentement photo** (si photo uploadée) :

☐ J'autorise le stockage et l'affichage de ma photo sur la plateforme (RGPD)

**Note importante** : L'assistante maternelle ne définit **pas** de mot de passe lors de l'inscription. Elle recevra un email avec un lien pour créer son mot de passe après validation du gestionnaire.

**Note** : La date du consentement est enregistrée automatiquement.

**Bouton** : "Suivant"

---

#### 3bis.2 Panneau 2 : Informations professionnelles

**Écran** : Informations professionnelles

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Date de naissance | Date | Format JJ/MM/AAAA | ✅ |
| Ville de naissance | Text | 2-150 caractères | ✅ |
| Pays de naissance | Select | Liste des pays | ✅ |
| Numéro de Sécurité sociale (NIR) | Text | 15 chiffres | ✅ |
| Numéro d'agrément | Text | Format libre | ✅ |
| Date d'obtention de l'agrément | Date | Format JJ/MM/AAAA | ✅ |
| Nombre d'enfants pouvant être accueillis | Number | 1-6 | ✅ |

**Note importante affichée** :
> ⚠️ Le numéro de Sécurité sociale (NIR) est saisi en clair et utilisé uniquement pour la génération automatique du contrat. Il est stocké de manière sécurisée et conforme au RGPD.

**Bouton** : "Suivant"

---

#### 3bis.3 Présentation

**Écran** : Message au gestionnaire

| Champ | Type | Validation | Obligatoire |
|-------|------|------------|-------------|
| Présentation | Textarea | Max 2000 caractères | ❌ |

**Exemple de texte d'aide** :
> "Présentez-vous et expliquez votre démarche. Vous pouvez ajouter des précisions sur votre expérience, votre méthode pédagogique, vos disponibilités, etc."

**Bouton** : "Suivant"

---

#### 3bis.4 Acceptation des CGU

**Écran** : Conditions Générales d'Utilisation

| Élément | Type | Obligatoire |
|---------|------|-------------|
| CGU | Checkbox | ✅ |

**Texte** :
☐ J'ai lu et j'accepte les [Conditions Générales d'Utilisation](./cgu.pdf) et la [Politique de confidentialité](./privacy.pdf)

**Comportement** :
- Les liens ouvrent les documents PDF dans un nouvel onglet
- Le refus bloque la création de compte
- La date d'acceptation est enregistrée en base

**Bouton** : "Suivant"

---

#### 3bis.5 Récapitulatif et validation

**Écran** : Résumé de toutes les informations saisies

**Sections affichées** :
1. **Identité** : Nom, prénom, email, téléphone, adresse, photo
2. **Informations professionnelles** : 
   - Date de naissance, lieu de naissance
   - NIR (masqué : XXX XX XX XX XXX 123)
   - Numéro d'agrément
   - Capacité d'accueil
3. **Présentation** : Extrait du texte (100 premiers caractères)

**Boutons** :
- "Modifier" (retour aux étapes précédentes)
- "Valider et envoyer ma demande"

**Message de confirmation** :
> "Votre demande d'inscription a été envoyée. Elle sera examinée par un gestionnaire. Vous recevrez un email ou un SMS une fois votre compte validé."

**Bouton** : "Terminer"

**État** : 🔴 À implémenter complètement selon CDC

---

### Étape 4 : Consultation des demandes par le gestionnaire

**Acteur** : Gestionnaire  
**Interface** : Dashboard gestionnaire avec 2 onglets

#### 4.1 Interface utilisateur

**Écran** : Dashboard avec navigation par onglets

```
┌─────────────────────────────────────────────────────────┐
│  Dashboard Gestionnaire                                 │
├─────────────────────────────────────────────────────────┤
│  [ Parents ]  [ Assistantes Maternelles ]               │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  📋 Demandes en attente (3)                            │
│                                                         │
│  ┌─────────────────────────────────────────────────┐  │
│  │ 👤 Jean MARTIN                                  │  │
│  │ 📧 jean.martin@example.com                      │  │
│  │ 📱 06 01 02 03 04                               │  │
│  │ 📅 Inscrit le : 20/11/2025                      │  │
│  │                                                 │  │
│  │    [ ✅ Valider ]    [ ❌ Refuser ]             │  │
│  └─────────────────────────────────────────────────┘  │
│                                                         │
│  ┌─────────────────────────────────────────────────┐  │
│  │ 👤 Sophie DURAND                                │  │
│  │ ...                                             │  │
│  └─────────────────────────────────────────────────┘  │
│                                                         │
└─────────────────────────────────────────────────────────┘
```

#### 4.2 Flux technique - Liste des parents

**Frontend → Backend**

```typescript
// Frontend (Flutter)
GET /api/v1/parents
Headers: {
  Authorization: Bearer <gestionnaire_token>
}
Query params: {
  statut: "en_attente" // Filtrer uniquement les comptes en attente
}
```

**Backend → Database**

```sql
-- Backend (NestJS)
SELECT 
  u.id,
  u.email,
  u.prenom,
  u.nom,
  u.telephone,
  u.statut,
  u.cree_le,
  p.id_co_parent
FROM utilisateurs u
LEFT JOIN parents p ON u.id = p.id_utilisateur
WHERE u.role = 'parent' 
  AND u.statut = 'en_attente'
ORDER BY u.cree_le DESC;
```

**Réponse**

```json
[
  {
    "id": "uuid-claire-martin",
    "email": "claire.martin@ptits-pas.fr",
    "prenom": "Claire",
    "nom": "MARTIN",
    "telephone": "06 89 56 78 90",
    "ville": "Bezons",
    "profession": "Infirmière",
    "situation_familiale": "Mariée",
    "statut": "en_attente",
    "cree_le": "2025-11-20T14:30:00Z"
  },
  {
    "id": "uuid-david-lecomte",
    "email": "david.lecomte@ptits-pas.fr",
    "prenom": "David",
    "nom": "LECOMTE",
    "telephone": "06 45 56 67 78",
    "ville": "Bezons",
    "profession": "Développeur web",
    "situation_familiale": "Père célibataire",
    "statut": "en_attente",
    "cree_le": "2025-11-21T09:15:00Z"
  }
]
```

#### 4.3 Flux technique - Liste des assistantes maternelles

**Frontend → Backend**

```typescript
// Frontend (Flutter)
GET /api/v1/assistantes-maternelles
Headers: {
  Authorization: Bearer <gestionnaire_token>
}
Query params: {
  statut: "en_attente"
}
```

**Backend → Database**

```sql
-- Backend (NestJS)
SELECT 
  u.id,
  u.email,
  u.prenom,
  u.nom,
  u.telephone,
  u.statut,
  u.cree_le,
  am.numero_agrement,
  am.ville_residence
FROM utilisateurs u
LEFT JOIN assistantes_maternelles am ON u.id = am.id_utilisateur
WHERE u.role = 'assistante_maternelle' 
  AND u.statut = 'en_attente'
ORDER BY u.cree_le DESC;
```

**Réponse**

```json
[
  {
    "id": "uuid-marie-dubois",
    "email": "marie.dubois@ptits-pas.fr",
    "prenom": "Marie",
    "nom": "DUBOIS",
    "telephone": "06 96 34 56 78",
    "ville": "Bezons",
    "statut": "en_attente",
    "cree_le": "2025-11-22T11:00:00Z",
    "numero_agrement": null,
    "ville_residence": "Bezons"
  },
  {
    "id": "uuid-fatima-elmansouri",
    "email": "fatima.elmansouri@ptits-pas.fr",
    "prenom": "Fatima",
    "nom": "EL MANSOURI",
    "telephone": "06 75 45 67 89",
    "ville": "Bezons",
    "statut": "en_attente",
    "cree_le": "2025-11-22T15:30:00Z",
    "numero_agrement": null,
    "ville_residence": "Bezons"
  }
]
```

**État** : 🟠 Backend implémenté, Frontend à connecter (actuellement en mock)

---

### Étape 5 : Validation d'un compte

**Acteur** : Gestionnaire  
**Action** : Clic sur le bouton "Valider"

#### 5.1 Flux technique - Validation

**Frontend → Backend**

```typescript
// Frontend (Flutter)
PATCH /api/v1/users/{userId}/valider
Headers: {
  Authorization: Bearer <gestionnaire_token>
  Content-Type: application/json
}
Body: {
  "comment": "Dossier complet, compte validé" // Optionnel
}
```

**Backend → Database**

```sql
-- Backend (NestJS)
-- Exemple : Lucas MOREAU valide Marie DUBOIS
BEGIN TRANSACTION;

-- Mise à jour du statut utilisateur
UPDATE utilisateurs 
SET statut = 'actif', 
    modifie_le = NOW()
WHERE id = 'uuid-marie-dubois';

-- Enregistrement de la validation
INSERT INTO validations (
  id_utilisateur,
  type,
  statut,
  valide_par,
  commentaire,
  cree_le
) VALUES (
  'uuid-marie-dubois',
  'validation_compte',
  'valide',
  'uuid-lucas-moreau',
  'Agrément vérifié - Profil complet',
  NOW()
);

COMMIT;
```

**Backend → Service Email**

```typescript
// Envoi du lien de création de mot de passe pour tous les utilisateurs (Parents et AM)
await this.mailService.sendPasswordCreationLink({
  to: user.email,
  prenom: user.prenom,
  nom: user.nom,
  token: user.password_reset_token,
  expiresAt: user.password_reset_expires,
  role: user.role // 'parent' ou 'assistante_maternelle'
});

// Si Parent 2 existe, envoi du même type d'email
if (user.role === 'parent' && parent2) {
  await this.mailService.sendPasswordCreationLink({
    to: parent2.email,
    prenom: parent2.prenom,
    nom: parent2.nom,
    token: parent2.password_reset_token,
    expiresAt: parent2.password_reset_expires,
    role: 'parent',
    isCoParent: true // Indique qu'il s'agit du co-parent
  });
}
```

**Réponse**

```json
{
  "message": "Compte validé avec succès",
  "userId": "uuid-marie-dubois",
  "emailSent": true
}
```

#### 5.2 Flux technique - Refus

**Frontend → Backend**

```typescript
// Frontend (Flutter)
PATCH /api/v1/users/{userId}/suspendre
Headers: {
  Authorization: Bearer <gestionnaire_token>
  Content-Type: application/json
}
Body: {
  "comment": "Informations incomplètes" // Obligatoire pour un refus
}
```

**Backend → Database**

```sql
-- Backend (NestJS)
-- Exemple : Lucas MOREAU refuse un compte (exemple fictif)
BEGIN TRANSACTION;

-- Mise à jour du statut utilisateur
UPDATE utilisateurs 
SET statut = 'suspendu', 
    modifie_le = NOW()
WHERE id = 'uuid-utilisateur-refuse';

-- Enregistrement du refus
INSERT INTO validations (
  id_utilisateur,
  type,
  statut,
  valide_par,
  commentaire,
  cree_le
) VALUES (
  'uuid-utilisateur-refuse',
  'validation_compte',
  'refuse',
  'uuid-lucas-moreau',
  'Informations incomplètes - Documents manquants',
  NOW()
);

COMMIT;
```

**Backend → Service Email**

```typescript
// Envoi de l'email de notification
await this.mailService.sendAccountRejected({
  to: user.email,
  prenom: user.prenom,
  nom: user.nom,
  role: user.role,
  reason: comment
});
```

**Réponse**

```json
{
  "message": "Compte refusé",
  "userId": "uuid-utilisateur-refuse",
  "emailSent": true
}
```

**État** : 🔴 Backend partiellement implémenté (manque envoi email), Frontend à connecter

---

### Étape 6 : Réception de la notification

**Acteur** : Parent ou Assistante Maternelle  
**Canal** : Email **OU** SMS (conformément au CDC 3.1.6 et 3.2.5)

**Note** : Le choix du canal de notification (email/SMS) peut être :
- Configuré par l'administrateur (paramètre global)
- Choisi par l'utilisateur lors de l'inscription
- Les deux en parallèle pour plus de fiabilité

#### 6.1 Email de validation - Parents (avec création de mot de passe)

**Expéditeur** : `no-reply@ptits-pas.fr`  
**Destinataire** : Email du parent  
**Objet** : `Votre compte P'titsPas a été validé - Créez votre mot de passe ✅`

**Template Parent 1** :

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
    .header { background-color: #4CAF50; color: white; padding: 20px; text-align: center; }
    .content { padding: 20px; background-color: #f9f9f9; }
    .button { display: inline-block; padding: 10px 20px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 5px; }
    .footer { text-align: center; padding: 20px; font-size: 12px; color: #666; }
    .warning { background-color: #FFF3CD; border-left: 4px solid #FFC107; padding: 10px; margin: 15px 0; }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>✅ Compte validé</h1>
    </div>
    <div class="content">
      <p>Bonjour {{prenom}} {{nom}},</p>
      
      <p>Bonne nouvelle ! Votre compte <strong>P'titsPas</strong> a été validé par notre équipe.</p>
      
      <p>Pour finaliser votre inscription et accéder à votre espace parent, veuillez créer votre mot de passe en cliquant sur le bouton ci-dessous :</p>
      
      <p style="text-align: center;">
        <a href="https://app.ptits-pas.fr/create-password?token={{token}}" class="button">Créer mon mot de passe</a>
      </p>
      
      <div class="warning">
        <strong>⏰ Attention :</strong> Ce lien est valable pendant <strong>7 jours</strong> (jusqu'au {{expires_date}}).
      </div>
      
      <p><strong>Votre identifiant :</strong> {{email}}</p>
      
      <p>Si vous avez des questions, n'hésitez pas à nous contacter à <a href="mailto:contact@ptits-pas.fr">contact@ptits-pas.fr</a>.</p>
      
      <p>À très bientôt sur P'titsPas !</p>
      
      <p>L'équipe P'titsPas</p>
    </div>
    <div class="footer">
      <p>P'titsPas - Plateforme de mise en relation parents / assistantes maternelles</p>
      <p><a href="https://ptits-pas.fr">ptits-pas.fr</a></p>
    </div>
  </div>
</body>
</html>
```

**Template Parent 2 (Co-parent)** :

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
    .header { background-color: #4CAF50; color: white; padding: 20px; text-align: center; }
    .content { padding: 20px; background-color: #f9f9f9; }
    .button { display: inline-block; padding: 10px 20px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 5px; }
    .footer { text-align: center; padding: 20px; font-size: 12px; color: #666; }
    .warning { background-color: #FFF3CD; border-left: 4px solid #FFC107; padding: 10px; margin: 15px 0; }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>✅ Bienvenue sur P'titsPas</h1>
    </div>
    <div class="content">
      <p>Bonjour {{prenom}} {{nom}},</p>
      
      <p>Votre co-parent vous a ajouté sur la plateforme <strong>P'titsPas</strong> et votre compte a été validé par notre équipe.</p>
      
      <p>Pour accéder à votre espace parent et consulter les informations de vos enfants, veuillez créer votre mot de passe en cliquant sur le bouton ci-dessous :</p>
      
      <p style="text-align: center;">
        <a href="https://app.ptits-pas.fr/create-password?token={{token}}" class="button">Créer mon mot de passe</a>
      </p>
      
      <div class="warning">
        <strong>⏰ Attention :</strong> Ce lien est valable pendant <strong>7 jours</strong> (jusqu'au {{expires_date}}).
      </div>
      
      <p><strong>Votre identifiant :</strong> {{email}}</p>
      
      <p>Si vous avez des questions ou si vous n'êtes pas à l'origine de cette inscription, contactez-nous à <a href="mailto:contact@ptits-pas.fr">contact@ptits-pas.fr</a>.</p>
      
      <p>À très bientôt sur P'titsPas !</p>
      
      <p>L'équipe P'titsPas</p>
    </div>
    <div class="footer">
      <p>P'titsPas - Plateforme de mise en relation parents / assistantes maternelles</p>
      <p><a href="https://ptits-pas.fr">ptits-pas.fr</a></p>
    </div>
  </div>
</body>
</html>
```

#### 6.2 Email de validation - Assistantes Maternelles (avec création de mot de passe)

**Expéditeur** : `no-reply@ptits-pas.fr`  
**Destinataire** : Email de l'assistante maternelle  
**Objet** : `Votre compte P'titsPas a été validé - Créez votre mot de passe ✅`

**Template** :

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
    .header { background-color: #4CAF50; color: white; padding: 20px; text-align: center; }
    .content { padding: 20px; background-color: #f9f9f9; }
    .button { display: inline-block; padding: 10px 20px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 5px; }
    .footer { text-align: center; padding: 20px; font-size: 12px; color: #666; }
    .warning { background-color: #FFF3CD; border-left: 4px solid #FFC107; padding: 10px; margin: 15px 0; }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>✅ Compte validé</h1>
    </div>
    <div class="content">
      <p>Bonjour {{prenom}} {{nom}},</p>
      
      <p>Bonne nouvelle ! Votre compte <strong>P'titsPas</strong> a été validé par notre équipe.</p>
      
      <p>Pour finaliser votre inscription et accéder à votre espace assistante maternelle, veuillez créer votre mot de passe en cliquant sur le bouton ci-dessous :</p>
      
      <p style="text-align: center;">
        <a href="https://app.ptits-pas.fr/create-password?token={{token}}" class="button">Créer mon mot de passe</a>
      </p>
      
      <div class="warning">
        <strong>⏰ Attention :</strong> Ce lien est valable pendant <strong>7 jours</strong> (jusqu'au {{expires_date}}).
      </div>
      
      <p><strong>Votre identifiant :</strong> {{email}}</p>
      
      <p>Si vous avez des questions, n'hésitez pas à nous contacter à <a href="mailto:contact@ptits-pas.fr">contact@ptits-pas.fr</a>.</p>
      
      <p>À très bientôt sur P'titsPas !</p>
      
      <p>L'équipe P'titsPas</p>
    </div>
    <div class="footer">
      <p>P'titsPas - Plateforme de mise en relation parents / assistantes maternelles</p>
      <p><a href="https://ptits-pas.fr">ptits-pas.fr</a></p>
    </div>
  </div>
</body>
</html>
```

#### 6.3 Email de refus

**Expéditeur** : `no-reply@ptits-pas.fr`  
**Destinataire** : Email de l'utilisateur  
**Objet** : `Votre demande d'inscription P'titsPas`

**Template** :

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
    .header { background-color: #FF9800; color: white; padding: 20px; text-align: center; }
    .content { padding: 20px; background-color: #f9f9f9; }
    .footer { text-align: center; padding: 20px; font-size: 12px; color: #666; }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>Votre demande d'inscription</h1>
    </div>
    <div class="content">
      <p>Bonjour {{prenom}} {{nom}},</p>
      
      <p>Nous avons bien reçu votre demande d'inscription sur <strong>P'titsPas</strong>.</p>
      
      <p>Malheureusement, nous ne pouvons pas valider votre compte pour le moment.</p>
      
      <p><strong>Motif :</strong> {{reason}}</p>
      
      <p>Si vous pensez qu'il s'agit d'une erreur ou si vous souhaitez plus d'informations, n'hésitez pas à nous contacter à <a href="mailto:contact@ptits-pas.fr">contact@ptits-pas.fr</a>.</p>
      
      <p>Cordialement,</p>
      
      <p>L'équipe P'titsPas</p>
    </div>
    <div class="footer">
      <p>P'titsPas - Plateforme de mise en relation parents / assistantes maternelles</p>
      <p><a href="https://ptits-pas.fr">ptits-pas.fr</a></p>
    </div>
  </div>
</body>
</html>
```

**État** : 🔴 À implémenter

---

#### 6.3 SMS de validation (optionnel)

**Expéditeur** : P'titsPas (nom court configurable)  
**Destinataire** : Numéro de téléphone de l'utilisateur

**Template SMS** :

```
P'titsPas : Votre compte a été validé ! Créez votre mot de passe : https://app.ptits-pas.fr/create-password?token={{token}} (valable 7 jours)
```

**Contraintes** :
- Maximum 160 caractères (SMS standard)
- Lien court pour l'URL
- Message clair et concis

---

#### 6.4 SMS de refus (optionnel)

**Expéditeur** : P'titsPas  
**Destinataire** : Numéro de téléphone de l'utilisateur

**Template SMS** :

```
P'titsPas : Votre demande d'inscription n'a pas pu être validée. Motif : {{reason_court}}. Contactez-nous : contact@ptits-pas.fr
```

**Contraintes** :
- Maximum 160 caractères
- Motif abrégé si nécessaire
- Contact pour plus d'informations

**État** : 🔴 À implémenter (Service SMS à configurer : Twilio, OVH, etc.)

---

### Étape 7 : Création du mot de passe

**Acteur** : Parent (Parent 1 ou Parent 2) ou Assistante Maternelle  
**Interface** : Page de création de mot de passe (lien reçu par email)

#### 7.1 Flux technique

**Frontend → Backend**

```typescript
// Frontend (Flutter/Web)
// L'utilisateur clique sur le lien reçu par email
// URL : https://app.ptits-pas.fr/create-password?token=<uuid>

GET /api/v1/auth/verify-token?token=<uuid>
// Vérification que le token est valide et non expiré

// Si valide, affichage du formulaire de création de mot de passe
POST /api/v1/auth/create-password
Headers: {
  Content-Type: application/json
}
Body: {
  "token": "<uuid>",
  "password": "NouveauMotDePasse123!",
  "password_confirmation": "NouveauMotDePasse123!"
}
```

**Backend → Database**

```typescript
// Backend (NestJS)
// 1. Vérification du token (existe, non expiré, non utilisé)
// 2. Validation du mot de passe (min 8 caractères, 1 majuscule, 1 chiffre)
// 3. Hash du mot de passe (bcrypt, 12 rounds)
// 4. Mise à jour de l'utilisateur

UPDATE utilisateurs
SET password = '$2b$12$...', -- Hash bcrypt du nouveau mot de passe
    password_reset_token = NULL, -- Suppression du token
    password_reset_expires = NULL,
    statut = 'actif', -- Activation du compte
    modifie_le = NOW()
WHERE password_reset_token = '<uuid>'
  AND password_reset_expires > NOW()
  AND password IS NULL; -- Sécurité : uniquement si pas de mot de passe existant
```

**Réponse**

```json
{
  "message": "Mot de passe créé avec succès. Vous pouvez maintenant vous connecter.",
  "userId": "uuid-claire-martin"
}
```

**Frontend** : Redirection automatique vers la page de connexion avec un message de succès.

**État** : 🔴 À implémenter (Frontend + Backend)

---

### Étape 8 : Connexion de l'utilisateur validé

**Acteur** : Parent ou Assistante Maternelle (compte validé et mot de passe défini)  
**Interface** : Page de connexion

#### 7.1 Flux technique

**Frontend → Backend**

```typescript
// Frontend (Flutter)
// Exemple : Claire MARTIN se connecte après validation
POST /api/v1/auth/login
Headers: {
  Content-Type: application/json
}
Body: {
  "email": "claire.martin@ptits-pas.fr",
  "password": "Test1234!"
}
```

**Backend → Database**

```sql
-- Backend (NestJS)
SELECT 
  id, email, password, prenom, nom, role, statut
FROM utilisateurs 
WHERE email = 'jean.martin@example.com';

-- Vérification :
-- 1. L'utilisateur existe
-- 2. Le mot de passe correspond (bcrypt.compare)
-- 3. Le statut est 'actif' (sinon erreur 403)
```

**Réponse - Succès**

```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "uuid-claire-martin",
    "email": "claire.martin@ptits-pas.fr",
    "role": "parent",
    "prenom": "Claire",
    "nom": "MARTIN",
    "statut": "actif"
  }
}
```

**Réponse - Compte en attente**

```json
{
  "statusCode": 403,
  "message": "Votre compte est en attente de validation. Vous recevrez un email une fois votre compte validé.",
  "error": "Forbidden"
}
```

**Réponse - Compte refusé**

```json
{
  "statusCode": 403,
  "message": "Votre compte a été refusé. Contactez contact@ptits-pas.fr pour plus d'informations.",
  "error": "Forbidden"
}
```

#### 7.2 Redirection après connexion

**Parent validé** → Dashboard parent (page simple : "Vous êtes connecté")  
**Assistante Maternelle validée** → Dashboard AM (page simple : "Vous êtes connecté")

**État** : ✅ Backend implémenté, Frontend à adapter

---

## 📊 Diagrammes de séquence

### Diagramme 1 : Création d'un gestionnaire

```mermaid
sequenceDiagram
    participant SA as Super Admin<br/>(Frontend)
    participant API as Backend API<br/>(NestJS)
    participant Auth as AuthGuard<br/>+ RolesGuard
    participant DB as PostgreSQL

    SA->>API: POST /gestionnaires<br/>{nom, prenom, email, password}
    API->>Auth: Vérifier token JWT
    Auth->>Auth: Vérifier role = super_admin
    Auth-->>API: ✅ Autorisé
    
    API->>API: Valider DTO (CreateGestionnaireDto)
    API->>API: Hash password (bcrypt, 12 rounds)
    
    API->>DB: INSERT INTO utilisateurs<br/>(role='gestionnaire', statut='actif')
    DB-->>API: ✅ Utilisateur créé (id, email, ...)
    
    API-->>SA: 201 Created<br/>{id, email, prenom, nom, role}
    
    SA->>SA: Afficher message de succès
```

---

### Diagramme 2 : Inscription d'un parent

```mermaid
sequenceDiagram
    participant P as Parent<br/>(Frontend)
    participant API as Backend API<br/>(NestJS)
    participant DB as PostgreSQL

    P->>API: POST /auth/register<br/>{email, password, prenom, nom, role='parent'}
    
    API->>API: Valider DTO (RegisterDto)
    
    API->>DB: SELECT * FROM utilisateurs<br/>WHERE email = ?
    DB-->>API: ❌ Aucun résultat
    
    API->>API: Hash password (bcrypt, 12 rounds)
    
    API->>DB: BEGIN TRANSACTION
    
    API->>DB: INSERT INTO utilisateurs<br/>(role='parent', statut='en_attente')
    DB-->>API: ✅ id_utilisateur
    
    API->>DB: INSERT INTO parents<br/>(id_utilisateur)
    DB-->>API: ✅ Parent créé
    
    API->>DB: COMMIT
    
    API-->>P: 201 Created<br/>{message, userId}
    
    P->>P: Afficher message:<br/>"Inscription réussie.<br/>Votre compte est en attente<br/>de validation."
```

---

### Diagramme 3 : Validation d'un compte par le gestionnaire

```mermaid
sequenceDiagram
    participant G as Gestionnaire<br/>(Frontend)
    participant API as Backend API<br/>(NestJS)
    participant Auth as AuthGuard<br/>+ RolesGuard
    participant DB as PostgreSQL
    participant Mail as Service Email<br/>(Nodemailer)
    participant SMTP as Serveur SMTP<br/>(mail.ptits-pas.fr)
    participant U as Utilisateur<br/>(Email)

    G->>API: GET /parents?statut=en_attente
    API->>Auth: Vérifier token + role gestionnaire
    Auth-->>API: ✅ Autorisé
    API->>DB: SELECT * FROM utilisateurs<br/>WHERE role='parent' AND statut='en_attente'
    DB-->>API: Liste des parents en attente
    API-->>G: 200 OK<br/>[{id, email, prenom, nom, ...}]
    
    G->>G: Afficher liste
    G->>G: Clic sur "Valider"
    
    G->>API: PATCH /users/{id}/valider<br/>{comment: "Dossier complet"}
    API->>Auth: Vérifier token + role gestionnaire
    Auth-->>API: ✅ Autorisé
    
    API->>DB: BEGIN TRANSACTION
    API->>DB: UPDATE utilisateurs<br/>SET statut='actif'<br/>WHERE id=?
    DB-->>API: ✅ 1 row updated
    
    API->>DB: INSERT INTO validations<br/>(type, statut, valide_par, ...)
    DB-->>API: ✅ Validation enregistrée
    
    API->>DB: COMMIT
    
    API->>Mail: sendAccountValidated(user)
    Mail->>Mail: Générer HTML depuis template
    Mail->>SMTP: SMTP SEND<br/>From: no-reply@ptits-pas.fr<br/>To: user.email<br/>Subject: Compte validé
    SMTP->>U: 📧 Email de validation
    SMTP-->>Mail: ✅ Email envoyé
    Mail-->>API: ✅ emailSent: true
    
    API-->>G: 200 OK<br/>{message, userId, emailSent}
    
    G->>G: Retirer l'utilisateur de la liste<br/>Afficher notification de succès
    
    U->>U: 📧 Reçoit l'email
    U->>U: Clic sur "Se connecter"
```

---

### Diagramme 4 : Connexion d'un utilisateur validé

```mermaid
sequenceDiagram
    participant U as Utilisateur<br/>(Frontend)
    participant API as Backend API<br/>(NestJS)
    participant DB as PostgreSQL

    U->>API: POST /auth/login<br/>{email, password}
    
    API->>DB: SELECT * FROM utilisateurs<br/>WHERE email = ?
    DB-->>API: Utilisateur trouvé
    
    API->>API: bcrypt.compare(password, hash)
    API->>API: ✅ Mot de passe correct
    
    API->>API: Vérifier statut
    
    alt Statut = 'actif'
        API->>API: Générer JWT<br/>(access_token + refresh_token)
        API-->>U: 200 OK<br/>{access_token, refresh_token, user}
        U->>U: Stocker tokens
        U->>U: Redirection vers dashboard
    else Statut = 'en_attente'
        API-->>U: 403 Forbidden<br/>"Compte en attente de validation"
        U->>U: Afficher message d'attente
    else Statut = 'suspendu'
        API-->>U: 403 Forbidden<br/>"Compte refusé"
        U->>U: Afficher message + contact
    end
```

---

## 🔧 Spécifications techniques

### Architecture Backend

**Framework** : NestJS 10.x  
**Langage** : TypeScript 5.x  
**ORM** : TypeORM 0.3.x  
**Validation** : class-validator + class-transformer  
**Authentication** : JWT (jsonwebtoken + @nestjs/jwt)  
**Password Hashing** : bcrypt (12 rounds)  
**Email** : Nodemailer (à installer)

### Architecture Frontend

**Framework** : Flutter 3.19.0  
**Langage** : Dart 3.x  
**State Management** : Provider / Riverpod  
**HTTP Client** : Dio / http  
**Storage** : flutter_secure_storage (tokens)

### Architecture Database

**SGBD** : PostgreSQL 17  
**Schema** : Voir [DATABASE.md](./DATABASE.md)  
**Tables concernées** :
- `utilisateurs` (table principale)
- `parents` (extension pour parents)
- `assistantes_maternelles` (extension pour AM)
- `validations` (historique des validations)

### Configuration Email

**Serveur SMTP** : `mail.ptits-pas.fr`  
**Port** : 25 (STARTTLS)  
**Expéditeur** : `no-reply@ptits-pas.fr`  
**Authentification** : Aucune (serveur interne)

---

## 📡 APIs utilisées

### API 1 : Créer un gestionnaire

**Endpoint** : `POST /api/v1/gestionnaires`  
**Authentification** : Bearer Token (super_admin uniquement)  
**Référence** : [API.md - Gestionnaires](./API.md#post-gestionnaires)

**Request** :
```json
{
  "email": "lucas.moreau@ptits-pas.fr",
  "password": "password",
  "prenom": "Lucas",
  "nom": "MOREAU"
}
```

**Response 201** :
```json
{
  "id": "uuid-lucas-moreau",
  "email": "lucas.moreau@ptits-pas.fr",
  "role": "gestionnaire",
  "prenom": "Lucas",
  "nom": "MOREAU"
}
```

**Errors** :
- `401 Unauthorized` : Token manquant ou invalide
- `403 Forbidden` : Rôle insuffisant (pas super_admin)
- `409 Conflict` : Email déjà utilisé
- `400 Bad Request` : Données invalides

---

### API 2 : Inscription (parent ou AM)

**Endpoint** : `POST /api/v1/auth/register`  
**Authentification** : Aucune (route publique)  
**Référence** : [API.md - Authentification](./API.md#post-authregister)

**Request** :
```json
{
  "email": "claire.martin@ptits-pas.fr",
  "password": "password",
  "prenom": "Claire",
  "nom": "MARTIN",
  "telephone": "01 39 98 89 01",
  "role": "parent"
}
```

**Response 201** :
```json
{
  "message": "Inscription réussie. Votre compte est en attente de validation.",
  "userId": "uuid-claire-martin"
}
```

**Errors** :
- `409 Conflict` : Email déjà utilisé
- `400 Bad Request` : Données invalides

---

### API 3 : Liste des parents en attente

**Endpoint** : `GET /api/v1/parents`  
**Authentification** : Bearer Token (gestionnaire ou super_admin)  
**Référence** : [API.md - Parents](./API.md#get-parents)

**Query Params** :
```
?statut=en_attente
```

**Response 200** :
```json
[
  {
    "id": "uuid",
    "email": "parent@example.com",
    "prenom": "Jean",
    "nom": "Martin",
    "telephone": "0601020304",
    "statut": "en_attente",
    "cree_le": "2025-11-20T14:30:00Z"
  }
]
```

**Errors** :
- `401 Unauthorized` : Token manquant ou invalide
- `403 Forbidden` : Rôle insuffisant

---

### API 4 : Liste des assistantes maternelles en attente

**Endpoint** : `GET /api/v1/assistantes-maternelles`  
**Authentification** : Bearer Token (gestionnaire ou super_admin)  
**Référence** : [API.md - Assistantes Maternelles](./API.md#get-assistantes-maternelles)

**Query Params** :
```
?statut=en_attente
```

**Response 200** :
```json
[
  {
    "id": "uuid",
    "email": "am@example.com",
    "prenom": "Marie",
    "nom": "Leblanc",
    "telephone": "0698765432",
    "statut": "en_attente",
    "cree_le": "2025-11-22T11:00:00Z"
  }
]
```

---

### API 5 : Valider un compte

**Endpoint** : `PATCH /api/v1/users/{id}/valider`  
**Authentification** : Bearer Token (gestionnaire, administrateur ou super_admin)  
**Référence** : [API.md - Utilisateurs](./API.md#patch-usersidvalider)

**Request** :
```json
{
  "comment": "Dossier complet, compte validé"
}
```

**Response 200** :
```json
{
  "message": "Compte validé avec succès",
  "userId": "uuid",
  "emailSent": true
}
```

**Errors** :
- `401 Unauthorized` : Token manquant ou invalide
- `403 Forbidden` : Rôle insuffisant
- `404 Not Found` : Utilisateur introuvable
- `400 Bad Request` : ID invalide

---

### API 6 : Refuser un compte

**Endpoint** : `PATCH /api/v1/users/{id}/suspendre`  
**Authentification** : Bearer Token (gestionnaire, administrateur ou super_admin)  
**Référence** : [API.md - Utilisateurs](./API.md#patch-usersidsuspendre)

**Request** :
```json
{
  "comment": "Informations incomplètes"
}
```

**Response 200** :
```json
{
  "message": "Compte suspendu",
  "userId": "uuid",
  "emailSent": true
}
```

---

### API 7 : Connexion

**Endpoint** : `POST /api/v1/auth/login`  
**Authentification** : Aucune (route publique)  
**Référence** : [API.md - Authentification](./API.md#post-authlogin)

**Request** :
```json
{
  "email": "parent@example.com",
  "password": "MotDePasse123"
}
```

**Response 200** :
```json
{
  "access_token": "eyJhbGc...",
  "refresh_token": "eyJhbGc...",
  "user": {
    "id": "uuid",
    "email": "parent@example.com",
    "role": "parent",
    "prenom": "Jean",
    "nom": "Martin",
    "statut": "actif"
  }
}
```

**Errors** :
- `401 Unauthorized` : Email ou mot de passe incorrect
- `403 Forbidden` : Compte en attente ou suspendu

---

## 🗄️ Modèles de données

### Utilisateur

**Table** : `utilisateurs`  
**Référence** : [DATABASE.md - Table utilisateurs](./DATABASE.md#1-utilisateurs)

```typescript
interface Utilisateur {
  id: UUID;                          // Identifiant unique
  email: string;                     // Email (unique)
  password: string;                  // Hash bcrypt
  prenom: string;                    // Prénom
  nom: string;                       // Nom
  genre?: 'H' | 'F' | 'Autre';      // Genre (optionnel)
  role: RoleType;                    // Rôle (voir enum ci-dessous)
  statut: StatutUtilisateurType;     // Statut (voir enum ci-dessous)
  telephone?: string;                // Téléphone
  adresse?: string;                  // Adresse complète
  photo_url?: string;                // URL photo de profil
  consentement_photo: boolean;       // Consentement photo
  date_consentement_photo?: Date;    // Date du consentement
  changement_mdp_obligatoire: boolean; // Force changement MDP
  cree_le: Date;                     // Date de création
  modifie_le: Date;                  // Dernière modification
  ville?: string;                    // Ville
  code_postal?: string;              // Code postal
  telephone?: string;                // Téléphone
  profession?: string;               // Profession
  situation_familiale?: string;      // Situation familiale
  date_naissance?: Date;             // Date de naissance
}
```

**Enums** :

```typescript
enum RoleType {
  PARENT = 'parent',
  GESTIONNAIRE = 'gestionnaire',
  SUPER_ADMIN = 'super_admin',
  ASSISTANTE_MATERNELLE = 'assistante_maternelle',
  ADMINISTRATEUR = 'administrateur'
}

enum StatutUtilisateurType {
  EN_ATTENTE = 'en_attente',
  ACTIF = 'actif',
  SUSPENDU = 'suspendu'
}
```

---

### Parent

**Table** : `parents`  
**Référence** : [DATABASE.md - Table parents](./DATABASE.md#3-parents)

```typescript
interface Parent {
  id_utilisateur: UUID;              // FK → utilisateurs(id)
  id_co_parent?: UUID;               // FK → utilisateurs(id) - Co-parent optionnel
}
```

**Relation** : 1:1 avec `utilisateurs`

---

### Assistante Maternelle

**Table** : `assistantes_maternelles`  
**Référence** : [DATABASE.md - Table assistantes_maternelles](./DATABASE.md#2-assistantes_maternelles)

```typescript
interface AssistanteMaternelle {
  id_utilisateur: UUID;              // FK → utilisateurs(id)
  numero_agrement?: string;          // Numéro d'agrément
  nir_chiffre?: string;              // NIR (15 caractères)
  nb_max_enfants?: number;           // Capacité maximale
  biographie?: string;               // Présentation
  disponible: boolean;               // Disponibilité
  ville_residence?: string;          // Ville
  date_agrement?: Date;              // Date d'agrément
  annee_experience?: number;         // Années d'expérience
  specialite?: string;               // Spécialités
  place_disponible?: number;         // Places disponibles
}
```

**Relation** : 1:1 avec `utilisateurs`

---

### Validation

**Table** : `validations`  
**Référence** : [DATABASE.md - Table validations](./DATABASE.md#14-validations)

```typescript
interface Validation {
  id: UUID;                          // Identifiant unique
  id_utilisateur: UUID;              // FK → utilisateurs(id)
  type: string;                      // Type de validation (ex: 'validation_compte')
  statut: StatutValidationType;      // Statut (voir enum ci-dessous)
  cree_le: Date;                     // Date de demande
  modifie_le: Date;                  // Dernière modification
  valide_par?: UUID;                 // FK → utilisateurs(id) - Validateur
  commentaire?: string;              // Commentaire du validateur
}
```

**Enum** :

```typescript
enum StatutValidationType {
  EN_ATTENTE = 'en_attente',
  VALIDE = 'valide',
  REFUSE = 'refuse'
}
```

---

## 📧 Templates d'emails

### Configuration Nodemailer

**Installation** :
```bash
npm install nodemailer
npm install -D @types/nodemailer
```

**Configuration** (`backend/src/mail/mail.config.ts`) :

```typescript
import { MailerOptions } from '@nestjs-modules/mailer';
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';

export const mailConfig: MailerOptions = {
  transport: {
    host: 'mail.ptits-pas.fr',
    port: 25,
    secure: false,
    tls: {
      rejectUnauthorized: false
    }
  },
  defaults: {
    from: '"P\'titsPas" <no-reply@ptits-pas.fr>',
  },
  template: {
    dir: __dirname + '/templates',
    adapter: new HandlebarsAdapter(),
    options: {
      strict: true,
    },
  },
};
```

### Service Email

**Fichier** : `backend/src/mail/mail.service.ts`

```typescript
import { Injectable } from '@nestjs/common';
import { MailerService } from '@nestjs-modules/mailer';

@Injectable()
export class MailService {
  constructor(private mailerService: MailerService) {}

  async sendAccountValidated(user: {
    email: string;
    prenom: string;
    nom: string;
    role: string;
  }): Promise<boolean> {
    try {
      const roleLabel = user.role === 'parent' ? 'Parent' : 'Assistante Maternelle';
      
      await this.mailerService.sendMail({
        to: user.email,
        subject: 'Votre compte P\'titsPas a été validé ✅',
        template: './account-validated',
        context: {
          prenom: user.prenom,
          nom: user.nom,
          email: user.email,
          role_label: roleLabel,
        },
      });
      
      return true;
    } catch (error) {
      console.error('Error sending validation email:', error);
      return false;
    }
  }

  async sendAccountRejected(user: {
    email: string;
    prenom: string;
    nom: string;
    role: string;
    reason: string;
  }): Promise<boolean> {
    try {
      await this.mailerService.sendMail({
        to: user.email,
        subject: 'Votre demande d\'inscription P\'titsPas',
        template: './account-rejected',
        context: {
          prenom: user.prenom,
          nom: user.nom,
          reason: user.reason,
        },
      });
      
      return true;
    } catch (error) {
      console.error('Error sending rejection email:', error);
      return false;
    }
  }
}
```

### Templates Handlebars

**Fichier** : `backend/src/mail/templates/account-validated.hbs`

Voir le template HTML dans la section [Étape 6.1](#61-email-de-validation)

**Fichier** : `backend/src/mail/templates/account-rejected.hbs`

Voir le template HTML dans la section [Étape 6.2](#62-email-de-refus)

---

## ✅ Tests et validation

### Tests unitaires (Backend)

**Framework** : Jest

**Fichiers de test** :
- `backend/src/routes/auth/auth.service.spec.ts`
- `backend/src/routes/user/user.service.spec.ts`
- `backend/src/mail/mail.service.spec.ts`

**Scénarios de test** :

1. **Création de gestionnaire**
   - ✅ Création réussie avec données valides
   - ❌ Échec si email déjà existant
   - ❌ Échec si utilisateur non super_admin
   - ❌ Échec si données invalides

2. **Inscription**
   - ✅ Inscription parent réussie
   - ✅ Inscription AM réussie
   - ✅ Création de l'entité métier (parent/AM)
   - ❌ Échec si email déjà existant
   - ❌ Échec si mot de passe trop faible

3. **Validation de compte**
   - ✅ Validation réussie + changement statut
   - ✅ Email envoyé
   - ✅ Enregistrement dans table validations
   - ❌ Échec si utilisateur non gestionnaire
   - ❌ Échec si utilisateur déjà validé

4. **Refus de compte**
   - ✅ Refus réussi + changement statut
   - ✅ Email envoyé avec motif
   - ✅ Enregistrement dans table validations
   - ❌ Échec si commentaire manquant

5. **Connexion**
   - ✅ Connexion réussie si compte actif
   - ❌ Échec si compte en attente
   - ❌ Échec si compte suspendu
   - ❌ Échec si mot de passe incorrect

### Tests d'intégration (Backend)

**Framework** : Supertest + Jest

**Scénarios de test** :

1. **Workflow complet - Parent**
   ```typescript
   it('should complete full parent workflow', async () => {
     // 1. Super admin crée un gestionnaire
     const gestionnaire = await createGestionnaire();
     
     // 2. Parent s'inscrit
     const parent = await registerParent();
     
     // 3. Gestionnaire liste les parents en attente
     const pendingParents = await getPendingParents(gestionnaire.token);
     expect(pendingParents).toContainEqual(expect.objectContaining({
       email: parent.email,
       statut: 'en_attente'
     }));
     
     // 4. Gestionnaire valide le parent
     await validateUser(gestionnaire.token, parent.id);
     
     // 5. Parent se connecte
     const loginResponse = await loginUser(parent.email, parent.password);
     expect(loginResponse.access_token).toBeDefined();
   });
   ```

2. **Workflow complet - Assistante Maternelle**
   - Identique au workflow parent

3. **Workflow refus**
   ```typescript
   it('should handle account rejection', async () => {
     const gestionnaire = await createGestionnaire();
     const parent = await registerParent();
     
     await rejectUser(gestionnaire.token, parent.id, 'Informations incomplètes');
     
     const loginResponse = await loginUser(parent.email, parent.password);
     expect(loginResponse.statusCode).toBe(403);
   });
   ```

### Tests E2E (Frontend + Backend)

**Framework** : Flutter Integration Tests + Mockito

**Scénarios de test** :

1. **Création gestionnaire (UI)**
   - Remplir le formulaire
   - Soumettre
   - Vérifier le message de succès
   - Vérifier que le gestionnaire peut se connecter

2. **Inscription parent (UI)**
   - Remplir le formulaire d'inscription
   - Soumettre
   - Vérifier le message "en attente de validation"
   - Vérifier que la connexion est refusée

3. **Dashboard gestionnaire (UI)**
   - Se connecter en tant que gestionnaire
   - Vérifier l'affichage des 2 onglets
   - Vérifier l'affichage des comptes en attente
   - Cliquer sur "Valider"
   - Vérifier que le compte disparaît de la liste

4. **Réception email (Manuel)**
   - Vérifier la réception de l'email de validation
   - Vérifier le contenu de l'email
   - Cliquer sur le lien de connexion
   - Vérifier la redirection vers l'application

### Checklist de validation

**Phase 1 : Backend**
- [ ] Endpoint création gestionnaire fonctionne
- [ ] Flag `changement_mdp_obligatoire` = TRUE pour gestionnaires/admins
- [ ] Endpoint inscription parent fonctionne (6 étapes)
  - [ ] Création Parent 1
  - [ ] Création Parent 2 (optionnel)
  - [ ] Création Enfant(s)
  - [ ] Enregistrement présentation
  - [ ] Enregistrement acceptation CGU avec horodatage
  - [ ] Récapitulatif
- [ ] Endpoint inscription AM fonctionne (5 étapes)
  - [ ] Panneau 1 : Identité + Photo + Consentement photo
  - [ ] Panneau 2 : NIR + Agrément + Infos pro
  - [ ] Présentation
  - [ ] Acceptation CGU
  - [ ] Récapitulatif
- [ ] Entité métier créée lors de l'inscription
- [ ] Endpoint validation fonctionne
- [ ] Endpoint refus fonctionne
- [ ] Email de validation envoyé
- [ ] Email de refus envoyé
- [ ] SMS de validation envoyé (optionnel)
- [ ] SMS de refus envoyé (optionnel)
- [ ] Connexion bloquée si compte en attente
- [ ] Connexion autorisée si compte actif
- [ ] Changement de mot de passe forcé à la première connexion (gestionnaires/admins)

**Phase 2 : Frontend**
- [ ] Écran création gestionnaire implémenté
- [ ] Formulaire d'inscription parent implémenté (6 étapes)
  - [ ] Étape 1 : Informations Parent 1
  - [ ] Étape 2 : Informations Parent 2 (optionnel)
  - [ ] Étape 3 : Informations Enfant(s) avec upload photo
  - [ ] Étape 4 : Présentation du dossier
  - [ ] Étape 5 : Acceptation CGU (liens PDF)
  - [ ] Étape 6 : Récapitulatif
- [ ] Formulaire d'inscription AM implémenté (5 étapes)
  - [ ] Panneau 1 : Identité + Upload photo + Consentement
  - [ ] Panneau 2 : NIR + Date/lieu naissance + Agrément
  - [ ] Présentation
  - [ ] Acceptation CGU (liens PDF)
  - [ ] Récapitulatif
- [ ] Dashboard gestionnaire avec 2 onglets
- [ ] Liste des parents en attente affichée (avec enfants)
- [ ] Liste des AM en attente affichée (avec NIR masqué)
- [ ] Boutons Valider/Refuser fonctionnels
- [ ] Messages de feedback utilisateur
- [ ] Gestion des erreurs
- [ ] Écran de changement de mot de passe forcé (première connexion)

**Phase 3 : Intégration**
- [ ] Workflow complet parent testé
- [ ] Workflow complet AM testé
- [ ] Workflow refus testé
- [ ] Emails reçus et corrects
- [ ] Connexion après validation OK
- [ ] Redirection vers dashboard OK

---

## 📚 Références

### Documentation interne

- [API.md](./API.md) - Documentation complète des endpoints
- [DATABASE.md](./DATABASE.md) - Schéma de la base de données
- [AUDIT.md](./AUDIT.md) - Audit du projet YNOV
- [README-ARCHITECTURE.md](./README-ARCHITECTURE.md) - Architecture du projet
- [README-DEPLOYMENT.md](./README-DEPLOYMENT.md) - Guide de déploiement

### Documentation externe

- [NestJS Documentation](https://docs.nestjs.com/)
- [TypeORM Documentation](https://typeorm.io/)
- [Flutter Documentation](https://flutter.dev/docs)
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
- [Nodemailer Documentation](https://nodemailer.com/)

### Cahier des Charges

**Section 3.1** : Gestion des utilisateurs  
**Section 3.2** : Processus de validation  
**Section 4.5** : Notifications email

---

## 📋 Résumé des modifications (Conformité CDC)

Ce document a été mis à jour pour être conforme au **Cahier des Charges v1.3** (Section 3).

### Principales modifications

#### Inscription Parent
- ✅ Passage de 1 formulaire simple à **6 étapes complètes**
- ✅ Ajout de la gestion du **Parent 2** (co-parent)
- ✅ Ajout de la création des **enfants** lors de l'inscription
- ✅ Ajout du champ **Présentation du dossier**
- ✅ Ajout de l'**Acceptation des CGU** avec horodatage
- ✅ Ajout d'un **Récapitulatif** avant validation

#### Inscription Assistante Maternelle
- ✅ Passage de 1 formulaire simple à **5 étapes avec 2 panneaux**
- ✅ Ajout du **NIR** (Numéro de Sécurité sociale) - **OBLIGATOIRE**
- ✅ Ajout de la **Photo obligatoire** (si option activée)
- ✅ Ajout du **Consentement photo** avec horodatage (RGPD)
- ✅ Ajout de la **Date et lieu de naissance**
- ✅ Ajout de l'**Acceptation des CGU** avec horodatage
- ✅ Ajout d'un **Récapitulatif** avant validation

#### Création Gestionnaire/Administrateur
- ✅ Ajout du **Changement de mot de passe obligatoire** à la première connexion

#### Notifications
- ✅ Ajout de la possibilité d'envoi par **SMS** en plus de l'email

### Champs Base de Données à Ajouter

```sql
-- Table utilisateurs
ALTER TABLE utilisateurs ADD COLUMN ville_naissance VARCHAR(150);
ALTER TABLE utilisateurs ADD COLUMN pays_naissance VARCHAR(100);
ALTER TABLE utilisateurs ADD COLUMN date_acceptation_cgu TIMESTAMPTZ;

-- Table assistantes_maternelles
-- Le champ nir_chiffre existe déjà mais doit être rendu OBLIGATOIRE
ALTER TABLE assistantes_maternelles ALTER COLUMN nir_chiffre SET NOT NULL;

-- Table parents ou nouvelle table
-- Option 1 : Ajouter à la table parents
ALTER TABLE parents ADD COLUMN presentation_dossier TEXT;

-- Option 2 : Créer une table dédiée
CREATE TABLE dossiers_inscription (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  id_utilisateur UUID REFERENCES utilisateurs(id) ON DELETE CASCADE,
  presentation TEXT,
  cree_le TIMESTAMPTZ DEFAULT now()
);
```

---

**Dernière mise à jour** : 24 Novembre 2025  
**Version** : 1.0  
**Statut** : ✅ Document validé - Conforme CDC v1.3

