From d0de1e514186adb7cf91c667cdfae06a6940dbe0 Mon Sep 17 00:00:00 2001
From: Jean-Philippe Metivier <jean-philippe.metivier@unicaen.fr>
Date: Mon, 18 Nov 2024 15:58:47 +0100
Subject: [PATCH] Motif d'annulation de session

---
 database/script/init_template.sql             |  3 +-
 .../config/merged/session.config.php          |  6 +++
 .../Controller/SessionController.php          | 27 ++++++++--
 .../Controller/SessionControllerFactory.php   |  4 ++
 .../Formation.Entity.Db.Session.dcm.xml       |  3 +-
 .../src/Formation/Entity/Db/Session.php       | 12 +++++
 .../Form/Annulation/AnnulationForm.php        | 51 +++++++++++++++++++
 .../Annulation/AnnulationFormAwareTrait.php   | 19 +++++++
 .../Form/Annulation/AnnulationFormFactory.php | 25 +++++++++
 .../Form/Annulation/AnnulationHydrator.php    | 27 ++++++++++
 .../Annulation/AnnulationHydratorFactory.php  | 14 +++++
 .../Helper/SessionInformationsViewHelper.php  |  1 -
 .../Helper/partial/session-informations.phtml | 11 ++++
 .../view/formation/session/afficher.phtml     |  2 +-
 14 files changed, 198 insertions(+), 7 deletions(-)
 create mode 100644 module/Formation/src/Formation/Form/Annulation/AnnulationForm.php
 create mode 100644 module/Formation/src/Formation/Form/Annulation/AnnulationFormAwareTrait.php
 create mode 100644 module/Formation/src/Formation/Form/Annulation/AnnulationFormFactory.php
 create mode 100644 module/Formation/src/Formation/Form/Annulation/AnnulationHydrator.php
 create mode 100644 module/Formation/src/Formation/Form/Annulation/AnnulationHydratorFactory.php

