# Cahier des charges — Module de gestion des formations

**Projet** : HR Consulting & Co — backoffice Laravel (Filament)
**Périmètre** : sessions de formation, participants & présences, certificats, rapport de formation, envois par e-mail, rôles et sécurité.
**Version** : juin 2026 (Phases 11 & 12 + améliorations).

---

## 1. Objet et périmètre

Le module permet au cabinet d'organiser ses **sessions de formation**, d'en gérer les **participants** (saisie unitaire ou import Excel), de **pointer les présences** (globalement ou jour par jour), de **délivrer des certificats nominatifs** authentifiables publiquement (PDF + QR code), de **rédiger et envoyer un rapport de formation** à l'intermédiaire de l'entreprise cliente, et de suivre l'activité via des **indicateurs (KPI)** sur le tableau de bord.

Tout est administré depuis le backoffice `/admin` (Filament). Seule la **page publique de vérification des certificats** (`/certificats/verifier/{code}`) est exposée aux visiteurs.

---

## 2. Acteurs et rôles

| Rôle | Description | Capacités |
|---|---|---|
| **Super administrateur** | Administrateur disposant de privilèges étendus. | Tout le rôle admin + **réouvrir une session clôturée** + accorder/retirer le rôle super admin. |
| **Administrateur** | Gestionnaire complet du backoffice. | Accès à toutes les ressources et toutes les actions du module. |
| **Agent** | Profil d'accès **restreint**. | Voir §2.1. |

### 2.1 Périmètre du rôle « agent »

**Autorisé** : liste des CV reçus, sessions de formation (consultation, création, édition), ajout et **import de participants**, pointage des présences, téléchargement des certificats (PDF unitaire et ZIP), rédaction et téléchargement du rapport, messages de contact, abonnés newsletter, demandes de formation, témoignages.

**Interdit** (boutons masqués **et** refus serveur 403, même par URL directe) :
- envoyer un rapport de formation ;
- envoyer des certificats par e-mail (individuel ou en masse) ;
- supprimer des participants ou des sessions ;
- clôturer une session ;
- accéder aux autres ressources du backoffice : clients, formations (catalogue), hero slides, formateurs, actualités, services, statistiques visiteurs, comptes utilisateurs, paramètres du site.

**Règles de cumul** : le drapeau « administrateur » **prime** — un compte admin coché « agent » n'est jamais restreint. Un compte ni admin ni agent n'accède pas au backoffice.

---

## 3. Sessions de formation

### 3.1 Données d'une session

