diff --git a/database/migration/1.0.5.sql b/database/migration/1.0.5.sql
new file mode 100644
index 0000000000000000000000000000000000000000..52bc52a47bdeb77af9472114e55af0c8f6362feb
--- /dev/null
+++ b/database/migration/1.0.5.sql
@@ -0,0 +1,16 @@
+-- Nouveaux Templates ---------------------------------------------------------
+INSERT INTO unicaen_renderer_template (code, description, document_type, document_sujet, document_corps, document_css, namespace) VALUES ('FORMATION_SESSION_RAPPEL_DEMANDE_VALIDATION', '<p>Courrier de rappel de la demande de validation d''une inscription à une formation du plan de formation</p>', 'mail', 'RAPPEL Vous n''avez pas encore validé la demande de formation de VAR[AGENT#Denomination]', e'<p>Bonjour,</p>
+<p>Vous n\'avez pas encore validé la demande de formation de VAR[AGENT#Denomination] pour la session VAR[SESSION#libelle] du  VAR[SESSION#periode].<br>Veuillez vous rendre dans votre tableau de bord en tant que Valideur·euse sur l\'application VAR[Macro#AppName] (VAR[Url#AppLink]) afin de statuer sur cette demande.</p>
+<p>Bonne journée,<br>L\'application VAR[Macro#AppName]</p>', null, 'Formation\Provider\Template');
+INSERT INTO unicaen_renderer_template (code, description, document_type, document_sujet, document_corps, document_css, namespace) VALUES ('FORMATION_EMARGEMENT', '<p>Feuille d''émargement</p>', 'pdf', 'Emargement_Session_VAR[SESSION#id].pdf', e'<h2 style="text-align: center;">Feuille d\'émargement</h2>
+<p><strong>Atelier</strong><br>Libellé : VAR[SESSION#libelle]<br>Période : VAR[SESSION#periode]</p>
+<p><br><strong>Formateur·trices<br></strong>VAR[SESSION#FormateursAvecSignature]</p>
+<p><strong>Séance</strong><br>Lieu : VAR[SEANCE#lieu]<br>Date : VAR[SEANCE#periode]</p>
+<p><br><strong>Liste des inscrit·es<br></strong>VAR[SESSION#InscritsAvecSignature]</p>', 'table.bordered { border-collapse: collapse; } table.bordered  td { border: 1px solid black; } table.bordered  th { border: 1px solid black; }', 'Formation\Provider\Template');
+
+-- Nouvelles Macros -----------------------------------------------------------
+INSERT INTO unicaen_renderer_macro (code, description, variable_name, methode_name) VALUES ('SESSION#InscritsAvecSignature', '<p>Retourne un tableau des inscrits de la liste principale avec une case pour leur signature</p>', 'session', 'getArrayListePrincipales');
+INSERT INTO unicaen_renderer_macro (code, description, variable_name, methode_name) VALUES ('SESSION#FormateursAvecSignature', '<p>Fournit un tableau listant les formateurs avec un case pour la signature</p>', 'session', 'getArrayFormateurs');
+INSERT INTO unicaen_renderer_macro (code, description, variable_name, methode_name) VALUES ('SEANCE#periode', '<p>Retourne la période au format DD/MM/YYYY H:m au DD/MM/YYYY H:m</p>', 'seance', 'getPeriode');
+INSERT INTO unicaen_renderer_macro (code, description, variable_name, methode_name) VALUES ('SEANCE#lieu', '<p>Retourne le lieu de la séance "Batiment Salle - Campus Ville"</p>', 'seance', 'toStringLieu');
+
diff --git a/module/Agent/src/Entity/Db/Agent.php b/module/Agent/src/Entity/Db/Agent.php
index 407dd1f68e07c68265c6a176e0341a13d1384e2b..750fd3181dd41b7096b4475713795a99874ddaa6 100644
--- a/module/Agent/src/Entity/Db/Agent.php
+++ b/module/Agent/src/Entity/Db/Agent.php
@@ -204,6 +204,17 @@ class Agent implements
         return null;
     }
 
+    public function getStructure(): string
+    {
+        $affectation = $this->getAffectationPrincipale();
+        if ($affectation === null) return 'Aucune structure connue';
+
+        $structure = $affectation->getStructure();
+        $niveau2 = $structure->getNiv2();
+        if ($structure === $niveau2) { return $structure->getLibelleLong(); }
+        return $niveau2->getLibelleLong() . " > ". $structure->getLibelleLong();
+    }
+
     /** @return AgentEchelon[] */
     public function getEchelons(?DateTime $date = null, bool $histo = false): array
     {
diff --git a/module/Application/view/application/document/pdf/entete-logo-ccc.phtml b/module/Application/view/application/document/pdf/entete-logo-ccc.phtml
index 2fd7deef97c1730438bcd50d627e882fc8e79380..f1d18a186c7931346a79824d5e4341f75e5b41df 100644
--- a/module/Application/view/application/document/pdf/entete-logo-ccc.phtml
+++ b/module/Application/view/application/document/pdf/entete-logo-ccc.phtml
@@ -11,7 +11,7 @@
     <tr>
         <td>
             <img style='height:3cm;' src='data:image/png;base64,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' />
-            <img style='height:3cm;' src='<?php echo $image; ?>' />
+            <img style='height:3cm;' src='<?php echo $image; ?>' alt="logo de l'établissement"/>
         </td>
         <td>
             <div style="display: inline-block; margin-right: 0;">
diff --git a/module/Application/view/application/index/index-gestionnaire.phtml b/module/Application/view/application/index/index-gestionnaire.phtml
index 19761668851356b05acc702ecb1a57a3a63795a6..f46f1f5db461f860c1334f6723ceaa93f8b124d3 100644
--- a/module/Application/view/application/index/index-gestionnaire.phtml
+++ b/module/Application/view/application/index/index-gestionnaire.phtml
@@ -68,7 +68,7 @@ foreach ($dictionnaireDemande as $etatCode => $demandes) {
             </div>
             <?php if (count($sessions) > 0) : ?>
                 <div class="card-body">
-                    <?php echo $this->formationInstanceArray($sessions, ['affichage' => ['gestionnaires' => false]]); ?>
+                    <?php echo $this->formationInstanceArray($sessions, ['id' => $etatCode, 'affichage' => ['gestionnaires' => false]]); ?>
                 </div>
             <?php endif; ?>
         </div>
diff --git a/module/Application/view/default/reponse.phtml b/module/Application/view/default/reponse.phtml
index 5595d8ccb1d5607455755b8eeae89fc2651da5b1..d7a77131190074bfef6fe113ebbebb17dfeeffdf 100644
--- a/module/Application/view/default/reponse.phtml
+++ b/module/Application/view/default/reponse.phtml
@@ -2,6 +2,8 @@
 
 /**
  * @var string $reponse
+ * @var string $success
+ * @var string $probleme
  */
 
 ?>
@@ -10,8 +12,15 @@
     <?php echo $reponse; ?>
 <?php endif; ?>
 
+<?php if (isset($success)) : ?>
+    <div class="alert alert-success text-success">
+        <span class="icon icon-checked"></span>
+        <?php echo $success; ?>
+    </div>
+<?php endif; ?>
+
 <?php if (isset($error)) : ?>
-    <div class="alert alert-error text-danger">
+    <div class="alert alert-danger text-danger">
         <span class="icon icon-unchecked"></span>
         <?php echo $error; ?>
     </div>
diff --git a/module/DemandeExterne/view/demande-externe/demande-externe/afficher.phtml b/module/DemandeExterne/view/demande-externe/demande-externe/afficher.phtml
index 1e87d94fc91dc7364bd21d48493235897b971dce..415a624611899e202c17a8c445db1599a5cd9139 100644
--- a/module/DemandeExterne/view/demande-externe/demande-externe/afficher.phtml
+++ b/module/DemandeExterne/view/demande-externe/demande-externe/afficher.phtml
@@ -266,5 +266,9 @@ $canGererGestionnaires = $canModifierSession;
             window.location.reload();
         });
     });
+
+    $(document).on('hide.bs.modal', '.modal', function () {
+        window.parent.location.reload();
+    });
 </script>
 
diff --git a/module/Formation/config/merged/formation-instance-document.config.php b/module/Formation/config/merged/formation-instance-document.config.php
index 57cb7aaf349918b1c33dc19b03a74c3eb77f8a83..81813b3113cd97a0126bc352f8823f1f833ac296 100644
--- a/module/Formation/config/merged/formation-instance-document.config.php
+++ b/module/Formation/config/merged/formation-instance-document.config.php
@@ -52,8 +52,7 @@ return [
                 [
                     'controller' => FormationInstanceDocumentController::class,
                     'action' => [
-                        'export-emargement',
-                        'export-tous-emargements',
+                        'generer-emargement',
                     ],
                     'privileges' => [
                         FormationinstancedocumentPrivileges::FORMATIONINSTANCEDOCUMENT_EMARGEMENT
@@ -116,25 +115,14 @@ return [
                             ],
                         ],
                     ],
-                    'export-emargement' => [
+                    'generer-emargement' => [
                         'type' => Segment::class,
                         'options' => [
-                            'route' => '/export-emargement/:journee',
+                            'route' => '/generer-emargement/:session[/:seance]',
                             'defaults' => [
-                                /** @see FormationInstanceDocumentController::exportEmargementAction() */
+                                /** @see FormationInstanceDocumentController::genererEmargementAction() */
                                 'controller' => FormationInstanceDocumentController::class,
-                                'action' => 'export-emargement',
-                            ],
-                        ],
-                    ],
-                    'export-tous-emargements' => [
-                        'type' => Segment::class,
-                        'options' => [
-                            'route' => '/export-tous-emargements/:session',
-                            'defaults' => [
-                                /** @see FormationInstanceDocumentController::exportTousEmargementsAction() */
-                                'controller' => FormationInstanceDocumentController::class,
-                                'action' => 'export-tous-emargements',
+                                'action' => 'generer-emargement',
                             ],
                         ],
                     ],
diff --git a/module/Formation/config/merged/session.config.php b/module/Formation/config/merged/session.config.php
index 3f597a60fd86d805e5a5302da6f892dc3677a68e..ad0e7c2dce2900dd656ec308b5d4f51edf90c29a 100644
--- a/module/Formation/config/merged/session.config.php
+++ b/module/Formation/config/merged/session.config.php
@@ -13,6 +13,10 @@ use Formation\Form\Annulation\AnnulationForm;
 use Formation\Form\Annulation\AnnulationFormFactory;
 use Formation\Form\Annulation\AnnulationHydrator;
 use Formation\Form\Annulation\AnnulationHydratorFactory;
+use Formation\Form\Notification\NotificationForm;
+use Formation\Form\Notification\NotificationFormFactory;
+use Formation\Form\Notification\NotificationHydrator;
+use Formation\Form\Notification\NotificationHydratorFactory;
 use Formation\Form\Session\SessionForm;
 use Formation\Form\Session\SessionFormFactory;
 use Formation\Form\Session\SessionHydrator;
@@ -110,6 +114,9 @@ return [
                         'demander-retour',
                         'cloturer',
                         'changer-etat',
+
+                        'notifier-responsable-pour-validation',
+                        'notifier-inscrit',
                     ],
                     'privileges' => [
                         FormationinstancePrivileges::FORMATIONINSTANCE_GERER_INSCRIPTION,
@@ -383,6 +390,27 @@ return [
                             ],
                         ],
                     ],
+                    /** notification **********************************************************/
+                    'notifier-responsable-pour-validation' => [
+                        'type' => Segment::class,
+                        'options' => [
+                            'route' => '/notifier-responsable-pour-validation/:session',
+                            'defaults' => [
+                                /** @see SessionController::notifierResponsablePourValidationAction() */
+                                'action' => 'notifier-responsable-pour-validation',
+                            ],
+                        ],
+                    ],
+                    'notifier-inscrit' => [
+                        'type' => Segment::class,
+                        'options' => [
+                            'route' => '/notifier-inscrit/:session',
+                            'defaults' => [
+                                /** @see SessionController::notifierInscritAction() */
+                                'action' => 'notifier-inscrit',
+                            ],
+                        ],
+                    ],
                     /** gestion des formateurs ************************************************/
                     'ajouter-formateur' => [
                         'type' => Segment::class,
@@ -485,12 +513,14 @@ return [
         'factories' => [
             AnnulationForm::class => AnnulationFormFactory::class,
             SessionForm::class => SessionFormFactory::class,
+            NotificationForm::class => NotificationFormFactory::class,
         ],
     ],
     'hydrators' => [
         'factories' => [
             AnnulationHydrator::class => AnnulationHydratorFactory::class,
             SessionHydrator::class => SessionHydratorFactory::class,
+            NotificationHydrator::class => NotificationHydratorFactory::class,
         ],
     ],
     'view_helpers' => [
diff --git a/module/Formation/src/Formation/Controller/FormationInstanceDocumentController.php b/module/Formation/src/Formation/Controller/FormationInstanceDocumentController.php
index 6848e465fb1bb483af9a44630108e8959c1d7b26..218e494b1130ce38a07201079092298d793ecbc7 100644
--- a/module/Formation/src/Formation/Controller/FormationInstanceDocumentController.php
+++ b/module/Formation/src/Formation/Controller/FormationInstanceDocumentController.php
@@ -49,6 +49,49 @@ class FormationInstanceDocumentController extends AbstractActionController
         $this->etablissementInfos[$clef] = $valeur;
     }
 
+    /**
+     * @throws MpdfException
+     */
+    public function genererEmargementAction(): ?string
+    {
+        $session = $this->getSessionService()->getRequestedSession($this);
+        $seance = $this->getSeanceService()->getRequestedSeance($this, 'seance');
+
+        if ($seance !== null) {
+            $seances = [$seance];
+            $title = "Emargement_Session_" . $session->getId() . "_" . $seance->getId();
+        } else {
+            $seances = $session->getSeances();
+            $seances = array_filter($seances, function (Seance $seance) {
+                return $seance->estNonHistorise();
+            });
+            $title = "Emargement_Session_" . $session->getId();
+        }
+
+
+        $rendus = [];
+        foreach ($seances as $seance) {
+            $vars = [
+                'session' => $session,
+                'seance' => $seance,
+                'MacroService' => $this->getMacroService(),
+                'UrlService' => $this->getUrlService(),
+            ];
+            $rendus[$seance->getId()] = $this->getRenduService()->generateRenduByTemplateCode(PdfTemplates::FORMATION_EMARGEMENT, $vars, false);
+        }
+
+        $exporter = new PdfExporter();
+        $exporter->setRenderer($this->renderer);
+        $exporter->getMpdf()->SetTitle($title);
+        $exporter->setHeaderScript('/application/document/pdf/entete-logo-ccc', null, $this->etablissementInfos);
+        $exporter->setFooterScript('/application/document/pdf/pied-vide');
+        $exporter->getMpdf()->SetMargins(0, 0, 50);
+        foreach ($seances as $seance) {
+            $exporter->addBodyHtml($rendus[$seance->getId()]->getCorps());
+        }
+        return $exporter->export($title);
+    }
+
     public function exportEmargementAction(): void
     {
         $journee = $this->getSeanceService()->getRequestedSeance($this);
@@ -76,21 +119,6 @@ class FormationInstanceDocumentController extends AbstractActionController
         exit;
     }
 
-    #[NoReturn] public function exportTousEmargementsAction(): void
-    {
-        $instance = $this->getSessionService()->getRequestedSession($this);
-        $journees = $instance->getSeances();
-        $journees = array_filter($journees, function (Seance $a) {
-            return $a->estNonHistorise();
-        });
-
-        $exporter = new EmargementPdfExporter($this->renderer, 'A4');
-        $exporter->setVars([]);
-        $filemane = "formation_" . $instance->getFormation()->getId() . "_du_" . str_replace("/", "-", $instance->getDebut()) . "_au_" . str_replace("/", "-", $instance->getFin()) . "_emargements.pdf";
-        $exporter->exportAll($journees, $filemane);
-        exit;
-    }
-
     /**
      * @throws MpdfException
      */
diff --git a/module/Formation/src/Formation/Controller/InscriptionController.php b/module/Formation/src/Formation/Controller/InscriptionController.php
index 8b028e96ee7b97cc837fc0930028d867ed100748..484f1615f4951772c10e0ce461b7b377a9f75897 100644
--- a/module/Formation/src/Formation/Controller/InscriptionController.php
+++ b/module/Formation/src/Formation/Controller/InscriptionController.php
@@ -618,7 +618,7 @@ class InscriptionController extends AbstractActionController
             $form->setData($data);
             if ($form->isValid()) {
                 $plafond = $this->getParametreService()->getValeurForParametre(FormationParametres::TYPE, FormationParametres::INSCRIPTION_PLAFOND_ANNUEL);
-                $volumeAnnuel = $this->getInscriptionService()->getVolumeAnnuelByAgent($agent, $session->getDebut(true)->format("Y")) + $session->getDuree(true);
+                $volumeAnnuel = $this->getInscriptionService()->getVolumeAnnuelByAgent($agent, ($session->getDebut(true))?$session->getDebut(true)->format("Y"):0) + $session->getDuree(true);
 
                 $justification = (isset($data['justification']) && trim($data['justification']) !== '') ? trim($data['justification']) : null;
                 if ($justification === null) {
diff --git a/module/Formation/src/Formation/Controller/SessionController.php b/module/Formation/src/Formation/Controller/SessionController.php
index 9e77bef103287e4221f4d4b8bb11d214531895d5..27d1266deac73a82adc21c2d4d9f0e9cbfc09591 100644
--- a/module/Formation/src/Formation/Controller/SessionController.php
+++ b/module/Formation/src/Formation/Controller/SessionController.php
@@ -5,9 +5,11 @@ namespace Formation\Controller;
 use DateTime;
 use Formation\Entity\Db\Inscription;
 use Formation\Form\Annulation\AnnulationFormAwareTrait;
+use Formation\Form\Notification\NotificationFormAwareTrait;
 use Formation\Form\SelectionFormateur\SelectionFormateurFormAwareTrait;
 use Formation\Form\SelectionGestionnaire\SelectionGestionnaireFormAwareTrait;
 use Formation\Form\Session\SessionFormAwareTrait;
+use Formation\Provider\Etat\InscriptionEtats;
 use Formation\Provider\Etat\SessionEtats;
 use Formation\Provider\Parametre\AutreParametres;
 use Formation\Provider\Role\FormationRoles;
@@ -28,6 +30,7 @@ use UnicaenApp\View\Model\CsvModel;
 use UnicaenEnquete\Service\Enquete\EnqueteServiceAwareTrait;
 use UnicaenEnquete\Service\Resultat\ResultatServiceAwareTrait;
 use UnicaenEtat\Service\EtatCategorie\EtatCategorieServiceAwareTrait;
+use UnicaenEtat\Service\EtatInstance\EtatInstanceServiceAwareTrait;
 use UnicaenEtat\Service\EtatType\EtatTypeServiceAwareTrait;
 use UnicaenMail\Service\Mail\MailServiceAwareTrait;
 use UnicaenParametre\Service\Parametre\ParametreServiceAwareTrait;
@@ -38,6 +41,7 @@ class SessionController extends AbstractActionController
 {
     use EnqueteServiceAwareTrait;
     use EtatCategorieServiceAwareTrait;
+    use EtatInstanceServiceAwareTrait;
     use EtatTypeServiceAwareTrait;
     use FormateurServiceAwareTrait;
     use FormationServiceAwareTrait;
@@ -52,6 +56,7 @@ class SessionController extends AbstractActionController
     use UserServiceAwareTrait;
 
     use AnnulationFormAwareTrait;
+    use NotificationFormAwareTrait;
     use SelectionFormateurFormAwareTrait;
     use SelectionGestionnaireFormAwareTrait;
     use SessionFormAwareTrait;
@@ -300,43 +305,163 @@ class SessionController extends AbstractActionController
     }
 
     /** WORKFLOW  *****************************************************************************************************/
-    public function ouvrirInscriptionAction(): Response
+
+    public function ouvrirInscriptionAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
-        $this->getSessionService()->ouvrirInscription($session);
+        $mails = $this->getSessionService()->ouvrirInscription($session);
 
-        return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+        }
+        if (!empty($success)) {
+            $successTexte = "Les abonné·es ont été notifié·es de l'ouverture des inscriptions de cette session (".count($success)." courrier·s envoyé·s)";
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "Les abonné·es suivant·es n'ont pas pu être prévenu·es : <ul>";
+            foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+            $problemeTexte .= "</ul>";
+        }
+
+        $vm = new ViewModel([
+            'title' => "Ouverture des inscriptions",
+            'reponse' => "Opération effectuée",
+            'success' => $successTexte??null,
+            'error' => $problemeTexte??null,
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
     }
 
-    public function fermerInscriptionAction(): Response
+    public function fermerInscriptionAction(): ViewModel
     {
         $instance = $this->getSessionService()->getRequestedSession($this);
-        $this->getSessionService()->fermerInscription($instance);
+        $mails = $this->getSessionService()->fermerInscription($instance);
 
+        $probleme = []; $success = [];
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+        }
+        if (!empty($success)) {
+            $successTexte = "Les inscrit·es des listes principales et complémentaires ont été notifié·es (".count($success)." courrier·s envoyé·s). ";
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "Les inscrit·es suivant·es n'ont pas pu être prévenu·es : <ul>";
+            foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+            $problemeTexte .= "</ul>";
+        }
 
-        return $this->redirect()->toRoute('session/afficher', ['session' => $instance->getId()], [], true);
+        $vm = new ViewModel([
+            'title' => "Fermeture des inscriptions",
+            'reponse' => "Opération effectuée",
+            'success' => $successTexte??null,
+            'error' => $problemeTexte??null,
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
     }
 
-    public function envoyerConvocationAction(): Response
+    public function envoyerConvocationAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
-        $this->getSessionService()->envoyerConvocation($session);
-        $this->getSessionService()->envoyerEmargement($session);
-        return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
+        $mails = $this->getSessionService()->envoyerConvocation($session);
+
+        $probleme = []; $success = [];
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+        }
+
+        if (!empty($success)) {
+            $successTexte = "Les convocations ont été envoyées aux inscrit·es de la liste principale (".count($success)." courrier·s envoyé·s). ";
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "Les stagiaire·s suivant·es n'ont pas pu être convoqué·es : <ul>";
+            foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+            $problemeTexte .= "</ul>";
+        }
+
+        $mails = $this->getSessionService()->envoyerEmargement($session);
+        $probleme = []; $success = [];
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "<p>".$problemeTexte."</p>";
+            $problemeTexte .= "<p>La notification vers les formateur·trices a échouée.</p>";
+        }
+
+        $vm = new ViewModel([
+            'title' => "Envoi des convocations",
+            'reponse' => "Opération effectuée",
+            'success' => $successTexte??null,
+            'error' => $problemeTexte??null,
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
     }
 
-    public function demanderRetourAction(): Response
+    public function demanderRetourAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
-        $this->getSessionService()->demanderRetour($session);
-        return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
+        $mails = $this->getSessionService()->demanderRetour($session);
+
+        $success = []; $probleme = [];
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) {
+                $probleme[] = $individu;
+            } else {
+                $success[] = $individu;
+            }
+        }
+        if (!empty($success)) {
+            $successTexte = "Les stagiaire·s ont être prévenu·es par courrier électronique  (".count($success)." courrier·s envoyé·s). <ul>";
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "Les stagiaire·s suivant·es n'ont pas pu être prévenu·es : <ul>";
+            foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+            $problemeTexte .= "</ul>";
+        }
+
+        $vm = new ViewModel([
+            'title' => "Demande de retour",
+            'reponse' => "La demande a bien été effectuée",
+            'success' => $successTexte??null,
+            'error' => $problemeTexte??null,
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
     }
 
-    public function cloturerAction(): Response
+    public function cloturerAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
-        $this->getSessionService()->cloturer($session);
-        return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
+        $mails = $this->getSessionService()->cloturer($session);
+
+        $success = []; $probleme = [];
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) {
+                $probleme[] = $individu;
+            } else {
+                $success[] = $individu;
+            }
+        }
+        if (!empty($success)) {
+            $successTexte = "Les inscrits de la liste complémentaire ont été abonné·es (".count($success)." courrier·s envoyé·s).";
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "Les inscrit·es suivant·es n'ont pas pu être prévenu·es : <ul>";
+            foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+            $problemeTexte .= "</ul>";
+        }
+
+        $vm = new ViewModel([
+            'title' => "Clôture de la session",
+            'reponse' => "La clôture de la session et l'abonnement des inscrit·es de la liste complémentaire",
+            'success' => $successTexte??null,
+            'error' => $problemeTexte??null,
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
     }
 
     public function annulerAction(): ViewModel
@@ -352,8 +477,29 @@ class SessionController extends AbstractActionController
             $data = $request->getPost();
             $form->setData($data);
             if ($form->isValid()) {
-                $this->getSessionService()->annuler($session);
-                exit();
+                $mails = $this->getSessionService()->annuler($session);
+
+                $success = []; $probleme = [];
+                foreach ($mails as $individu => $mail) {
+                    if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+                }
+                if (!empty($success)) {
+                    $successTexte = "Les inscrit·es de la liste principale ont été prévenu·es (".count($success)." courrier·s envoyé·s).";
+                }
+                if (!empty($probleme)) {
+                    $problemeTexte = "Les inscrit·es suivant·es n'ont pas pu être prévenu·es : <ul>";
+                    foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+                    $problemeTexte .= "</ul>";
+                }
+
+                $vm = new ViewModel([
+                    'title' => "Annulation de la session",
+                    'reponse' => "La session est maintenant annulée. <br>Raison:".$session->getMotifAnnulation(),
+                    'success' => $successTexte??null,
+                    'error' => $problemeTexte??null,
+                ]);
+                $vm->setTemplate('default/reponse');
+                return $vm;
             }
         }
 
@@ -365,11 +511,17 @@ class SessionController extends AbstractActionController
         return $vm;
     }
 
-    public function reouvrirAction(): Response
+    public function reouvrirAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
         $this->getSessionService()->reouvrir($session);
-        return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
+
+        $vm = new ViewModel([
+            'title' => "Ré-ouverture de la session",
+            'reponse' => "La session est de nouveau ouverte et peut-être à nouveau modifiée.",
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
     }
 
     public function changerEtatAction(): ViewModel
@@ -381,31 +533,34 @@ class SessionController extends AbstractActionController
             $data = $request->getPost();
             $etat = $this->getEtatTypeService()->getEtatType($data['etat']);
 
-            switch ($etat->getCode()) {
-                case SessionEtats::ETAT_CREATION_EN_COURS :
-                    $this->getSessionService()->recreation($session);
-                    exit();
-                case SessionEtats::ETAT_INSCRIPTION_OUVERTE :
-                    $this->getSessionService()->ouvrirInscription($session);
-                    exit();
-                case SessionEtats::ETAT_INSCRIPTION_FERMEE :
-                    $this->getSessionService()->fermerInscription($session);
-                    exit();
-                case SessionEtats::ETAT_FORMATION_CONVOCATION :
-                    $this->getSessionService()->envoyerConvocation($session);
-                    $this->getSessionService()->envoyerEmargement($session);
-                    exit();
-                case SessionEtats::ETAT_ATTENTE_RETOURS :
-                    $this->getSessionService()->demanderRetour($session);
-                    exit();
-                case SessionEtats::ETAT_CLOTURE_INSTANCE :
-                    $this->getSessionService()->cloturer($session);
-                    exit();
-                case SessionEtats::ETAT_SESSION_ANNULEE :
-                    $this->getSessionService()->annuler($session);
-                    exit();
-                default :
-            }
+            $this->getEtatInstanceService()->setEtatActif($session, $etat->getCode());
+            $this->getSessionService()->update($session);
+
+            //Les gestions n'utilise pas le bouton correctement ...
+//            switch ($etat->getCode()) {
+//                case SessionEtats::ETAT_CREATION_EN_COURS :
+//                    exit();
+//                case SessionEtats::ETAT_INSCRIPTION_OUVERTE :
+//                    $this->getSessionService()->ouvrirInscription($session);
+//                    exit();
+//                case SessionEtats::ETAT_INSCRIPTION_FERMEE :
+//                    $this->getSessionService()->fermerInscription($session);
+//                    exit();
+//                case SessionEtats::ETAT_FORMATION_CONVOCATION :
+//                    $this->getSessionService()->envoyerConvocation($session);
+//                    $this->getSessionService()->envoyerEmargement($session);
+//                    exit();
+//                case SessionEtats::ETAT_ATTENTE_RETOURS :
+//                    $this->getSessionService()->demanderRetour($session);
+//                    exit();
+//                case SessionEtats::ETAT_CLOTURE_INSTANCE :
+//                    $this->getSessionService()->cloturer($session);
+//                    exit();
+//                case SessionEtats::ETAT_SESSION_ANNULEE :
+//                    $this->getSessionService()->annuler($session);
+//                    exit();
+//                default :
+//            }
 
             exit();
         }
@@ -417,6 +572,112 @@ class SessionController extends AbstractActionController
         ]);
     }
 
