diff --git a/database/migration/1.0.5.sql b/database/migration/1.0.5.sql index d036622e58a1fd6c0dde58defa5c44550c12bb85..52bc52a47bdeb77af9472114e55af0c8f6362feb 100644 --- a/database/migration/1.0.5.sql +++ b/database/migration/1.0.5.sql @@ -1,3 +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/Formation/config/merged/session.config.php b/module/Formation/config/merged/session.config.php index 3aefc05f148efd3d5cc3487536659bbd44ef3ba4..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; @@ -112,6 +116,7 @@ return [ 'changer-etat', 'notifier-responsable-pour-validation', + 'notifier-inscrit', ], 'privileges' => [ FormationinstancePrivileges::FORMATIONINSTANCE_GERER_INSCRIPTION, @@ -396,6 +401,16 @@ return [ ], ], ], + '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, @@ -498,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/SessionController.php b/module/Formation/src/Formation/Controller/SessionController.php index 6308b78cfe65059edf6798c192d3dfc4d00ddc55..92937d8cc0b08a5884e2a49c4c7162f11bb6b12b 100644 --- a/module/Formation/src/Formation/Controller/SessionController.php +++ b/module/Formation/src/Formation/Controller/SessionController.php @@ -5,6 +5,7 @@ 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; @@ -55,6 +56,7 @@ class SessionController extends AbstractActionController use UserServiceAwareTrait; use AnnulationFormAwareTrait; + use NotificationFormAwareTrait; use SelectionFormateurFormAwareTrait; use SelectionGestionnaireFormAwareTrait; use SessionFormAwareTrait; @@ -609,6 +611,66 @@ class SessionController extends AbstractActionController 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->getNotificationService()->getMailService()->sendMail($adresse, $sujet, $corps,'Formation'):null; + } + + $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 4473141cdde0d0749b26c74154c2f28371f4f393..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; @@ -68,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); @@ -94,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/Session.php b/module/Formation/src/Formation/Entity/Db/Session.php index ab9612bc2166707e81a1a33eb9651b6c5c04123f..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[] */ 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/view/formation/session/partial/inscrits.phtml b/module/Formation/view/formation/session/partial/inscrits.phtml index 24160402731e1d9708adde79771d1fe1b445b46f..598538596e64b580ca2c693f401e48f22aa9b2e5 100644 --- a/module/Formation/view/formation/session/partial/inscrits.phtml +++ b/module/Formation/view/formation/session/partial/inscrits.phtml @@ -35,6 +35,7 @@ $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(); @@ -46,11 +47,18 @@ $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" data-event="modification" + 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">