diff --git a/database/script/init_template.sql b/database/script/init_template.sql
index 98be940c..8f007031 100644
--- a/database/script/init_template.sql
+++ b/database/script/init_template.sql
@@ -41,7 +41,8 @@ INSERT INTO unicaen_renderer_macro (code, description, variable_name, methode_na
     ('Url#GestionDemandesExternes', '<p>Retourne le lien vers la page de gestion des demandes externes</p>', 'UrlService', 'getUrlGestionDemandesExternes'),
     ('Url#MesFormations', '<p>Retourne l''url de la page des formations réalisées d''un·e agent·e</p>', 'UrlService', 'getUrlMesFormations'),
     ('Url#PlanDeFormation', '<p>Fourni un lieu vers la page des plans de formation courants</p>', 'UrlService', 'getUrlPlanDeFormation'),
-    ('Url#ValidateurDemandesExternes', '<p>Retourne l''url associé à la page mes agents avec l''onglet ''Demande à titre individuel'' sélectionné</p>', 'UrlService', 'getUrlValidateurDemandesExternes')
+    ('Url#ValidateurDemandesExternes', '<p>Retourne l''url associé à la page mes agents avec l''onglet ''Demande à titre individuel'' sélectionné</p>', 'UrlService', 'getUrlValidateurDemandesExternes'),
+    ('SESSION#MotifAnnulation', '<p>Affiche le motif d''annulation</p>', 'session', 'getMotifAnnulation')
 ;
 
 INSERT INTO unicaen_renderer_template (code, description, document_type, document_sujet, document_corps, document_css, namespace) VALUES ('ENQUETE_EXPLICATION', '<p>Texte précisant le caractère anonyme et <em>facultatif</em> de l''enquête</p>', 'texte', 'À propos des formulaires de retour d''expérience', e'<p>Ces formulaires sont anonymes et si vous ne souhaitez pas fournir de réponse à une des questions de l\'enquête vous pouvez sélectionner la réponse "<em>Sans avis</em>".</p>
diff --git a/module/Formation/config/merged/session.config.php b/module/Formation/config/merged/session.config.php
index 24b4a17e..3f597a60 100644
--- a/module/Formation/config/merged/session.config.php
+++ b/module/Formation/config/merged/session.config.php
@@ -9,6 +9,10 @@ use Formation\Controller\SessionControllerFactory;
 use Formation\Controller\InscriptionController;
 use Formation\Event\NotificationNouvellesSessions\NotificationNouvellesSessionsEvent;
 use Formation\Event\NotificationNouvellesSessions\NotificationNouvellesSessionsEventFactory;
+use Formation\Form\Annulation\AnnulationForm;
+use Formation\Form\Annulation\AnnulationFormFactory;
+use Formation\Form\Annulation\AnnulationHydrator;
+use Formation\Form\Annulation\AnnulationHydratorFactory;
 use Formation\Form\Session\SessionForm;
 use Formation\Form\Session\SessionFormFactory;
 use Formation\Form\Session\SessionHydrator;
@@ -479,11 +483,13 @@ return [
     ],
     'form_elements' => [
         'factories' => [
+            AnnulationForm::class => AnnulationFormFactory::class,
             SessionForm::class => SessionFormFactory::class,
         ],
     ],
     'hydrators' => [
         'factories' => [
+            AnnulationHydrator::class => AnnulationHydratorFactory::class,
             SessionHydrator::class => SessionHydratorFactory::class,
         ],
     ],
diff --git a/module/Formation/src/Formation/Controller/SessionController.php b/module/Formation/src/Formation/Controller/SessionController.php
index 45f99169..9e77bef1 100644
--- a/module/Formation/src/Formation/Controller/SessionController.php
+++ b/module/Formation/src/Formation/Controller/SessionController.php
@@ -4,6 +4,7 @@ namespace Formation\Controller;
 
 use DateTime;
 use Formation\Entity\Db\Inscription;
+use Formation\Form\Annulation\AnnulationFormAwareTrait;
 use Formation\Form\SelectionFormateur\SelectionFormateurFormAwareTrait;
 use Formation\Form\SelectionGestionnaire\SelectionGestionnaireFormAwareTrait;
 use Formation\Form\Session\SessionFormAwareTrait;
@@ -50,6 +51,7 @@ class SessionController extends AbstractActionController
     use ResultatServiceAwareTrait;
     use UserServiceAwareTrait;
 
+    use AnnulationFormAwareTrait;
     use SelectionFormateurFormAwareTrait;
     use SelectionGestionnaireFormAwareTrait;
     use SessionFormAwareTrait;
@@ -337,11 +339,30 @@ class SessionController extends AbstractActionController
         return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
     }
 
-    public function annulerAction(): Response
+    public function annulerAction(): ViewModel
     {
         $session = $this->getSessionService()->getRequestedSession($this);
-        $this->getSessionService()->annuler($session);
-        return $this->redirect()->toRoute('session/afficher', ['session' => $session->getId()], [], true);
+
+        $form = $this->getAnnulationForm();
+        $form->setAttribute('action', $this->url()->fromRoute('session/annuler', ['session' => $session->getId()] ,[], true));
+        $form->bind($session);
+
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            $data = $request->getPost();
+            $form->setData($data);
+            if ($form->isValid()) {
+                $this->getSessionService()->annuler($session);
+                exit();
+            }
+        }
+
+        $vm = new ViewModel([
+            'title' => "Annulation de la session",
+            'form' => $form,
+        ]);
+        $vm->setTemplate('default/default-form');
+        return $vm;
     }
 
     public function reouvrirAction(): Response
diff --git a/module/Formation/src/Formation/Controller/SessionControllerFactory.php b/module/Formation/src/Formation/Controller/SessionControllerFactory.php
index 2763b52b..af2f710c 100644
--- a/module/Formation/src/Formation/Controller/SessionControllerFactory.php
+++ b/module/Formation/src/Formation/Controller/SessionControllerFactory.php
@@ -2,6 +2,7 @@
 
 namespace Formation\Controller;
 