+
+    public function notifierResponsablePourValidationAction(): ViewModel
+    {
+        $session = $this->getSessionService()->getRequestedSession($this);
+        $inscriptions = $this->getInscriptionService()->getInscriptionsBySession($session);
+        $inscriptions = array_filter($inscriptions, function (Inscription $inscription) {
+            return $inscription->estNonHistorise() AND $inscription->isEtatActif(InscriptionEtats::ETAT_DEMANDE);
+        });
+
+        $mails = [];
+        /** @var Inscription $inscription */
+        foreach ($inscriptions as $inscription)
+        {
+            $mails[$inscription->getIndividu()->getDenomination()] =  $this->getNotificationService()->triggerRappelDemandeValidationValideur($inscription);
+        }
+
+        $success = []; $probleme = [];
+        foreach ($mails as $individu => $mail) {
+            if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+        }
+        if (!empty($success)) {
+            $successTexte = " Les valideur·deuses ont été notifié·es (".count($success)." courrier·s envoyé·s).";
+        }
+        if (!empty($probleme)) {
+            $problemeTexte = "L'opération n'a pas pu être faite pour les inscriptions de  : <ul>";
+            foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+            $problemeTexte .= "</ul>";
+        }
+
+        $vm = new ViewModel([
+            'title' => "Courrier de rappel de demande de validation",
+            'reponse' => "Opération effectuée",
+            'success' => $successTexte??null,
+            'error' => $problemeTexte??null,
+        ]);
+        $vm->setTemplate('default/reponse');
+        return $vm;
+    }
+
+    public function notifierInscritAction(): ViewModel
+    {
+        $session = $this->getSessionService()->getRequestedSession($this);
+
+        $form = $this->getNotificationForm();
+        $form->setAttribute('action', $this->url()->fromRoute('session/notifier-inscrit', ['session' => $session->getId()], [], true));
+        $form->bind($session);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $inscriptions = match ($data['liste']) {
+                    Inscription::PRINCIPALE => $session->getListePrincipale(),
+                    Inscription::COMPLEMENTAIRE => $session->getListeComplementaire(),
+                    'tous' => $session->getListeValide(),
+                    default => [],
+                };
+                $sujet = trim($data['sujet']);
+                $corps = trim($data['corps']);
+
+                foreach ($inscriptions as $inscription) {
+                    $adresse = $inscription->getIndividu()->getEmail();
+                    $mails[$inscription->getIndividu()->getDenomination()] = ($adresse)?$this->getMailService()->sendMail($adresse, $sujet, $corps,'Formation'):null;
+                    if ($mails[$inscription->getIndividu()->getDenomination()])
+                    {
+                        $mails[$inscription->getIndividu()->getDenomination()]->setMotsClefs([$session->generateTag(), $inscription->generateTag(), 'Notification interne']);
+                        $this->getMailService()->update($mails[$inscription->getIndividu()->getDenomination()]);
+                        $session->addMail($mails[$inscription->getIndividu()->getDenomination()]);
+                    }
+                }
+                $this->getSessionService()->update($session);
+
+                $success = []; $probleme = [];
+                foreach ($mails as $individu => $mail) {
+                    if ($mail === null) $probleme[] = $individu; else $success[] = $individu;
+                }
+                if (!empty($success)) {
+                    $successTexte = " Les stagiaires ont été notifié·es (".count($success)." courrier·s envoyé·s).";
+                }
+                if (!empty($probleme)) {
+                    $problemeTexte = "L'opération n'a pas pu être faite pour les inscriptions de  : <ul>";
+                    foreach ($probleme as $individu) $problemeTexte .= "<li>" . $individu . "</li>";
+                    $problemeTexte .= "</ul>";
+                }
+
+                $vm = new ViewModel([
+                    'title' => "Notification des inscrits",
+                    'reponse' => "Opération effectuée",
+                    'success' => $successTexte??null,
+                    'error' => $problemeTexte??null,
+                ]);
+                $vm->setTemplate('default/reponse');
+                return $vm;
+            }
+        }
+
+        $vm = new ViewModel([
+            'title' => "Notification des inscrits",
+            'form' => $form,
+        ]);
+        $vm->setTemplate('default/default-form');
+        return $vm;
+    }
+
+
     public function resultatEnqueteAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