- **Titre de la formation** (obligatoire — tel qu'imprimé sur les certificats).
- **Formateur(s)** (obligatoire, multi-sélection) : choisis dans le référentiel des formateurs ; un nom absent peut être **créé à la volée** (le formateur naît *inactif* et reste invisible sur le site public tant que sa fiche n'est pas complétée).
- **Lieu de formation** : référentiel partagé des lieux, avec **création à la volée sans doublon** (casse ignorée). Le même référentiel alimente le rapport de formation.
- **Dates de début et de fin** (obligatoires, fin ≥ début).
- **Programme — journées de formation** : liste détaillée des journées (voir §3.2).
- **Intermédiaire** (voir §3.3).
- **Modèle de certificat** par défaut de la session : *Classique*, *Moderne* ou *Premium*.
- **E-mail de contact** (usage interne), **notes internes** (jamais imprimées).

La liste des sessions affiche : ID, formation, dates, formateurs, nombre de participants, modèle, statut (En cours / Clôturée), date d'ajout — triée par **date d'ajout décroissante**.

### 3.2 Programme par journées

Chaque session peut détailler son programme jour par jour. Une **journée** porte :
- une **date** (obligatoire, **unique** au sein de la session) ;
- une **heure de début** et une **heure de fin** (optionnelles, fin > début) ;
- le **module dispensé** ce jour-là (libellé libre).

Ces journées servent de référentiel au **pointage des présences par jour** (§4.3) et sont triées chronologiquement.

### 3.3 Intermédiaire de session

L'intermédiaire est l'interlocuteur de l'entreprise cliente qui a organisé la formation ; il est le **destinataire du rapport de formation**.

- **Prénom, nom, téléphone et e-mail obligatoires** (fonction optionnelle).
- Option « **L'intermédiaire participe à la formation** » : s'il est coché, l'intermédiaire est **ajouté automatiquement aux participants**, **sans doublon** (déduplication par e-mail au sein de la session, opération idempotente à chaque enregistrement). Décocher la case **ne retire pas** le participant déjà inscrit (retrait manuel).

### 3.4 Cycle de vie : clôture et réouverture

#### Objet de la clôture

La clôture marque la **fin administrative** d'une session de formation. Elle fige la session dans l'état où elle se trouve afin de garantir l'intégrité des données ayant servi à émettre les certificats et le rapport : plus aucune modification n'est possible, mais les opérations de **diffusion** (exports, envois) et d'**intégrité** (révocation de certificat) restent disponibles.

#### Déclenchement

- Action « **Clôturer** » sur la ligne de la session, soumise à une **confirmation explicite** rappelant les conséquences (« La session ne sera plus modifiable. Les exports, rapports et envois de certificats par e-mail resteront disponibles. Seul un super administrateur pourra la réouvrir. »).
- Réservée aux **administrateurs** : bouton masqué pour les agents et pour une session déjà clôturée, action inopérable côté serveur même via une requête forgée.
- La clôture est **tracée** : horodatage et auteur enregistrés. Le statut affiché passe de « En cours » à « **Clôturée** » ; un filtre Clôturées / En cours est disponible.
- Opération **idempotente** : clôturer une session déjà clôturée est sans effet.

#### Effets d'une session clôturée

**Interdit** (verrou interface **et** verrou serveur — défense en profondeur) :
- modification de la fiche session : formulaire entier en **lecture seule**, enregistrement refusé côté serveur ;
- ajout, édition, suppression et **import Excel** de participants ;
- **pointage des présences** (bascule rapide, présences par jour, actions de masse) ;
- **suppression de la session** : garde posée au niveau du modèle lui-même (elle vaut donc aussi pour les suppressions de masse) — il faut réouvrir la session avant de pouvoir la supprimer.

**Reste disponible** après clôture :
- téléchargement des certificats (PDF unitaire et ZIP) ;
- **envoi des certificats par e-mail** (individuel et en masse, règles RG-E inchangées) ;
- téléchargement et **envoi du rapport de formation** ;
- **révocation** de certificat (action d'intégrité, possible à tout moment).

#### Interaction avec le rapport de formation

La clôture vaut **fin administrative** de la formation : une session est considérée « terminée » (condition d'envoi du rapport, RG-R2) si sa date de fin est passée **ou** si elle a été clôturée (voir §3.5). Cas d'usage : une session d'une seule journée clôturée le soir même peut envoyer son rapport immédiatement, sans attendre minuit.

#### Réouverture

- Réservée au **super administrateur** exclusivement (bouton invisible — donc inexécutable — pour tout autre profil), avec confirmation.
- La session redevient intégralement modifiable ; l'horodatage et l'auteur de clôture sont effacés.
- Idempotente sur une session ouverte.

#### Suppression

**Supprimer** (session ouverte, admin uniquement) : supprime définitivement la session, ses participants et leurs certificats (avertissement explicite).

### 3.5 Notion de session « terminée »

Une session est considérée **finie** (condition d'envoi du rapport) si :
- sa **date de fin est passée** (jour de fin inclus jusqu'à minuit), **ou**
- elle a été **explicitement clôturée** (la clôture vaut fin administrative — une session d'un jour clôturée le soir même peut envoyer son rapport sans attendre minuit).

---

## 4. Participants et présences

### 4.1 Fiche participant

Prénom et nom **obligatoires** ; entreprise, fonction, téléphone optionnels ; **e-mail obligatoire** (il sert à l'envoi du certificat et figure dans les flux du rapport).

### 4.2 Import Excel

- Modèle de fichier téléchargeable (« Modèle d'import (Excel) ») avec les en-têtes attendus : Prénom, Nom, Entreprise, Fonction, Téléphone, E-mail.
- Formats acceptés : `.xlsx`, `.xls`, `.csv` — **2 Mo max, 500 lignes max**.
- Règles de ligne : prénom + nom obligatoires (sinon ligne ignorée et comptée), **e-mail valide obligatoire** (sinon ligne rejetée et comptée).
- Notification récapitulative : importés / lignes ignorées / e-mails invalides. Le fichier téléversé est stocké sur le disque privé puis **systématiquement supprimé** après traitement.

### 4.3 Présences

La présence d'un participant est un **tri-état** : *non renseignée* (état initial), *présent*, *absent*. Elle peut être pointée de trois façons :

1. **Bascule rapide « Présent »** (colonne de la liste) : présent = pointé sur **toutes** les journées déclarées ; absent = plus aucune journée.
2. **Action « Présences par jour »** (visible si la session déclare un programme par journées) : liste à cocher des journées (date, horaires, module) avec bouton **Tout sélectionner / Tout désélectionner** — on coche toutes les dates, quelques-unes, ou aucune. **Aucune journée cochée = participant entièrement absent.**
3. **Actions de masse** « Marquer présents » / « Marquer absents » sur une sélection de participants.

Quel que soit le mode, le **détail par jour et l'agrégat global restent synchronisés** : un participant est *présent* dès qu'il a au moins une journée de présence, *entièrement absent* s'il est pointé sur aucune. Une colonne « Jours » (ex. `2 / 3`) montre l'assiduité par participant.

Le pointage est **impossible sur une session clôturée**. Un filtre Présents / Absents ou non renseignés est disponible.

### 4.4 Suppression

La suppression d'un participant (admin uniquement, confirmation requise) supprime aussi **ses certificats**. Interdite sur session clôturée et pour les agents.

---

## 5. Certificats de formation

### 5.1 Caractéristiques

- PDF **A4 paysage haute résolution** (dompdf), 3 modèles visuels : *Classique*, *Moderne*, *Premium*. Le modèle par défaut est porté par la session et **figé à l'émission** de chaque certificat.
- Chaque certificat porte un **code unique infalsifiable** : préfixe `HR` + 20 caractères aléatoires (alphabet Crockford Base32, généré par CSPRNG, unicité garantie en base) — soit 22 caractères.
- Un **QR code** imprimé sur le certificat pointe vers la page publique de vérification du code.
- Signataire (nom, fonction, signature et cachet numérisés) et e-mail de contact imprimés : paramétrables dans le backoffice (Paramètres → Certificats).

### 5.2 Règles de génération

- **RG-C1** — La génération **réutilise toujours** le certificat valide existant du participant : le code et le QR restent **stables** d'une régénération à l'autre. Un nouveau certificat n'est créé que si le participant n'en a aucun de valide.
- **RG-C2** — **Aucun certificat ne peut être généré pour un participant entièrement absent** (pointé absent sur toute la formation) : refus côté serveur et boutons masqués. Un participant à la présence *non renseignée* reste éligible.
- **RG-C3** — L'export **ZIP** de la session génère les certificats manquants des participants éligibles et **ignore les entièrement absents**.
- **RG-C4** — Tout certificat déjà envoyé une première fois par e-mail porte la mention « **DUPLICATA** » sur les téléchargements et envois suivants (l'original n'est expédié qu'une fois).

### 5.3 Vérification publique

Page publique `/certificats/verifier` : saisie (tolérante — minuscules, tirets, espaces, confusions I/L/O) ou scan du QR code. La page confirme l'authenticité, affiche le titulaire, la formation, la période et les formateurs — ou signale un code **inconnu** ou un certificat **révoqué**.

### 5.4 Révocation

- Révocation possible à tout moment, **même session clôturée** (action d'intégrité), avec raison interne optionnelle.
- Le certificat n'est **jamais supprimé** : son code devient « révoqué » à la vérification publique. **Tous** les certificats encore valides du participant sont révoqués d'un coup.
- La révocation est **notifiée par e-mail** au participant et à l'intermédiaire (sans divulguer la raison interne) ; un échec d'e-mail n'annule jamais la révocation.
- Irréversible ; un nouveau certificat (nouveau code) peut être généré ensuite.

---

## 6. Envois par e-mail

Tous les envois sont synchrones avec accusé par notification (succès / avertissement / erreur). En développement, les e-mails sont capturés par Mailpit ; en production, via le SMTP configuré.

### 6.1 Certificat individuel

- Action « Envoyer par e-mail » sur la ligne du participant : modal de confirmation avec l'adresse **pré-remplie et modifiable** ; l'adresse saisie est enregistrée sur la fiche du participant si elle a changé.
- L'e-mail (sujet « Votre certificat de formation — {Formation} ») joint le **PDF du certificat** et rappelle la formation, la période, le code et le lien de vérification.

### 6.2 Envoi en masse

- Action « Envoyer les certificats par e-mail » (depuis la liste des sessions ou l'onglet participants), avec **ciblage** :
  - **Tous les participants (sauf absents)** : présents + présences non renseignées ;
  - **Uniquement les participants présents**.
- Envoi un par un ; les participants **sans adresse** sont ignorés et comptés ; chaque échec est compté sans interrompre la boucle. Notification récapitulative : envoyés / ignorés / échecs.

### 6.3 Règles communes aux envois de certificats

- **RG-E1** — Aucun envoi (individuel ou masse) tant qu'**aucun participant n'est pointé présent** dans la session.
- **RG-E2** — Aucun envoi à un participant **entièrement absent**, quel que soit le ciblage (exclu de la masse, bouton individuel masqué, refus serveur).
- **RG-E3** — Le **premier envoi** expédie l'exemplaire original puis fige l'horodatage ; tous les suivants portent la mention DUPLICATA.
- **RG-E4** — Les **agents** ne peuvent envoyer aucun certificat.
- **RG-E5** — Les envois restent possibles après clôture de la session.

### 6.4 Rapport de formation (voir aussi §7)

E-mail **HTML soigné** (charte navy/vert/gold) adressé à l'intermédiaire avec le **PDF complet du rapport en pièce jointe**.

### 6.5 Notification de révocation

E-mail au participant et à l'intermédiaire signalant que le certificat n'est plus valide (sans la raison interne).

---

## 7. Rapport de formation

### 7.1 Rédaction

Page dédiée par session (« Rapport ») composée de :
- un panneau **« Données de la session »** en lecture seule, jamais ressaisi : formation, période, formateurs, effectif, présents (+ taux), certificats délivrés ;
- des **sections rédactionnelles** : synthèse exécutive, contexte, objectifs pédagogiques, lieu (référentiel partagé, création à la volée), programme dispensé (modules + durées), écarts au programme, méthodes & moyens, logistique & supports, assiduité, évaluation des acquis, évaluation à chaud (critères notés sur 5 + moyenne calculée), verbatims, points forts, difficultés, recommandations & plan d'action, conclusion.

À la première ouverture, chaque bloc est **pré-rempli avec un modèle de texte** construit à partir des données de la session (titre, période, formateurs, lieu) ; les passages à personnaliser sont signalés par des crochets `[...]`. Le rédacteur modifie librement.

### 7.2 PDF

Document **A4 portrait** multi-pages (dompdf) à la charte graphique du cabinet : page de garde (logo, formation, période, lieu, formateurs, référence de session `SESS-AAAA-NNNN`, destinataire, date d'émission), en-tête et pied de page répétés avec pagination, sections numérotées, cartes statistiques, tableaux (programme, satisfaction), bloc signature (signataire paramétré), **annexe nominative** des participants (présence + certificat délivré). Marges garanties, aucun débordement.

Le PDF est **téléchargeable à tout moment** (aperçu avant envoi, archivage après envoi, même session clôturée).

### 7.3 Règles d'envoi du rapport

L'action « Envoyer à l'intermédiaire » est soumise à **cinq garde-fous**, contrôlés côté serveur :

- **RG-R1** — **Envoi unique, à vie** : un rapport déjà envoyé ne peut jamais être renvoyé. Après l'envoi, le rapport est **figé** (lecture seule, réécriture refusée côté serveur) afin que le PDF téléchargeable reste strictement identique à l'exemplaire envoyé. Statut, horodatage et destinataire sont journalisés et ne peuvent pas être falsifiés depuis le formulaire.
- **RG-R2** — La session doit être **terminée ou clôturée** (§3.5).
- **RG-R3** — **Au moins un participant pointé présent** dans la session.
- **RG-R4** — L'**e-mail de l'intermédiaire** doit être renseigné.
- **RG-R5** — Le rapport ne doit pas être **vide** (au moins une section renseignée).

Tout garde-fou non satisfait affiche une notification explicite et annule l'envoi. Un échec SMTP est signalé et **ne marque pas** le rapport comme envoyé. Les **agents** peuvent rédiger et télécharger le rapport mais **jamais l'envoyer** (RG-E4 étendue).

---

## 8. Tableau de bord (KPI)

Cartes affichées en tête du dashboard :

| KPI | Détail |
|---|---|
| Sessions actives | + nombre de sessions à venir |
| Participants présents | + taux de présence global (présences pointées uniquement) |
| Certificats valides | + nombre envoyés par e-mail |
| **Certificats révoqués** | en rouge dès qu'il y en a |
| Clients actifs | + formateurs actifs |
| CV soumis | + non lus (alerte rouge) |

Les blocs « compte / déconnexion » et « documentation Filament » sont retirés du tableau de bord.

---

## 9. Comptes et sécurité

### 9.1 Accès au backoffice

Réservé aux comptes **administrateurs** ou **agents** (vérification à la connexion — OWASP A01). Gestion des comptes (ressource Utilisateurs) réservée aux administrateurs.

### 9.2 Politique de mot de passe (standard minimum)

**10 caractères minimum, avec majuscules, minuscules, chiffre et caractère spécial** — appliquée à la création et à l'édition des comptes ainsi qu'au profil.

### 9.3 Profil utilisateur

Tout utilisateur connecté peut modifier **son nom, son e-mail et son mot de passe** depuis le menu utilisateur. Le changement de mot de passe exige :
1. le **mot de passe actuel** (vérifié contre le hash en base) ;
2. un **nouveau mot de passe** conforme à la politique ;
3. une **confirmation strictement identique**.

Champs vides = mot de passe inchangé. Les mots de passe sont **hachés** (jamais stockés ni journalisés en clair).

### 9.4 Garde-fous d'administration

- Un administrateur ne peut ni **se retirer lui-même** le rôle admin, ni **supprimer son propre compte** (anti-verrouillage).
- Le rôle **super admin** n'est modifiable que par un super admin, jamais sur sa propre fiche.
- **Pas de suppression de masse** des utilisateurs.
- Toutes les restrictions d'interface (boutons masqués) sont **doublées côté serveur** (défense en profondeur contre les requêtes forgées).

---

## 10. Contraintes techniques

- **Stack** : Laravel 12 (PHP 8.2+), MySQL 8, Filament v3 (backoffice), Livewire 3, dompdf (PDF), chillerlan/php-qrcode (QR), Maatwebsite Excel (imports/exports).
- **E-mails** : SMTP paramétré en `.env` (Mailpit en développement) ; destinataires de notification paramétrables en backoffice.
- **Intégrité** : suppressions en cascade contrôlées (session → participants → certificats ; journées → présences), contraintes d'unicité en base (journée par session, présence par participant et par jour, code de certificat).
- **Qualité** : l'ensemble des règles ci-dessus est couvert par la suite de tests automatisés (315 tests) exécutée sur MySQL.