+use Formation\Form\Annulation\AnnulationForm;
 use Formation\Form\SelectionFormateur\SelectionFormateurForm;
 use Formation\Form\SelectionGestionnaire\SelectionGestionnaireForm;
 use Formation\Form\Session\SessionForm;
@@ -63,10 +64,12 @@ class SessionControllerFactory
         $userService = $container->get(UserService::class);
 
         /**
+         * @var AnnulationForm $annulationForm
          * @var SelectionFormateurForm $selectionFormateurForm
          * @var SelectionGestionnaireForm $selectionGestionnaireForm
          * @var SessionForm $sessionForm
          */
+        $annulationForm = $container->get('FormElementManager')->get(AnnulationForm::class);
         $sessionForm = $container->get('FormElementManager')->get(SessionForm::class);
         $selectionFormateurForm = $container->get('FormElementManager')->get(SelectionFormateurForm::class);
         $selectionGestionnaireForm = $container->get('FormElementManager')->get(SelectionGestionnaireForm::class);
@@ -86,6 +89,7 @@ class SessionControllerFactory
         $controller->setResultatService($resultatService);
         $controller->setSessionService($sessionService);
         $controller->setUserService($userService);
+        $controller->setAnnulationForm($annulationForm);
         $controller->setSessionForm($sessionForm);
         $controller->setSelectionFormateurForm($selectionFormateurForm);
         $controller->setSelectionGestionnaireForm($selectionGestionnaireForm);
diff --git a/module/Formation/src/Formation/Entity/Db/Mapping/Formation.Entity.Db.Session.dcm.xml b/module/Formation/src/Formation/Entity/Db/Mapping/Formation.Entity.Db.Session.dcm.xml
index 55dd3c80..2b6285e0 100644
--- a/module/Formation/src/Formation/Entity/Db/Mapping/Formation.Entity.Db.Session.dcm.xml
+++ b/module/Formation/src/Formation/Entity/Db/Mapping/Formation.Entity.Db.Session.dcm.xml
@@ -16,7 +16,8 @@
         <field name="lieu"                      type="string" length="256"      column="lieu"                        nullable="true"/>
         <field name="type"                      type="string" length="256"      column="type"                        nullable="true"/>
         <field name="autoInscription"           type="boolean"                  column="auto_inscription"            nullable="true"/>
-        <field name="complement"                type="string" length="4096"     column="complement"                  nullable="true"/>
+        <field name="complement"                type="text"                     column="complement"                  nullable="true"/>
+        <field name="motifAnnulation"           type="text"                     column="motif_annulation"                  nullable="true"/>
 
         <one-to-many field="journees"       target-entity="Formation\Entity\Db\Seance"    mapped-by="instance"/>
         <one-to-many field="inscriptions"   target-entity="Formation\Entity\Db\Inscription"    mapped-by="session"/>
diff --git a/module/Formation/src/Formation/Entity/Db/Session.php b/module/Formation/src/Formation/Entity/Db/Session.php
index 5142ede6..c60a72df 100644
--- a/module/Formation/src/Formation/Entity/Db/Session.php
+++ b/module/Formation/src/Formation/Entity/Db/Session.php
@@ -72,6 +72,7 @@ class Session implements
 
     private ?SessionParametre $parametre = null;
 
+    private ?string $motifAnnulation = null;
 
 
     public function __construct()
@@ -142,6 +143,17 @@ class Session implements
         return $this;
     }
 