diff --git a/module/Formation/src/Formation/Controller/SessionControllerFactory.php b/module/Formation/src/Formation/Controller/SessionControllerFactory.php
index af2f710ccd4c4d282accfb5fee9a4781d166d9c9..5174bff76cde9ec6450cc6dfd233fe2e028c2ee3 100644
--- a/module/Formation/src/Formation/Controller/SessionControllerFactory.php
+++ b/module/Formation/src/Formation/Controller/SessionControllerFactory.php
@@ -3,6 +3,7 @@
 namespace Formation\Controller;
 
 use Formation\Form\Annulation\AnnulationForm;
+use Formation\Form\Notification\NotificationForm;
 use Formation\Form\SelectionFormateur\SelectionFormateurForm;
 use Formation\Form\SelectionGestionnaire\SelectionGestionnaireForm;
 use Formation\Form\Session\SessionForm;
@@ -19,6 +20,7 @@ use Psr\Container\NotFoundExceptionInterface;
 use UnicaenEnquete\Service\Enquete\EnqueteService;
 use UnicaenEnquete\Service\Resultat\ResultatService;
 use UnicaenEtat\Service\EtatCategorie\EtatCategorieService;
+use UnicaenEtat\Service\EtatInstance\EtatInstanceService;
 use UnicaenEtat\Service\EtatType\EtatTypeService;
 use UnicaenMail\Service\Mail\MailService;
 use UnicaenParametre\Service\Parametre\ParametreService;
