- Ajout Cahier des Charges v1.3 - Ajout Workflow technique création de compte (v1.0) - Réorganisation docs avec préfixes numériques (00_, 01_, etc.) - Ajout données de test CSV - Modifications principales : * Champ téléphone unique (suppression mobile/fixe) * Inscription sans mot de passe (Parents + AM) * Création MDP par email après validation (7j) * Genre enfant obligatoire (H/F) * Date agrément obligatoire pour AM
2289 lines
65 KiB
Markdown
2289 lines
65 KiB
Markdown
# 📋 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
|
|
|