+    public function getMotifAnnulation(): ?string
+    {
+        return $this->motifAnnulation;
+    }
+
+    public function setMotifAnnulation(?string $motifAnnulation): void
+    {
+        $this->motifAnnulation = $motifAnnulation;
+    }
+
+
     /** PLACE SUR LISTE  **********************************************************************************************/
 
     /**
diff --git a/module/Formation/src/Formation/Form/Annulation/AnnulationForm.php b/module/Formation/src/Formation/Form/Annulation/AnnulationForm.php
new file mode 100644
index 00000000..e7a05830
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Annulation/AnnulationForm.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Formation\Form\Annulation;
+
+use Laminas\Form\Element\Button;
+use Laminas\Form\Element\Textarea;
+use Laminas\Form\Form;
+use Laminas\InputFilter\Factory;
+
+class AnnulationForm extends Form
+{
+    public function init() : void
+    {
+        //description
+        $this->add([
+            'name' => 'motif_annulation',
+            'type' => Textarea::class,
+            'options' => [
+                'label' => "Motif d'annulation <span class='icon icon-obligatoire' title='champ obligatoire'></span> :",
+                'label_options' => ['disable_html_escape' => true,],
+                'label_attributes' => [
+                    'class' => 'control-label',
+                ],
+            ],
+            'attributes' => [
+                'id' => 'motif_annulation',
+                'class' => 'tinymce',
+            ]
+        ]);
+        //bouton
+        $this->add([
+            'type' => Button::class,
+            'name' => 'bouton',
+            'options' => [
+                'label' => '<i class="fas fa-save"></i> Enregistrer',
+                'label_options' => [
+                    'disable_html_escape' => true,
+                ],
+            ],
+            'attributes' => [
+                'type' => 'submit',
+                'class' => 'btn btn-success',
+            ],
+        ]);
+        $this->setInputFilter((new Factory())->createInputFilter([
+            'motif_annulation' => [ 'require' => true,  ],
+        ]));
+
+    }
+
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Annulation/AnnulationFormAwareTrait.php b/module/Formation/src/Formation/Form/Annulation/AnnulationFormAwareTrait.php
new file mode 100644
index 00000000..f1e8a694
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Annulation/AnnulationFormAwareTrait.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Formation\Form\Annulation;
+
+trait AnnulationFormAwareTrait {
+
+    private AnnulationForm $annulationForm;
+
+    public function getAnnulationForm(): AnnulationForm
+    {
+        return $this->annulationForm;
+    }
+
+    public function setAnnulationForm(AnnulationForm $annulationForm): void
+    {
+        $this->annulationForm = $annulationForm;
+    }
+
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Annulation/AnnulationFormFactory.php b/module/Formation/src/Formation/Form/Annulation/AnnulationFormFactory.php
new file mode 100644
index 00000000..04eec0de
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Annulation/AnnulationFormFactory.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Formation\Form\Annulation;
+
+use Laminas\Form\Annotation\Hydrator;
+use Psr\Container\ContainerExceptionInterface;
+use Psr\Container\ContainerInterface;
+use Psr\Container\NotFoundExceptionInterface;
+
+class AnnulationFormFactory {
+
+    /**
+     * @throws ContainerExceptionInterface
+     * @throws NotFoundExceptionInterface
+     */
+    public function __invoke(ContainerInterface $containerInterface): AnnulationForm
+    {
+        /** @var AnnulationHydrator $hydrator */
+        $hydrator = $containerInterface->get('HydratorManager')->get(AnnulationHydrator::class);
+
+        $form = new AnnulationForm();
+        $form->setHydrator($hydrator);
+        return $form;
+    }
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Annulation/AnnulationHydrator.php b/module/Formation/src/Formation/Form/Annulation/AnnulationHydrator.php
new file mode 100644
index 00000000..ce4e510f
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Annulation/AnnulationHydrator.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Formation\Form\Annulation;
+
+use Formation\Entity\Db\Session;
+use Laminas\Hydrator\HydratorInterface;
+
+class AnnulationHydrator implements HydratorInterface {
+
+    public function extract(object $object): array
+    {
+        /** @var Session $object */
+        $data = [
+            'motif_annulation' => $object->getMotifAnnulation(),
+        ];
+        return $data;
+    }
+
+    public function hydrate(array $data, object $object): object
+    {
+        $motif = (isset($data['motif_annulation']) AND trim($data['motif_annulation']) !== '') ? trim($data['motif_annulation']) : null;
+
+        /** @var Session $object */
+        $object->setMotifAnnulation($motif);
+        return $object;
+    }
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Form/Annulation/AnnulationHydratorFactory.php b/module/Formation/src/Formation/Form/Annulation/AnnulationHydratorFactory.php
new file mode 100644
index 00000000..f96dd117
--- /dev/null
+++ b/module/Formation/src/Formation/Form/Annulation/AnnulationHydratorFactory.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Formation\Form\Annulation;
+
+use Psr\Container\ContainerInterface;
+
+class AnnulationHydratorFactory {
+
+    public function __invoke(ContainerInterface $container): AnnulationHydrator
+    {
+        $hydrator = new AnnulationHydrator();
+        return $hydrator;
+    }
+}
\ No newline at end of file
diff --git a/module/Formation/src/Formation/View/Helper/SessionInformationsViewHelper.php b/module/Formation/src/Formation/View/Helper/SessionInformationsViewHelper.php
index d8902d64..ceb86c91 100644
--- a/module/Formation/src/Formation/View/Helper/SessionInformationsViewHelper.php
+++ b/module/Formation/src/Formation/View/Helper/SessionInformationsViewHelper.php
@@ -2,7 +2,6 @@
 
 namespace Formation\View\Helper;
 
-use Formation\Entity\Db\FormationInstance;
 use Formation\Entity\Db\Session;
 use Laminas\View\Helper\AbstractHelper;
 use Laminas\View\Helper\Partial;
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 34b410c5..8a479325 100644
--- a/module/Formation/src/Formation/View/Helper/partial/session-informations.phtml
+++ b/module/Formation/src/Formation/View/Helper/partial/session-informations.phtml
@@ -10,6 +10,7 @@
 use Application\Entity\Db\Interfaces\HasSourceInterface;
 use DemandeExterne\Provider\Privilege\DemandeexternePrivileges;
 use Formation\Entity\Db\Session;
+use Formation\Provider\Etat\SessionEtats;
 
 
 $gestionnaires = $session->getGestionnaires();
@@ -24,6 +25,16 @@ $displayListe = (!isset($options['display-liste']) OR $options['display-liste']
     <dl class="row">
         <dt class="col-md-3"> État</dt>
         <dd class="col-md-9">  <?php echo ($session->getEtatActif()) ? $this->etattype($session->getEtatActif()->getType(), ['display-categorie' => false]) . " " . $session->getEtatActif()->getType()->getLibelle() : "N.C."; ?> </dd>
+        <?php if ($session->isEtatActif(SessionEtats::ETAT_SESSION_ANNULEE)): ?>
+            <dt class="col-md-3"> Motif d'annulation</dt>
+            <dd class="col-md-9">
+                <?php if ($session->getMotifAnnulation()): ?>
+                    <?php echo $session->getMotifAnnulation(); ?>
+                <?php else : ?>
+                    <em>Aucun motif connu</em>
+                <?php endif; ?>
+            </dd>
+        <?php endif; ?>
         <?php if ($session->getComplement() !== null) : ?>
             <dt class="col-md-3"> Compléments</dt>
             <dd class="col-md-9"> <?php echo $session->getComplement(); ?></dd>
diff --git a/module/Formation/view/formation/session/afficher.phtml b/module/Formation/view/formation/session/afficher.phtml
index 36962f89..3bb6045f 100644
--- a/module/Formation/view/formation/session/afficher.phtml
+++ b/module/Formation/view/formation/session/afficher.phtml
@@ -178,7 +178,7 @@ $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">
+                            class="btn btn-danger ajax-modal" data-event="modification">
                         Annuler la session
                     </a>
                 <?php else : ?>
-- 
GitLab