@@ -36,6 +38,7 @@ class SessionControllerFactory
         /**
          * @var EnqueteService $enqueteService
          * @var EtatCategorieService $etatCategorieService
+         * @var EtatInstanceService $etatInstanceService
          * @var EtatTypeService $etatTypeService
          * @var FormateurService $formateurService
          * @var FormationService $formationService
@@ -50,6 +53,7 @@ class SessionControllerFactory
          */
         $enqueteService = $container->get(EnqueteService::class);
         $etatCategorieService = $container->get(EtatCategorieService::class);
+        $etatInstanceService = $container->get(EtatInstanceService::class);
         $etatTypeService = $container->get(EtatTypeService::class);
         $formateurService = $container->get(FormateurService::class);
         $formationService = $container->get(FormationService::class);
@@ -65,11 +69,13 @@ class SessionControllerFactory
 
         /**
          * @var AnnulationForm $annulationForm
+         * @var NotificationForm $notificationForm
          * @var SelectionFormateurForm $selectionFormateurForm
          * @var SelectionGestionnaireForm $selectionGestionnaireForm
          * @var SessionForm $sessionForm
          */
         $annulationForm = $container->get('FormElementManager')->get(AnnulationForm::class);
+        $notificationForm = $container->get('FormElementManager')->get(NotificationForm::class);
         $sessionForm = $container->get('FormElementManager')->get(SessionForm::class);
         $selectionFormateurForm = $container->get('FormElementManager')->get(SelectionFormateurForm::class);
         $selectionGestionnaireForm = $container->get('FormElementManager')->get(SelectionGestionnaireForm::class);
@@ -77,6 +83,7 @@ class SessionControllerFactory
         $controller = new SessionController();
         $controller->setEnqueteService($enqueteService);
         $controller->setEtatCategorieService($etatCategorieService);
+        $controller->setEtatInstanceService($etatInstanceService);
         $controller->setEtatTypeService($etatTypeService);
         $controller->setFormateurService($formateurService);
         $controller->setFormationService($formationService);
@@ -90,6 +97,7 @@ class SessionControllerFactory
         $controller->setSessionService($sessionService);
         $controller->setUserService($userService);
         $controller->setAnnulationForm($annulationForm);
+        $controller->setNotificationForm($notificationForm);
         $controller->setSessionForm($sessionForm);
         $controller->setSelectionFormateurForm($selectionFormateurForm);
         $controller->setSelectionGestionnaireForm($selectionGestionnaireForm);
diff --git a/module/Formation/src/Formation/Entity/Db/Seance.php b/module/Formation/src/Formation/Entity/Db/Seance.php
index e302b841ef00fcce3303bc60a9d44c7abf444b68..f6c3aac5620e87fc055f8f3934231341d153a893 100644
--- a/module/Formation/src/Formation/Entity/Db/Seance.php
+++ b/module/Formation/src/Formation/Entity/Db/Seance.php
@@ -221,4 +221,24 @@ class Seance implements HistoriqueAwareInterface, HasSourceInterface
         $session = $this->getInstance();
         return ($session->getSeances() === null OR $session->getSeances() === [] OR $this->getDateFin()->format('d/m/Y H:i') === $session->getFin());
     }
+
+    /**
+     * @noinspection PhpUnused
+     * MACRO SEANCE#lieu
+     */
+    public function toStringLieu(): string
+    {
+        if ($this->getLieu() === null) return "Aucun lieu connu";
+        return $this->getLieu()->getBatiment(). " " .$this->getLieu()->getLibelle() . " - " . $this->getLieu()->getCampus() . " - " . $this->getLieu()->getVille();
+    }
+
+    /**
+     * @noinspection PhpUnused
+     * MACRO SEANCE#periode
+     */
+    public function getPeriode() : string
+    {
+        if (!$this->getDateDebut() OR !$this->getDateFin()) return "Aucune période connue";
+        return $this->getDateDebut()->format("d/m/Y H:i"). " au " .$this->getDateFin()->format("d/m/Y H:i");
+    }
 }
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Entity/Db/Session.php b/module/Formation/src/Formation/Entity/Db/Session.php
index c60a72df74ffb0a3f2916db2fcb61ed0945dae71..eab9aeeb0d31a738807f37eb028d4881ca42d0c7 100644
--- a/module/Formation/src/Formation/Entity/Db/Session.php
+++ b/module/Formation/src/Formation/Entity/Db/Session.php
@@ -418,6 +418,21 @@ class Session implements
         return $array;
     }
 
+    /**
+     * @return Inscription[]
+     */
+    public function getListeValide(): array
+    {
+        $array = array_filter($this->inscriptions->toArray(), function (Inscription $a) {
+            return ($a->estNonHistorise()
+                AND !$a->isEtatActif(InscriptionEtats::ETAT_DESISTEMENT));
+        });
+        usort($array, function (Inscription $a, Inscription $b) {
+            return $a->getStagiaireDenomination() <=> $b->getStagiaireDenomination();
+        });
+        return $array;
+    }
+
     /**
      * @return Inscription[]
      */
@@ -638,7 +653,38 @@ class Session implements
         return $this->getFormation()->getId() . "/" . $this->getId();
     }
 
-    /** @noinspection PhpUnused */
+    /** @noinspection PhpUnused
+     *  MACRO SESSION#inscrits */
+    public function getArrayListePrincipales(): string
+    {
+        $stagiaiares = array_map(function (Inscription $i) { return $i->getIndividu(); } , $this->getListePrincipale());
+        usort($stagiaiares, function ($a, $b) { return $a->getDenomination(false) <=> $b->getDenomination(false); });
+
+        $text = "<table class='bordered' style='width:100%;'>";
+        $text .= "<thead>";
+        $text .= "<tr style='border-bottom:1px solid black;'>";
+        $text .= "<th style='width: 50%;'>Stagiaires  </th>";
+        $text .= "<th style='width: 50%;'>Signature  </th>";
+        $text .= "</tr>";
+        $text .= "</thead>";
+        $text .= "<tbody>";
+        foreach ($stagiaiares as $stagiaire) {
+            $text .= "<tr>";
+            $text .= "<td>";
+            $text .= $stagiaire->getDenomination() . "<br>";
+            $text .= $stagiaire->getStructure() ;
+            $text .= "</td>";
+            $text .= "<td>" . "</td>";
+            $text .= "</tr>";
+        }
+        $text .= "</tbody>";
+        $text .= "</table>";
+
+        return $text;
+    }
+
+    /** @noinspection PhpUnused
+     *  MACRO SESSION#formateurs*/
     public function getListeFormateurs(): string
     {
         /** @var Formateur[] $formateurs */
@@ -667,6 +713,38 @@ class Session implements
         return $text;
     }
 
