petitspas/docs/20_WORKFLOW-CREATION-COMPTE.md
Julien Martin a5dae7a017 docs: Workflow création de compte + refonte documentation
- 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
2025-11-25 00:28:35 +01:00

65 KiB

📋 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
  2. Acteurs
  3. Workflow détaillé
  4. Diagrammes de séquence
  5. Spécifications techniques
  6. APIs utilisées
  7. Modèles de données
  8. Templates d'emails
  9. 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

-- 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

// 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

// 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

{
  "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 et la Politique de confidentialité

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

// 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

// 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

{
  "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 et la Politique de confidentialité

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

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

Backend → Database

-- 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

[
  {
    "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

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

Backend → Database

-- 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

[
  {
    "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

// 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

-- 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

// 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

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

5.2 Flux technique - Refus

Frontend → Backend

// 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

-- 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

// 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

{
  "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 :

<!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) :

<!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 :

<!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 :

<!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

// 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

// 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

{
  "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

// 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

-- 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

{
  "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

{
  "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é

{
  "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

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

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

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é

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
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

Request :

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

Response 201 :

{
  "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

Request :

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

Response 201 :

{
  "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

Query Params :

?statut=en_attente

Response 200 :

[
  {
    "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

Query Params :

?statut=en_attente

Response 200 :

[
  {
    "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

Request :

{
  "comment": "Dossier complet, compte validé"
}

Response 200 :

{
  "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

Request :

{
  "comment": "Informations incomplètes"
}

Response 200 :

{
  "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

Request :

{
  "email": "parent@example.com",
  "password": "MotDePasse123"
}

Response 200 :

{
  "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

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 :

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

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

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

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 :

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

📧 Templates d'emails

Configuration Nodemailer

Installation :

npm install nodemailer
npm install -D @types/nodemailer

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

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

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

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

Voir le template HTML dans la section Étape 6.2


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

    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

    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

Documentation externe

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

-- 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