+    /** @noinspection PhpUnused
+     * MACRO SESSION#FormateursAvecSignature
+     **/
+    public function getArrayFormateurs(): string
+    {
+        /** @var Formateur[] $formateurs */
+        $formateurs = $this->getFormateurs();
+
+        $text = "<table class='bordered' style='width:100%;'>";
+        $text .= "<thead>";
+        $text .= "<tr style='border-bottom:1px solid black;'>";
+        $text .= "<th style='width:50%'> Dénomination </th>";
+        $text .= "<th style='width:50%'> Signature </th>";
+        $text .= "</tr>";
+        $text .= "</thead>";
+        $text .= "<tbody>";
+        foreach ($formateurs as $formateur) {
+            $text .= "<tr>";
+            $text .= "<td>";
+            $text .= $formateur->getPrenom() . " " . $formateur->getNom() . " <br>";
+            $text .= $formateur->getAttachement();
+            $text .= "</td>";
+            $text .= "<td>";
+            $text .= "</td>";
+            $text .= "</tr>";
+        }
+        $text .= "</tbody>";
+        $text .= "</table>";
+
+        return $text;
+    }
+
     /** @noinspection PhpUnused */
     public function getListeJournees(): string
     {
diff --git a/module/Formation/src/Formation/Form/Notification/NotificationForm.php b/module/Formation/src/Formation/Form/Notification/NotificationForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..81fdd39dc60dc8f5ecf60dbcfd0b512535c88fae
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Notification/NotificationForm.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Formation\Form\Notification;
+
+use Formation\Entity\Db\Inscription;
+use Laminas\Form\Element\Button;
+use Laminas\Form\Element\Select;
+use Laminas\Form\Element\Text;
+use Laminas\Form\Element\Textarea;
+use Laminas\Form\Form;
+use Laminas\InputFilter\Factory;
+
+class NotificationForm extends Form {
+
+    public function init(): void
+    {
+        // liste
+        $this->add([
+            'type' => Select::class,
+            'name' => 'liste',
+            'options' => [
+                'label' => "Liste à notifier <span class='icon icon-obligatoire' title='Obligatoire'></span>  :",
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+                'empty_option' => "Sélectionner une liste d'inscrit·e ...",
+                'value_options' => [
+                    Inscription::PRINCIPALE => 'Liste principale',
+                    Inscription::COMPLEMENTAIRE => 'Liste complémentaire',
+                    'tous' => 'Tou·tes les inscrit·es',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'liste',
+                'class'             => 'bootstrap-selectpicker show-tick',
+                'data-live-search'  => 'true',
+            ],
+        ]);
+        // libelle
+        $this->add([
+            'type' => Text::class,
+            'name' => 'sujet',
+            'options' => [
+                'label' => "Sujet du courrier <span class='icon icon-obligatoire' title='Champ obligatoire'></span>:",
+                'label_options' => [ 'disable_html_escape' => true, ],
+            ],
+            'attributes' => [
+                'id' => 'sujet',
+            ],
+        ]);
+        // corps
+        $this->add([
+            'name' => 'corps',
+            'type' => Textarea::class,
+            'options' => [
+                'label' => "Corps du courrier <span class='icon icon-obligatoire' title='Champ obligatoire'></span>:",
+                'label_options' => [ 'disable_html_escape' => true, ],
+            ],
+            'attributes' => [
+                'id' => 'corps',
+                'class' => 'tinymce',
+            ],
+        ]);
+    //bouton
+        $this->add([
+            'type' => Button::class,
+            'name' => 'creer',
+            'options' => [
+                'label' => '<span class="icon icon-notifier"></span> Notifier ',
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+            ],
+            'attributes' => [
+                'type' => 'submit',
+                'class' => 'btn btn-success',
+            ],
+        ]);
+
+        //input filter
+        $this->setInputFilter((new Factory())->createInputFilter([
+            'liste' => ['required' => true,],
+            'sujet' => ['required' => true,],
+            'corps' => ['required' => true,],
+        ]));
+    }
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Notification/NotificationFormAwareTrait.php b/module/Formation/src/Formation/Form/Notification/NotificationFormAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..f180a9e1358c2305c8d6bacc910d0b73ae3e7bfc
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Notification/NotificationFormAwareTrait.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Formation\Form\Notification;
+
+trait NotificationFormAwareTrait
+{
+    private NotificationForm $notificationForm;
+
+    public function getNotificationForm(): NotificationForm
+    {
+        return $this->notificationForm;
+    }
+
+    public function setNotificationForm(NotificationForm $notificationForm): void
+    {
+        $this->notificationForm = $notificationForm;
+    }
+
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Notification/NotificationFormFactory.php b/module/Formation/src/Formation/Form/Notification/NotificationFormFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..8f3bc303feacbe952077e7da7021bfce8039e326
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Notification/NotificationFormFactory.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Formation\Form\Notification;
+
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
+use Psr\Container\NotFoundExceptionInterface;
+
+class NotificationFormFactory
+{
+    /**
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $container): NotificationForm
+    {
+        $hydrator = $container->get('HydratorManager')->get(NotificationHydrator::class);
+        $form = new NotificationForm();
+        $form->setHydrator($hydrator);
+        return $form;
+    }
+
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Notification/NotificationHydrator.php b/module/Formation/src/Formation/Form/Notification/NotificationHydrator.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b0e9f3f652088c25cf0db029664fc22971c0196
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Notification/NotificationHydrator.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Formation\Form\Notification;
+
+use Laminas\Hydrator\HydratorInterface;
+
+class NotificationHydrator implements HydratorInterface
+{
+    public function extract(object $object): array
+    {
+        return [];
+    }
+
+    public function hydrate(array $data, object $object): object
+    {
+        return $object;
+    }
+
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Notification/NotificationHydratorFactory.php b/module/Formation/src/Formation/Form/Notification/NotificationHydratorFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..471abf2530d3e109f95178a1ed0d0632a5f62591
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Notification/NotificationHydratorFactory.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Formation\Form\Notification;
+
+use Psr\Container\ContainerInterface;
+
+class NotificationHydratorFactory
+{
+    public function __invoke(ContainerInterface $container): NotificationHydrator
+    {
+        $hydrator = new NotificationHydrator();
+        return $hydrator;
+    }
+
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Provider/Template/MailTemplates.php b/module/Formation/src/Formation/Provider/Template/MailTemplates.php
index 95c4f29ba8cf9f16bc82aec539e69e96eb103158..36a6aa1103103dfb06f0c1aa2efc905ef5ddb769 100644
--- a/module/Formation/src/Formation/Provider/Template/MailTemplates.php
+++ b/module/Formation/src/Formation/Provider/Template/MailTemplates.php
@@ -26,6 +26,8 @@ class MailTemplates {
     const SESSION_DEMANDE_RETOUR                        = "FORMATION_SESSION_DEMANDE_RETOUR";
     const SESSION_ANNULEE                               = "FORMATION_SESSION_ANNULEE";
 
+    //notification de rappel ou de precision
+    const SESSION_RAPPEL_DEMANDE_VALIDATION             = "FORMATION_SESSION_RAPPEL_DEMANDE_VALIDATION";
     //rappel
     const FORMATION_RAPPEL_AVANT_FORMATION              = "FORMATION_NOTIFICATION_SESSION_IMMINENTE";
     const FORMATION_INSCRIPTION_OUVERTE                 = "FORMATION_NOTIFICATION_ABONNEMENT_FORMATION";
diff --git a/module/Formation/src/Formation/Provider/Template/PdfTemplates.php b/module/Formation/src/Formation/Provider/Template/PdfTemplates.php
index 99d0026bdf84274db20a396d941945a5e007dc1e..7542c1a4743aa7c11f3ede22b73fc1de86ee2a44 100644
--- a/module/Formation/src/Formation/Provider/Template/PdfTemplates.php
+++ b/module/Formation/src/Formation/Provider/Template/PdfTemplates.php
@@ -8,4 +8,5 @@ class PdfTemplates {
     const FORMATION_ATTESTATION             = "FORMATION_ATTESTATION";
     const FORMATION_HISTORIQUE              = "FORMATION_HISTORIQUE";
     const FORMATION_ABSENCE                 = "FORMATION_ABSENCE";
+    const FORMATION_EMARGEMENT              = "FORMATION_EMARGEMENT";
 }
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Service/Notification/NotificationService.php b/module/Formation/src/Formation/Service/Notification/NotificationService.php
index eb7a08ddf84f9651fbecb170ded8451bb0029d4a..25aeeeff1f47e4f881efba1b4b0883097ad0169a 100644
--- a/module/Formation/src/Formation/Service/Notification/NotificationService.php
+++ b/module/Formation/src/Formation/Service/Notification/NotificationService.php
@@ -82,12 +82,16 @@ class NotificationService
 
     public function generateAndSend(string $templateCode, $adresses, array $motsClefs = [], array $vars = []): ?Mail
     {
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode($templateCode, $vars);
-        $mail = $this->getMailService()->sendMail($adresses, $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $motsClefs[] = $rendu->getTemplate()->generateTag();
-        $mail->setMotsClefs($motsClefs);
-        $this->getMailService()->update($mail);
+        try {
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode($templateCode, $vars);
+            $mail = $this->getMailService()->sendMail($adresses, $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $motsClefs[] = $rendu->getTemplate()->generateTag();
+            $mail->setMotsClefs($motsClefs);
+            $this->getMailService()->update($mail);
         return $mail;
+        } catch (RuntimeException $e) {
+            return null;
+        }
     }
 
     /** GESTION DES INSCRIPTIONS **************************************************************************************/
@@ -211,14 +215,17 @@ class NotificationService
         $session = $inscrit->getSession();
         if (!$session->isMailActive()) return null;
 
-        $vars = $this->generateVariableArray($inscrit);
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_LISTE_PRINCIPALE, $vars);
-        $mail = $this->getMailService()->sendMail($inscrit->getIndividu()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
-        $this->getMailService()->update($mail);
-        $session->addMail($mail);
-        $this->getObjectManager()->flush($session);
-        return $mail;
+        if ($inscrit->getIndividu() !== null AND $inscrit->getIndividu()->getEmail() !== null) {
+            $vars = $this->generateVariableArray($inscrit);
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_LISTE_PRINCIPALE, $vars);
+            $mail = $this->getMailService()->sendMail($inscrit->getIndividu()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
     }
 
     /** Notification envoyée vers les inscrit·es de la liste complémentaire lors de la clôture des inscriptions */
@@ -228,14 +235,17 @@ class NotificationService
         if (!$session->isMailActive()) return null;
         $individu = $inscrit->getIndividu();
 
-        $vars = $this->generateVariableArray($inscrit);
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_LISTE_COMPLEMENTAIRE, $vars);
-        $mail = $this->getMailService()->sendMail($individu->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
-        $this->getMailService()->update($mail);
-        $session->addMail($mail);
-        $this->getObjectManager()->flush($session);
-        return $mail;
+        if ($inscrit->getIndividu() !== null AND $inscrit->getIndividu()->getEmail() !== null) {
+            $vars = $this->generateVariableArray($inscrit);
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_LISTE_COMPLEMENTAIRE, $vars);
+            $mail = $this->getMailService()->sendMail($individu->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
     }
 
     /** Notification vers l'agent lors de son retrait d'une liste */
@@ -244,14 +254,17 @@ class NotificationService
         $session = $inscrit->getSession();
         if (!$session->isMailActive()) return null;
 
-        $vars = $this->generateVariableArray($inscrit);
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_LISTE_COMPLEMENTAIRE, $vars);
-        $mail = $this->getMailService()->sendMail($inscrit->getAgent()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
-        $this->getMailService()->update($mail);
-        $session->addMail($mail);
-        $this->getObjectManager()->flush($session);
-        return $mail;
+        if ($inscrit->getIndividu() !== null AND $inscrit->getIndividu()->getEmail() !== null) {
+            $vars = $this->generateVariableArray($inscrit);
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_LISTE_COMPLEMENTAIRE, $vars);
+            $mail = $this->getMailService()->sendMail($inscrit->getAgent()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
     }
 
     /** Notification envoyée vers l'inscrit de la liste principale pour convocation */
@@ -272,13 +285,16 @@ class NotificationService
             foreach ($superieurs as $superieur) $copie[] = $superieur->getValidateur()->getEmail();
         }
 
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_CONVOCATION, $vars);
-        $mail = $this->getMailService()->sendMail($agent->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation', null, $copie);
-        $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
-        $this->getMailService()->update($mail);
-        $session->addMail($mail);
-        $this->getObjectManager()->flush($session);
-        return $mail;
+        if ($inscrit->getIndividu() !== null AND $inscrit->getIndividu()->getEmail() !== null) {
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_CONVOCATION, $vars);
+            $mail = $this->getMailService()->sendMail($agent->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation', null, $copie);
+            $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
     }
 
     /** Notification envoyée vers les stagaires pour leur demander leurs retours */
@@ -294,12 +310,15 @@ class NotificationService
 
         $vars = $this->generateVariableArray($inscrit);
         $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_DEMANDE_RETOUR, $vars);
-        $mail = $this->getMailService()->sendMail($inscrit->getIndividu()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
-        $this->getMailService()->update($mail);
-        $session->addMail($mail);
-        $this->getObjectManager()->flush($session);
-        return $mail;
+        if ($inscrit->getIndividu() !== null AND $inscrit->getIndividu()->getEmail() !== null) {
+            $mail = $this->getMailService()->sendMail($inscrit->getIndividu()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
     }
 
     /** Notification vers les inscrit·e ayant eu une absence */
@@ -379,16 +398,42 @@ class NotificationService
         $agent = $inscrit->getAgent();
         if ($agent === null) throw new RuntimeException("Aucune personne d'identifié·e pour cette inscription");
 
-        $vars = $this->generateVariableArray($inscrit);
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_ANNULEE, $vars);
-        $mail = $this->getMailService()->sendMail($inscrit->getAgent()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+        if ($inscrit->getIndividu() !== null AND $inscrit->getIndividu()->getEmail() !== null) {
+            $vars = $this->generateVariableArray($inscrit);
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_ANNULEE, $vars);
+            $mail = $this->getMailService()->sendMail($inscrit->getAgent()->getEmail(), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $mail->setMotsClefs([$session->generateTag(), $inscrit->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
+    }
+
+    public function triggerRappelDemandeValidationValideur(Inscription $inscription): ?Mail
+    {
+        $valideurs = $this->getAgentValidateurService()->getAgentsValidateursByAgent($inscription->getAgent());
+        if (empty($valideurs)) return null;
+
+        $adresses = [];
+        foreach ($valideurs as $valideur) {
+            if ($valideur->getAgent()->getEmail()) $adresses[] = $valideur->getValidateur()->getEmail();
+        }
+        if (empty($adresses)) return null;
+
+        $session = $inscription->getSession();
+
+        $vars = $this->generateVariableArray($inscription);
+        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_RAPPEL_DEMANDE_VALIDATION, $vars);
+        $mail = $this->getMailService()->sendMail($adresses, $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+        $mail->setMotsClefs([$session->generateTag(), $inscription->generateTag(), $rendu->getTemplate()->generateTag()]);
         $this->getMailService()->update($mail);
         $session->addMail($mail);
         $this->getObjectManager()->flush($session);
         return $mail;
-    }
 
+    }
 
     /** Mails de rappel ***********************************************************************************************/
 
@@ -422,20 +467,23 @@ class NotificationService
             $mails[] = $formateur->getEmail();
         }
 
-        $urlService = $this->getUrlService()->setVariables(['instance' => $session]);
-        $vars = [
-            'session' => $session,
-            'instance' => $session,
-            'UrlService' => $urlService,
-            'MacroService' => $this->getMacroService()
-        ];
-        $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_EMARGEMENT, $vars);
-        $mail = $this->getMailService()->sendMail(implode(",", $mails), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
-        $mail->setMotsClefs([$session->generateTag(), $rendu->getTemplate()->generateTag()]);
-        $this->getMailService()->update($mail);
-        $session->addMail($mail);
-        $this->getObjectManager()->flush($session);
-        return $mail;
+        if (!empty($mails)) {
+            $urlService = $this->getUrlService()->setVariables(['instance' => $session]);
+            $vars = [
+                'session' => $session,
+                'instance' => $session,
+                'UrlService' => $urlService,
+                'MacroService' => $this->getMacroService()
+            ];
+            $rendu = $this->getRenduService()->generateRenduByTemplateCode(MailTemplates::SESSION_EMARGEMENT, $vars);
+            $mail = $this->getMailService()->sendMail(implode(",", $mails), $rendu->getSujet(), $rendu->getCorps(), 'Formation');
+            $mail->setMotsClefs([$session->generateTag(), $rendu->getTemplate()->generateTag()]);
+            $this->getMailService()->update($mail);
+            $session->addMail($mail);
+            $this->getObjectManager()->flush($session);
+            return $mail;
+        }
+        return null;
     }
 
     /**
diff --git a/module/Formation/src/Formation/Service/Seance/SeanceService.php b/module/Formation/src/Formation/Service/Seance/SeanceService.php
index 885848e957a397fc1e00ca8d490e7777d05942be..1d8b3d92c99048bf167f0b60ee132da2a058bfbb 100644
--- a/module/Formation/src/Formation/Service/Seance/SeanceService.php
+++ b/module/Formation/src/Formation/Service/Seance/SeanceService.php
@@ -99,7 +99,7 @@ class SeanceService
      * @param integer $id
      * @return Seance|null
      */
-    public function getSeance(int $id): ?Seance
+    public function getSeance(?int $id): ?Seance
     {
         $qb = $this->createQueryBuilder()
             ->andWhere('journee.id = :id')
diff --git a/module/Formation/src/Formation/Service/Session/SessionService.php b/module/Formation/src/Formation/Service/Session/SessionService.php
index 4d107be10a8c5d5e17a3e4660aa56c96b8b3f97c..f078aa280b4c154129d760686ee2213a0e49e0e7 100644
--- a/module/Formation/src/Formation/Service/Session/SessionService.php
+++ b/module/Formation/src/Formation/Service/Session/SessionService.php
@@ -24,6 +24,7 @@ use Laminas\Mvc\Controller\AbstractActionController;
 use UnicaenApp\Exception\RuntimeException;
 use UnicaenEtat\Service\EtatInstance\EtatInstanceServiceAwareTrait;
 use UnicaenEtat\Service\EtatType\EtatTypeServiceAwareTrait;
+use UnicaenMail\Entity\Db\Mail;
 use UnicaenParametre\Service\Parametre\ParametreServiceAwareTrait;
 use UnicaenUtilisateur\Entity\Db\UserInterface;
 
@@ -334,48 +335,35 @@ class SessionService
 
     /** Fonctions associées aux états de l'instance *******************************************************************/
 
-
-    public function recreation(Session $instance): Session
-    {
-        $this->getEtatInstanceService()->setEtatActif($instance, SessionEtats::ETAT_CREATION_EN_COURS);
-        $this->update($instance);
-
-        return $instance;
-    }
-
-
-    /**
-     * @param Session $instance
-     * @return Session
-     */
-    public function ouvrirInscription(Session $instance): Session
+    /** @return Mail[] */
+    public function ouvrirInscription(Session $session): array
     {
-        $this->getEtatInstanceService()->setEtatActif($instance, SessionEtats::ETAT_INSCRIPTION_OUVERTE);
-        $this->update($instance);
-
+        $this->getEtatInstanceService()->setEtatActif($session, SessionEtats::ETAT_INSCRIPTION_OUVERTE);
+        $this->update($session);
 
         //notification abonnement
-        $abonnements = $instance->getFormation()->getAbonnements();
+        $abonnements = $session->getFormation()->getAbonnements();
+        $mails = [];
         foreach ($abonnements as $abonnement) {
-            if ($abonnement->estNonHistorise()) $this->getNotificationService()->triggerNouvelleSession($instance, $abonnement);
+            if ($abonnement->estNonHistorise()) {
+                $mails[$abonnement->getAgent()->getDenomination()] = $this->getNotificationService()->triggerNouvelleSession($session, $abonnement);
+            }
         }
 
-        return $instance;
+        return $mails;
     }
 
-    /**
-     * @param Session $instance
-     * @return Session
-     */
-    public function fermerInscription(Session $instance): Session
+    /** @return Mail[] */
+    public function fermerInscription(Session $session): array
     {
-        $this->getEtatInstanceService()->setEtatActif($instance, SessionEtats::ETAT_INSCRIPTION_FERMEE);
-        $this->update($instance);
+        $this->getEtatInstanceService()->setEtatActif($session, SessionEtats::ETAT_INSCRIPTION_FERMEE);
+        $this->update($session);
 
-        foreach ($instance->getListePrincipale() as $inscrit) {
+        $mails = [];
+        foreach ($session->getListePrincipale() as $inscrit) {
 
             $configuration = $this->getNotificationConfigurationService()->getNotificationConfigurationWithParams("SESSION", MailTemplates::SESSION_LISTE_PRINCIPALE, "Inscriptions closes");
-            if ($configuration === null OR $configuration->isActive()) $this->getNotificationService()->triggerListePrincipale($inscrit);
+            if ($configuration === null OR $configuration->isActive()) $mails[$inscrit->getIndividu()->getDenomination() . " (Liste principale)"] = $this->getNotificationService()->triggerListePrincipale($inscrit);
 
             $agent = $inscrit->getAgent();
             $formation = $inscrit->getSession()->getFormation();
@@ -384,23 +372,26 @@ class SessionService
                 if ($abonnement !== null) $this->getAbonnementService()->retirerAbonnement($agent, $formation);
             }
         }
-        foreach ($instance->getListeComplementaire() as $inscrit) {
+        foreach ($session->getListeComplementaire() as $inscrit) {
 
             $configuration = $this->getNotificationConfigurationService()->getNotificationConfigurationWithParams("SESSION", MailTemplates::SESSION_LISTE_COMPLEMENTAIRE, "Inscriptions closes");
-            if ($configuration === null OR $configuration->isActive()) $this->getNotificationService()->triggerListeComplementaire($inscrit);
-
-            $agent = $inscrit->getAgent();
-            $formation = $inscrit->getSession()->getFormation();
-            if ($inscrit->isInterne()) {
-                $abonnement = $this->getAbonnementService()->getAbonnementByAgentAndFormation($agent, $formation);
-                if ($abonnement === null) $this->getAbonnementService()->ajouterAbonnement($agent, $formation);
-            }
+            if ($configuration === null OR $configuration->isActive()) $mails[$inscrit->getIndividu()->getDenomination() . " (Liste complémentaire)"] = $this->getNotificationService()->triggerListeComplementaire($inscrit);
+
+            //NOTE :: sera fait à la cloture de la session plutôt qu'à la cloture
+//            $agent = $inscrit->getAgent();
+//            $formation = $inscrit->getSession()->getFormation();
+//            if ($inscrit->isInterne()) {
+//                $abonnement = $this->getAbonnementService()->getAbonnementByAgentAndFormation($agent, $formation);
+//                if ($abonnement === null) $this->getAbonnementService()->ajouterAbonnement($agent, $formation);
+//            }
         }
-        return $instance;
+        return $mails;
     }
 
-    public function envoyerConvocation(Session $session, ?Inscription $inscription = null): Session
+    /** @return Mail[] $mails */
+    public function envoyerConvocation(Session $session, ?Inscription $inscription = null): array
     {
+        $mails = [];
         if ($inscription === null) {
             $this->getEtatInstanceService()->setEtatActif($session, SessionEtats::ETAT_FORMATION_CONVOCATION);
             $this->update($session);
@@ -412,39 +403,43 @@ class SessionService
         if ($configuration === null OR $configuration->isActive()) {
             foreach ($liste as $inscrit) {
                 if ($inscrit->estNonHistorise()) {
-                    $this->getNotificationService()->triggerConvocation($inscrit);
+                    $mails[$inscrit->getIndividu()->getDenomination()] = $this->getNotificationService()->triggerConvocation($inscrit);
                 }
             }
         }
-        return $session;
+        return $mails;
     }
 
-    public function demanderRetour(Session $instance): Session
+    /** @return Mail[] $mails */
+    public function demanderRetour(Session $session): array
     {
-        $this->getEtatInstanceService()->setEtatActif($instance, SessionEtats::ETAT_ATTENTE_RETOURS);
-        $this->update($instance);
+        $mails = [];
+        $this->getEtatInstanceService()->setEtatActif($session, SessionEtats::ETAT_ATTENTE_RETOURS);
+        $this->update($session);
 
         $configuration = $this->getNotificationConfigurationService()->getNotificationConfigurationWithParams("SESSION", MailTemplates::SESSION_DEMANDE_RETOUR, "Demande de retour");
         if ($configuration === null OR $configuration->isActive()) {
-            foreach ($instance->getListePrincipale() as $inscrit) {
-                $this->getNotificationService()->triggerDemandeRetour($inscrit);
+            foreach ($session->getListePrincipale() as $inscrit) {
+                $mails[$inscrit->getIndividu()->getDenomination()] = $this->getNotificationService()->triggerDemandeRetour($inscrit);
             }
         }
-        return $instance;
+        return $mails;
     }
 
-    public function envoyerAbsence(Session $session, ?Inscription $inscription = null): Session
+    /** @return Mail[] */
+    public function envoyerAbsence(Session $session, ?Inscription $inscription = null): array
     {
         $liste = [];
         if ($inscription !== null) $liste[] = $inscription; else $liste = $session->getListePrincipale();
 
+        $mails = [];
         $configuration = $this->getNotificationConfigurationService()->getNotificationConfigurationWithParams("SESSION", MailTemplates::SESSION_ABSENCE, "Envoi des constats d'absence");
         if ($configuration === null OR $configuration->isActive()) {
             foreach ($liste as $inscrit) {
-                if ($inscrit->estNonHistorise()) $this->getNotificationService()->triggerConstatAbsence($inscrit);
+                if ($inscrit->estNonHistorise()) $mails[] =  $this->getNotificationService()->triggerConstatAbsence($inscrit);
             }
         }
-        return $session;
+        return $mails;
     }
 
     public function envoyerAttestation(Session $session, ?Inscription $inscription = null): Session
@@ -460,68 +455,64 @@ class SessionService
         return $session;
     }
 
-
-
-
-    /**
-     * @param Session $instance
-     * @return Session
-     */
-    public function envoyerEmargement(Session $instance): Session
+    /** @return Mail[] */
+    public function envoyerEmargement(Session $session): array
     {
-        if ($instance->isEmargementActive()) {
-            $this->update($instance);
-            $this->getNotificationService()->triggerLienPourEmargement($instance);
+        $mails = [];
+        if ($session->isEmargementActive()) {
+            $this->update($session);
+            $configuration = $this->getNotificationConfigurationService()->getNotificationConfigurationWithParams("SESSION", MailTemplates::SESSION_EMARGEMENT, "Envoi de l'emargement");
+            if ($configuration === null OR $configuration->isActive()) {
+                $mails[] = $this->getNotificationService()->triggerLienPourEmargement($session);
+            }
         }
-        return $instance;
+        return $mails;
     }
 
 
 
-    /**
-     * @param Session $instance
-     * @return Session
-     */
-    public function cloturer(Session $instance): Session
+    /** @return Mail[] */
+    public function cloturer(Session $session): array
     {
         //changement de l'état de la session
-        $this->getEtatInstanceService()->setEtatActif($instance, SessionEtats::ETAT_CLOTURE_INSTANCE);
-        $this->update($instance);
+        $this->getEtatInstanceService()->setEtatActif($session, SessionEtats::ETAT_CLOTURE_INSTANCE);
+        $this->update($session);
 
+        $mails = [];
         //ajout d'un abonnement à la formation aux inscrits de la liste complémentaire
-        $formation = $instance->getFormation();
-        foreach ($instance->getListeComplementaire() as $inscription) {
-            $agent = $inscription->getAgent();
-            if ($agent !== null) { // exclusion des stagiaires externes
-                $abonnement = $this->getAbonnementService()->getAbonnementByAgentAndFormation($agent, $formation);
-                if ($abonnement === null) {
-                    $this->getAbonnementService()->ajouterAbonnement($agent, $formation);
-                    $this->getNotificationService()->triggerAjoutAbonnementPostCloture($inscription);
+        $formation = $session->getFormation();
+        foreach ($session->getListeComplementaire() as $inscription) {
+            if ($inscription->isInterne()) { // exclusion des stagiaires externes
+                $agent = $inscription->getAgent();
+                if ($agent !== null) {
+                    $abonnement = $this->getAbonnementService()->getAbonnementByAgentAndFormation($agent, $formation);
+                    if ($abonnement === null) {
+                        $this->getAbonnementService()->ajouterAbonnement($agent, $formation);
+                        $mails[] = $this->getNotificationService()->triggerAjoutAbonnementPostCloture($inscription);
+                    }
                 }
             }
         }
-        return $instance;
+        return $mails;
     }
 
-    /**
-     * @param Session $instance
-     * @return Session
-     */
-    public function annuler(Session $instance): Session
+    /** @return Mail[] */
+    public function annuler(Session $session): array
     {
-        $this->getEtatInstanceService()->setEtatActif($instance, SessionEtats::ETAT_SESSION_ANNULEE);
-        $this->update($instance);
-        foreach ($instance->getInscriptions() as $inscrit) {
+        $this->getEtatInstanceService()->setEtatActif($session, SessionEtats::ETAT_SESSION_ANNULEE);
+        $this->update($session);
+        $mails = [];
+        foreach ($session->getInscriptions() as $inscrit) {
             if (!$inscrit->isEtatActif(InscriptionEtats::ETAT_DESISTEMENT AND !$inscrit->isEtatActif(InscriptionEtats::ETAT_REFUSER))) {
                 $configuration = $this->getNotificationConfigurationService()->getNotificationConfigurationWithParams("SESSION", MailTemplates::SESSION_ANNULEE, "Annulation de la session");
-                if ($configuration === null or $configuration->isActive()) $this->getNotificationService()->triggerSessionAnnulee($inscrit);
+                if ($configuration === null or $configuration->isActive()) $mails[$inscrit->getStagiaireDenomination()] = $this->getNotificationService()->triggerSessionAnnulee($inscrit);
                 $agent = $inscrit->getAgent();
                 $formation = $inscrit->getSession()->getFormation();
                 $abonnement = $this->getAbonnementService()->getAbonnementByAgentAndFormation($agent, $formation);
-                if ($abonnement === null) $this->getAbonnementService()->ajouterAbonnement($agent, $formation);
+                if ($abonnement === null) $mails[$agent->getDenomination()] = $this->getAbonnementService()->ajouterAbonnement($agent, $formation);
             }
         }
-        return $instance;
+        return $mails;
     }
 
     /**
@@ -601,11 +592,9 @@ class SessionService
         $result = [];
         /** @var Session[] $sessions */
         foreach ($sessions as $session) {
-            $formation = $session->getFormation();
-            $groupe = $formation->getGroupe();
             $result[] = array(
                 'id' => $session->getId(),
-                'label' => ($groupe ? $groupe->getLibelle() : "Acucun groupe") . " > " . $session->getFormation()->getLibelle(),
+                'label' =>  $session->getFormation()->getLibelle(),
                 'extra' => "<span class='badge' style='background-color: slategray;'>" . $session->getPeriode() . "</span>",
             );
         }
diff --git a/module/Formation/src/Formation/View/Helper/partial/session-informations.phtml b/module/Formation/src/Formation/View/Helper/partial/session-informations.phtml
index 8a479325bc1d62e6d896d9fcafa8f47ff730ffd3..fcb95c359109d0166d5e99ed6db157762bf4a61b 100644
--- a/module/Formation/src/Formation/View/Helper/partial/session-informations.phtml
+++ b/module/Formation/src/Formation/View/Helper/partial/session-informations.phtml
@@ -11,11 +11,13 @@ use Application\Entity\Db\Interfaces\HasSourceInterface;
 use DemandeExterne\Provider\Privilege\DemandeexternePrivileges;
 use Formation\Entity\Db\Session;
 use Formation\Provider\Etat\SessionEtats;
+use Formation\Provider\Privilege\FormationinstancePrivileges;
 
 
 $gestionnaires = $session->getGestionnaires();
 
 $canAfficherDemande = $this->isAllowed(DemandeexternePrivileges::getResourceId(DemandeexternePrivileges::DEMANDEEXTERNE_AFFICHER));
+$canGereInscription = $this->isAllowed(FormationinstancePrivileges::getResourceId(FormationinstancePrivileges::FORMATIONINSTANCE_GERER_INSCRIPTION));
 
 $displayCloture = (!isset($options['display-cloture']) OR $options['display-cloture'] !== false);
 $displayListe = (!isset($options['display-liste']) OR $options['display-liste'] !== false);
@@ -121,9 +123,14 @@ $displayListe = (!isset($options['display-liste']) OR $options['display-liste']
         <?php echo $session->getType(); ?> - <?php echo $session->getDuree(); ?> -
     <?php endif; ?>
     <?php if ($displayListe) : ?>
-        Liste principale
-        <?php if ($session->getSource() !== HasSourceInterface::SOURCE_LAGAF) : ?>
-            <?php echo count($session->getListePrincipale()); ?>/<?php echo $session->getNbPlacePrincipale(); ?>
+
+        <?php if ($canGereInscription) : ?>
+            <?php if ($session->getSource() !== HasSourceInterface::SOURCE_LAGAF) : ?>
+                Liste principale
+                <?php echo count($session->getListePrincipale()); ?>/<?php echo $session->getNbPlacePrincipale(); ?>
+            <?php endif; ?>
+        <?php else : ?>
+            Nombre de place en liste principale : <?php echo $session->getNbPlacePrincipale(); ?> places
         <?php endif; ?>
     <?php endif; ?>
     <!--    --->
diff --git a/module/Formation/src/Formation/View/Helper/partial/sessions-array.phtml b/module/Formation/src/Formation/View/Helper/partial/sessions-array.phtml
index 59a2491b4da474cee40b5c6988a78d7d74ca0f9c..f7ccd7790bad4dfc6ffd68dd80281269dc345f99 100644
--- a/module/Formation/src/Formation/View/Helper/partial/sessions-array.phtml
+++ b/module/Formation/src/Formation/View/Helper/partial/sessions-array.phtml
@@ -6,10 +6,8 @@
  * @var array $options
  */
 
-
 /** Droits pour les actions */
 
-use Formation\Entity\Db\Seance;
 use Formation\Entity\Db\Session;
 use Formation\Provider\Etat\SessionEtats;
 use Formation\Provider\Privilege\FormationPrivileges;
@@ -18,6 +16,8 @@ $displayGestionnaire = true;
 if (isset($options['affichage']) and isset($options['affichage']['gestionnaires'])) {
     $displayGestionnaire = $options['affichage']['gestionnaires'];
 }
+$id = (isset($options['id'])) ? $options['id'] : null;
+
 
 $canAfficherInstance = false;
 if (!isset($options['droits']) and !isset($options['droits']['afficher'])) {
@@ -44,7 +44,7 @@ usort($sessions, function (Session $a, Session $b) {
 $sessions = array_reverse($sessions);
 ?>
 
-<table class="datatable table table-condensed" id="">
+<table class="datatable table table-condensed" <?php if ($id) echo 'id="' . $id . '"'; ?>>
     <thead>
     <tr>
         <th> Session</th>
@@ -52,7 +52,7 @@ $sessions = array_reverse($sessions);
             <th> Gestionnaire·s</th> <?php endif; ?>
         <th> Période</th>
         <th> #Inscrit</th>
-        <th>  État</th>
+        <th> État</th>
         <th class="action"> Action</th>
     </tr>
     </thead>
@@ -61,8 +61,8 @@ $sessions = array_reverse($sessions);
         <?php if ($canSupprimerInstance or $instance->estNonHistorise()) : ?>
             <tr class="<?php if ($instance->estHistorise()) echo " historise "; ?>"
                 style="<?php if (in_array($instance->getEtatActif()->getType()->getCode(), SessionEtats::ETATS_OUVERTS)
-                        AND ($instance->getDateClotureInscription() === null
-                            OR $instance->getDateClotureInscription() < (new DateTime())))  echo 'background: var(--unistrap-color-light)'; ?>"
+                    and ($instance->getDateClotureInscription() === null
+                        or $instance->getDateClotureInscription() < (new DateTime()))) echo 'background: var(--unistrap-color-light)'; ?>"
             >
                 <td class="identification">
                         <span class="badge source <?php echo $instance->getSource(); ?>">
@@ -169,6 +169,16 @@ $sessions = array_reverse($sessions);
     </tbody>
 </table>
 
-<script>
-
-</script>
+<?php if ($id) : ?>
+    <script>
+        $(function () {
+            $('table#<?php echo $id; ?>').dataTable({
+                paging: false,
+                autoWidth: false,
+                "language": {
+                    "url": "/js/datatables_fr.json",
+                },
+            });
+        });
+    </script>
+<?php endif; ?>
diff --git a/module/Formation/view/formation/session/afficher.phtml b/module/Formation/view/formation/session/afficher.phtml
index 3bb6045fc74734f15f0d376f1bdb02a9990c2b1c..7efeedeead14c8664c1d9abbe984636a2197302a 100644
--- a/module/Formation/view/formation/session/afficher.phtml
+++ b/module/Formation/view/formation/session/afficher.phtml
@@ -129,7 +129,7 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                     <br/>
                     <a <?php /** @see SessionController::ouvrirInscriptionAction() */ ?>
                             href="<?php echo $this->url('session/ouvrir-inscription', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-primary">
+                            class="btn btn-primary ajax-modal">
                         Ouvrir les inscriptions
                     </a>
                 <?php endif; ?>
@@ -137,7 +137,7 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                     <br/>
                     <a <?php /** @see SessionController::fermerInscriptionAction() */ ?>
                             href="<?php echo $this->url('session/fermer-inscription', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-primary">
+                            class="btn btn-primary ajax-modal">
                         Fermer les inscriptions
                     </a>
                 <?php endif; ?>
@@ -145,7 +145,7 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                     <br/>
                     <a <?php /** @see SessionController::envoyerConvocationAction() */ ?>
                             href="<?php echo $this->url('session/envoyer-convocation', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-primary">
+                            class="btn btn-primary  ajax-modal">
                         Convoquer les inscrits
                     </a>
                 <?php endif; ?>
@@ -153,7 +153,7 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                     <br/>
                     <a <?php /** @see SessionController::demanderRetourAction() */ ?>
                             href="<?php echo $this->url('session/demander-retour', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-primary">
+                            class="btn btn-primary ajax-modal">
                         Demander les retours
                     </a>
                 <?php endif; ?>
@@ -161,7 +161,7 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                     <br/>
                     <a <?php /** @see SessionController::cloturerAction() */ ?>
                             href="<?php echo $this->url('session/cloturer', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-primary  <?php if (!empty($presencesManquantes) or !empty($fraisManquants)) echo " disabled "; ?>">
+                            class="btn btn-primary ajax-modal <?php if (!empty($presencesManquantes) or !empty($fraisManquants)) echo " disabled "; ?>">
                         Clotûrer la session
                     </a>
                 <?php endif; ?>
@@ -169,7 +169,7 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
             <?php if ($canGererInscription) : ?>
                 <a <?php /** @see SessionController::changerEtatAction() */ ?>
                         href="<?php echo $this->url('session/changer-etat', ['session' => $session->getId()], [], true); ?>"
-                        class="btn btn-primary ajax-modal" data-event="modification">
+                        class="btn btn-warning ajax-modal" data-event="modification">
                     Changer l'état
                 </a>
             <?php endif; ?>
@@ -178,13 +178,13 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                 <?php if (!$session->isEtatActif(SessionEtats::ETAT_SESSION_ANNULEE)) : ?>
                     <a <?php /** @see SessionController::annulerAction() */ ?>
                             href="<?php echo $this->url('session/annuler', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-danger ajax-modal" data-event="modification">
+                            class="btn btn-danger ajax-modal" >
                         Annuler la session
                     </a>
                 <?php else : ?>
                     <a <?php /** @see SessionController::reouvrirAction() */ ?>
                             href="<?php echo $this->url('session/reouvrir', ['session' => $session->getId()], [], true); ?>"
-                            class="btn btn-primary">
+                            class="btn btn-primary ajax-modal">
                         Remettre la session en édition
                     </a>
                 <?php endif; ?>
@@ -342,8 +342,8 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                         <br/>
                     <?php endif; ?>
                     <?php if ($canEmargement): ?>
-                        <?php /** @see FormationInstanceDocumentController::exportTousEmargementsAction() */ ?>
-                        <a href="<?php echo $this->url('session/export-tous-emargements', ['session' => $session->getId()], [], true); ?>"
+                        <?php /** @see FormationInstanceDocumentController::genererEmargementAction() */ ?>
+                        <a href="<?php echo $this->url('session/generer-emargement', ['session' => $session->getId()], [], true); ?>"
                            class="btn btn-primary" target="_blank">
                             <span class="icon icon-pdf"></span>
                             Exporter les émargements
@@ -415,8 +415,8 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                             </td>
                             <td>
                                 <?php if ($canEmargement) : ?>
-                                    <?php /** @see FormationInstanceDocumentController::exportEmargementAction() */ ?>
-                                    <a href="<?php echo $this->url('session/export-emargement', ['journee' => $journee->getId()], [], true); ?>"
+                                    <?php /** @see FormationInstanceDocumentController::genererEmargementAction() */ ?>
+                                    <a href="<?php echo $this->url('session/generer-emargement', ['session' => $session->getId(), 'seance' => $journee->getId()], [], true); ?>"
                                        title="Exporter l'émargement de la séance de formation" target="_blank">
                                         <span class="icon icon-pdf"></span><span class="lettrine">E</span></a>
                                 <?php endif; ?>
@@ -517,4 +517,10 @@ $canMesSessions = $this->isAllowed(FormateurPrivileges::getResourceId(FormateurP
                 window.location.reload();
             });
         });
+
+        $(function () {
+            $(document).on('hide.bs.modal', '.modal', function () {
+                window.parent.location.reload();
+            });
+        });
     </script>
\ No newline at end of file
diff --git a/module/Formation/view/formation/session/changer-etat.phtml b/module/Formation/view/formation/session/changer-etat.phtml
index be3fb7a2eb2f1f7d486935a336823be8dd84ccad..1aacac946ec3ae9c325a3fc7a647038016ec5148 100644
--- a/module/Formation/view/formation/session/changer-etat.phtml
+++ b/module/Formation/view/formation/session/changer-etat.phtml
@@ -11,6 +11,19 @@ use UnicaenEtat\Entity\Db\EtatType;
 
 ?>
 
+<div class="alert alert-warning">
+    <p>
+        <strong>
+            <span class="icon icon-attention"></span>
+            Cette action ne fait que de modifier l'état associé à la session.
+        </strong>
+    </p>
+    <p>
+        Elle ne provoque aucun envoi de mail ou traitement.
+        Pour réaliser cela, veuillez utiliser les boutons associés aux différentes étapes du cycle de vie d'une session.
+    </p>
+</div>
+
 <div class="alert alert-info">
     La session de formation <strong><?php echo $session->getFormation()->getLibelle(); ?></strong>
     (<?php echo $session->getPeriode(); ?>) est actuellement à l'état
diff --git a/module/Formation/view/formation/session/index.phtml b/module/Formation/view/formation/session/index.phtml
index efd9051acbc569fdaccff3c811333f79e4bc85f4..ca99e8893da11995de40579dfe483da5874200a6 100644
--- a/module/Formation/view/formation/session/index.phtml
+++ b/module/Formation/view/formation/session/index.phtml
@@ -38,7 +38,7 @@ $canVoir = $this->isAllowed(FormationPrivileges::getResourceId(FormationPrivileg
 
 <?php echo $this->messenger()->addMessagesFromFlashMessenger(); ?>
 
-<?php echo $this->formationInstanceArray($instances); ?>
+<?php echo $this->formationInstanceArray($instances, ['id' => 'sessions']); ?>
 
 <script>
     $(function() {
diff --git a/module/Formation/view/formation/session/partial/inscrits.phtml b/module/Formation/view/formation/session/partial/inscrits.phtml
index abfa131b21c1f1677d286381909af22736abedcd..598538596e64b580ca2c693f401e48f22aa9b2e5 100644
--- a/module/Formation/view/formation/session/partial/inscrits.phtml
+++ b/module/Formation/view/formation/session/partial/inscrits.phtml
@@ -34,6 +34,8 @@ $canSupprimerInscription = $this->isAllowed(FormationinstancePrivileges::getReso
 
 $urlRetour = $this->url('session/afficher', ['session' => $instance->getId()], ['fragment' => 'inscriptions'], true);
 
+$canNotifierValideur = $this->isAllowed(FormationinstancePrivileges::getResourceId(FormationinstancePrivileges::FORMATIONINSTANCE_GERER_INSCRIPTION));
+$canNotifierInscrit = $this->isAllowed(FormationinstancePrivileges::getResourceId(FormationinstancePrivileges::FORMATIONINSTANCE_GERER_INSCRIPTION));
 
 $liste = $instance->getListeDisponible();
 $principaleComplete = $instance->isListePrincipaleComplete();
@@ -43,6 +45,21 @@ $inscriptions = $instance->getInscriptions()
 
 ?>
 
+<?php /** @see \Formation\Controller\SessionController::notifierResponsablePourValidationAction() */ ?>
+<a href="<?php echo $this->url('session/notifier-responsable-pour-validation', ['session' => $instance->getId()], []); ?>"
+   class="btn btn-primary ajax-modal"
+>
+    <span class="icon icon-notifier"></span>
+    Rappel de la demande de validation aux valideur·euses
+</a>
+<?php /** @see \Formation\Controller\SessionController::notifierInscritAction() */ ?>
+<a href="<?php echo $this->url('session/notifier-inscrit', ['session' => $instance->getId()], []); ?>"
+   class="btn btn-primary ajax-modal"
+>
+    <span class="icon icon-notifier"></span>
+    Notifier les inscrit·es
+</a>
+
 <div class="row">
     <div class="col-md-6">
         <h2>
diff --git a/readme.md b/readme.md
index 7ab5dbe121e68d2779b6bb7c5ef9ce0f31b2ec85..89fe76310cb53d234344f04486f2be91b9436de0 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,67 @@
-# Application Mes Formations
+ Mes Formations
+ ===
+---
+
+**Mes Formations** est une application web dédiée à la gestion dématérialisée des formations professionnelles. Elle permet de centraliser et de simplifier le processus de gestion des formations, qu'elles soient rattachées à des plans de formation ou issues de demandes individuelles.
+
+Grâce à un circuit de validation entièrement en ligne, l'application facilite la coordination entre les agents, les valideurs, et les responsables de structure tout en intégrant un système de notifications pour assurer le suivi des demandes et décisions.
+
+L'application propose également des interfaces intuitives pour la gestion des historiques de formation, permettant :
+* Aux agents de consulter leurs parcours de formation.
+* Aux valideurs et responsables d'accéder aux données consolidées pour un suivi précis et une prise de décision éclairée.
+
+En offrant une solution complète et dématérialisée, **Mes Formations** optimise la gestion administrative des formations tout en renforçant la transparence et la traçabilité. 
+
+**Mes Formations** est développée par l'Université de Caen Normandie dans une démarche collaborative et innovante. 
+En tant qu'application open-source, elle est distribuée sous la licence CeCILL, garantissant ainsi une utilisation libre, des possibilités d'adaptation, et un partage dans le respect des droits des utilisateurs. 
+
+# Changements 
+
+## 1.0.5 (06/12/2024)
+
+* Transformation des émargements en un template 
+* Ajout de la notification de rappel au responsable qui n'aurait pas validé ou refusé la demande de formation
+* Ajout de la possibilité de notifier les inscrit·es pour les prevenir d'un changement ou d'une demande particulière
+* Poursuite des changements des tableaux de bord des gestionnaires
+* Modification du comportement du bouton "changer état" des sessions pour ne pas provoquer de notification
+* Ajout de rapport pour les opérations faisant évoluer les états des sessions
+
+## 1.0.4 (29/11/2024)
+
+* Amélioration des interfaces pour les gestionnaires de formations
+* Ajout d'écrans et d'indicateurs pour la gestion des désistements
+* Ajout de la possibilité de fournir un motif d'annulation d'une session (et de l'exploiter pour les notifications)
+* Ajout d'export des personnes formées
+* Ajout de blocage des agents déjà inscrit à des formations à la même date et du nombre d'inscrits
+* Affichage du lieu (général) des formations sur les écrans listant les sessions
+* Correction des problèmes de changement d'état des inscriptions à l'annulation d'une session
+
+## 1.0.3 (18/11/2024)
+
+* Ajout d'écran pour les référent·es de domaine de formation : insciptions et sessions
+* Correction de la gestion des justifications et amélioration de leurs affichages
+* Amélioration des écrans des valideur·euses et des responsables de structure
+* Possibilité de révoquer les chaînes de validation remontant des SI (via les synchronisations)
+
+## 1.0.2 (13/11/2024)
+
+* Correction d'une mention oubliée à EMC2 dans le pied de page des documents générés
+* Possibilité de contrôler du logo de l'application via un paramêtre
+* Amélioration de la visibilité des inscrits à une formation et des privileges pour l'affichage des sessions
+* Correction des destinataires de la notification de validation
+* Ajout de filtrage sur les écrans des historiques de formations
+
+## 1.0.1 (06/11/2024)
+
+* Correction du bug tentant des référents mal déclarés
+* Amélioration de divers affichages remontés comme non pratique par les premiers usagers
+
+## 1.0.0 (30/10/2024)
+
+Première version livrant la partie *formation du plan de formation*
+
+
+# Liens utiles
 
 - [Indicateurs](documentation/docs/indicateurs.md)
 - [Template](documentation/docs/renderer.md)