Commit cea33e35 authored by Antony Le Courtes's avatar Antony Le Courtes
Browse files

Synchronisation du source code de l'intervenant lors d'une PEC/REN Siham (#50845)

parent 48b568ba
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ return [
        'actif'       => AppConfig::get('export-rh', 'actif') ? AppConfig::get('export-rh', 'actif') : false,
        'connecteur'  => AppConfig::get('export-rh', 'connecteur') ? AppConfig::get('export-rh', 'connecteur') : '',
        'sync-code'   => AppConfig::get('export-rh', 'sync-code') ? AppConfig::get('export-rh', 'sync-code') : false,
        'sync-source' => AppConfig::get('export-rh', 'sync-source') ? AppConfig::get('export-rh', 'sync-source') : '',
    ],

];
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ suivantes :
        'actif'      => true,//False pour désactiver l'export RH
        'connecteur' => 'siham',//Le nom du connecteur dont vous avez besoin, pour le moment seul le connecteur SIHAM a été développé.
        'sync-code'  => false,//Permet de venir forcer le code de l'intervenant avec le matricule siham en retour d'un renouvellement ou d'une prise en charge
        'sync-source'  => '',//Code de la source à remplacer après la synchronisation
    ],
```

+34 −16
Original line number Diff line number Diff line
@@ -2,9 +2,11 @@

# Principe

Le module ExportRh de OSE permet de rendre une disponible au sein de l'applicatif une fonctionnalité d'export des données intervenants dans le SI RH. Pour le moment, seul SIHAM est pris en charge par ce module.
Le module ExportRh de OSE permet de rendre une disponible au sein de l'applicatif une fonctionnalité d'export des données intervenants dans le SI RH. Pour le
moment, seul SIHAM est pris en charge par ce module.

Si vous activez le module export et que vous avez SIHAM, vous pourrez pour un intervenant, vacataire et uniquement pour l'année universitaire en cours, lancer une prise en charge ou un renouvellement directement dans SIHAM à partir de OSE.
Si vous activez le module export et que vous avez SIHAM, vous pourrez pour un intervenant, vacataire et uniquement pour l'année universitaire en cours, lancer
une prise en charge ou un renouvellement directement dans SIHAM à partir de OSE.

A noter que le renouvellement, ou la prise en charge SIHAM n'est possible que si le contrat OSE a une date de retour signée.

@@ -12,7 +14,8 @@ A noter que le renouvellement, ou la prise en charge SIHAM n'est possible que si

## Privilège et accès à l'export

Pour accéder aux écrans d'export RH, il faut vous rendre au niveau de la fiche de l'intervenant, si vous avez le privilège associé, vous verrez un nouvel onglet Export RH :
Pour accéder aux écrans d'export RH, il faut vous rendre au niveau de la fiche de l'intervenant, si vous avez le privilège associé, vous verrez un nouvel onglet
Export RH :

![Fiche export RH](fiche-export.png)

@@ -24,53 +27,68 @@ Voici le nouveau privilège à donner aux rôles :

On appelle prise en charge (PEC), le fait d'exporter vers SIHAM un intervenant inconnu du SI RH. Un matricule va être créé et attribué à cet intervenant.

Pour une PEC, les données personnelles sont injectées dans SIHAM pour la première fois, on parle bien des données issues du dossier de l'intervenant et non pas celles de la fiche intervenant :
Pour une PEC, les données personnelles sont injectées dans SIHAM pour la première fois, on parle bien des données issues du dossier de l'intervenant et non pas
celles de la fiche intervenant :

![Données personnelles mises à jour](pec-donnees.png)

Lors d'une prise en charge, OSE va créer un nouvelle affectation pour l'année universitaire en cours, et créer le statut, le type d'emploi, la position administrative et le service dans SIHAM, le tout en auto validé dans SIHAM.
Lors d'une prise en charge, OSE va créer un nouvelle affectation pour l'année universitaire en cours, et créer le statut, le type d'emploi, la position
administrative et le service dans SIHAM, le tout en auto validé dans SIHAM.

Toutes ces informations sont paramétrables à l'aide du formulaire personnalisé SIHAM :

![Formulaire SIHAM](formulaire-connecteur-siham.png)

Si vous avez activé le paramètre 'sync-code', la prise en charge va venir remplacer le code de l'intervenant par le matricule SIHAM. Ce paramètre est utile surtout dans le cas où vous proposez des comptes locaux à ose pour vos vacataires. (Attention, dans ce cas le connecteur MV_INTERVENANT.sql qui
alimente OSE avec les intervenants doit bien évidement utiliser le matricule SIHAM comme CODE intervenant afin que la synchronisationne ne produise pas de doublon)
Si vous avez activé le paramètre 'sync-code', la prise en charge va venir remplacer le code de l'intervenant par le matricule SIHAM. Ce paramètre est utile
surtout dans le cas où vous proposez des comptes locaux à ose pour vos vacataires. (Attention, dans ce cas le connecteur MV_INTERVENANT.sql qui
alimente OSE avec les intervenants doit bien évidement utiliser le matricule SIHAM comme CODE intervenant afin que la synchronisationne ne produise pas de
doublon)

Idem pour le paramètre 'sync-source',forcera la source de l'intervenant avec le code source correspondant.

## Renouvellement d'un intervenant (REN)

On appelle renouvellement (REN), le fait d'exporter vers SIHAM un intervenant déjà connu du SI RH.

Le renouvellement va d'abord mettre à jour certaines données personnelles de l'intervenant, à noter que vous pourrez désactiver la synchronisation de certaines données en décochant les lignes :
Le renouvellement va d'abord mettre à jour certaines données personnelles de l'intervenant, à noter que vous pourrez désactiver la synchronisation de certaines
données en décochant les lignes :

![Données personnelles mises à jour](renouvellement-donnees.png)

**Attention, les WS SIHAM de l'AMUE sont buggés pour la mise à jour des coordonnées bancaires lors d'un renouvellement, il faudra donc les mettre à jour manuellement si nécessaire. Une demande d'assistance est en cours (mettre le lien ici)**
**Attention, les WS SIHAM de l'AMUE sont buggés pour la mise à jour des coordonnées bancaires lors d'un renouvellement, il faudra donc les mettre à jour
manuellement si nécessaire. Une demande d'assistance est en cours (mettre le lien ici)**

De la même façon, OSE va créer un nouvelle affectation pour l'année universitaire en cours, et mettre à jour le statut, le type d'emploi, la position administrative et le service dans SIHAM, le tout en auto validé dans SIHAM.
De la même façon, OSE va créer un nouvelle affectation pour l'année universitaire en cours, et mettre à jour le statut, le type d'emploi, la position
administrative et le service dans SIHAM, le tout en auto validé dans SIHAM.

![Formulaire SIHAM](formulaire-connecteur-siham.png)

Si vous avez activé le paramètre 'sync-code', le renouvellement va venir remplacer le code de l'intervenant par le matricule SIHAM. Ce paramètre est utile surtout dans le cas où vous proposez des comptes locaux ose pour vos vacataires. (Attention, dans ce cas le connecteur MV_INTERVENANT.sql qui
alimente OSE avec les intervenants doit bien évidement utiliser le matricule SIHAM comme CODE intervenant afin que la synchronisationne ne produise pas de doublon)
Si vous avez activé le paramètre 'sync-code', le renouvellement va venir remplacer le code de l'intervenant par le matricule SIHAM. Ce paramètre est utile
surtout dans le cas où vous proposez des comptes locaux ose pour vos vacataires. (Attention, dans ce cas le connecteur MV_INTERVENANT.sql qui
alimente OSE avec les intervenants doit bien évidement utiliser le matricule SIHAM comme CODE intervenant afin que la synchronisationne ne produise pas de
doublon)

## Suite à la PEC ou au REN

Une fois la prise en charge ou le renouvellement effectué via OSE, vous retrouverez le dossier de l'agent à jour, il ne vous restera plus qu'à le contractualiser manuellement dans SIHAM.
Une fois la prise en charge ou le renouvellement effectué via OSE, vous retrouverez le dossier de l'agent à jour, il ne vous restera plus qu'à le
contractualiser manuellement dans SIHAM.

![SIHAM](siham.png)

## Synchronisation

Si l'intervenant possède déjà une affectation sur l'année en cours, vous ne pourrez donc pas lancer une PEC ou un REN, mais vous aurez quand même la possiblité de synchroniser les quelques données personnelles de OSE vers SIHAM.
Si l'intervenant possède déjà une affectation sur l'année en cours, vous ne pourrez donc pas lancer une PEC ou un REN, mais vous aurez quand même la possiblité
de synchroniser les quelques données personnelles de OSE vers SIHAM.

**Attention, les WS SIHAM de l'AMUE sont buggés pour la mise à jour des coordonnées bancaires lors d'une synchronisation, il faudra donc les mettre à jour manuellement si nécessaire. Une demande d'assistance est en cours (mettre le lien ici)**
**Attention, les WS SIHAM de l'AMUE sont buggés pour la mise à jour des coordonnées bancaires lors d'une synchronisation, il faudra donc les mettre à jour
manuellement si nécessaire. Une demande d'assistance est en cours (mettre le lien ici)**

## Indicateur

Un nouvel indicateur situé dans la rubrique contrat des indicateurs (indicateur N°380), vous donne la liste des vacataires à prendre en charge ou à renouveller.

Il n'est utilisable que sur l'année universitaire en cours, car comme dit précédement, seul les vacataires de l'année universitaire en cours sont concernés par le module ExporRh.
Il n'est utilisable que sur l'année universitaire en cours, car comme dit précédement, seul les vacataires de l'année universitaire en cours sont concernés par
le module ExporRh.

![INDICATEUR](indicateur.png)

+172 −151
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ use Laminas\Hydrator\ClassMethodsHydrator;
use Paiement\Service\MiseEnPaiementIntervenantStructureServiceAwareTrait;
use Paiement\Service\MiseEnPaiementServiceAwareTrait;
use RuntimeException;
use UnicaenCode\Service\Traits\ConfigServiceAwareTrait;


/**
@@ -90,79 +91,31 @@ class IntervenantService extends AbstractEntityService


    /**
     * Retourne l'intervenant de l'année précédente
     *
     * @param Intervenant $intervenant
     * @param int         $anneeDiff
     *
     * @return Intervenant|null
     */
    public function getPrecedent(Intervenant $intervenant, int $anneeDiff = -1): ?Intervenant
    {
        $code        = $intervenant->getCode();
        $anneeId     = $this->getServiceContext()->getAnnee()->getId() + $anneeDiff;
        $statutId    = $intervenant->getStatut() ? $intervenant->getStatut()->getId() : null;
        $structureId = $intervenant->getStructure() ? $intervenant->getStructure()->getId() : null;

        $bones = $this->getBones(['CODE' => $code, 'ANNEE_ID' => $anneeId]);

        return $this->bestIntervenantByBones($bones, $code, $anneeId, $statutId, $structureId);
    }



    public function getByCode(string $code): ?Intervenant
    {
        $anneeId     = $this->getServiceContext()->getAnnee()->getId();
        $statutId    = null;
        $structureId = $this->getServiceContext()->getStructure();
        if ($structureId) $structureId = $structureId->getId();

        $bones = $this->getBones(['CODE' => $code, 'ANNEE_ID' => $anneeId]);

        return $this->bestIntervenantByBones($bones, $code, $anneeId, $statutId, $structureId);
    }



    public function getByCodeRh(string $codeRh): ?Intervenant
    {
        $anneeId     = $this->getServiceContext()->getAnnee()->getId();
        $statutId    = null;
        $structureId = $this->getServiceContext()->getStructure();
        if ($structureId) $structureId = $structureId->getId();

        $bones = $this->getBones(['CODE_RH' => $codeRh, 'ANNEE_ID' => $anneeId]);

        return $this->bestIntervenantByBones($bones, $codeRh, $anneeId, null, null);
    }



    /**
     * Retourne les identifiants des données concernés
     *
     * @param string $sourceCode
     * @param Annee  $annee
     * @param string|string[]|null $sourceCode
     * @param integer|null         $anneeId
     *
     * @return Intervenant|null
     * @return integer[]|null
     */
    public function getByUtilisateurCode(string $utilisateurCode): ?Intervenant
    protected function getId ($column, $value, $anneeId = null)
    {
        $anneeId     = $this->getServiceContext()->getAnnee()->getId();
        $statutId    = null;
        $structureId = $this->getServiceContext()->getStructure();
        if ($structureId) $structureId = $structureId->getId();
        if (empty($sourceCode)) return null;

        $bones = $this->getBones(['UTILISATEUR_CODE' => $utilisateurCode, 'ANNEE_ID' => $anneeId]);
        $code  = null;
        foreach ($bones as $bone) {
            if (!$code) $code = $bone['CODE'];
            if ($code != $bone['CODE']) {
                throw new \Exception('Intervenants différents retournés');
        $sql = 'SELECT ID FROM INTERVENANT WHERE ' . $column . ' IN (:value)';
        if ($anneeId) {
            $sql .= ' AND ANNEE_ID = ' . (string)(int)$anneeId;
        }
        $stmt = $this->getEntityManager()->getConnection()->executeQuery(
            $sql,
            ['value' => (array)$value],
            ['value' => \Doctrine\DBAL\Connection::PARAM_INT_ARRAY]
        );
        if ($r = $stmt->fetch()) {
            return (int)$r['ID'];
        } else {
            return null;
        }

        return $this->bestIntervenantByBones($bones, $code, $anneeId, $statutId, $structureId);
    }


@@ -231,33 +184,97 @@ class IntervenantService extends AbstractEntityService



    public function isImportable(Intervenant $intervenant): bool
    private function getIntervenantIdParDefaut (string $code, int $anneeId): ?int
    {
        $connection = $this->getEntityManager()->getConnection();
        if (!$code || !$anneeId) return null;

        $sqlEnabled = "SELECT sync_enabled FROM import_tables WHERE table_name = 'INTERVENANT'";
        $res        = $connection->fetchAssociative($sqlEnabled);
        if (false === $res || '0' == $res['SYNC_ENABLED']) return false;
        $sql  = "SELECT intervenant_id FROM intervenant_par_defaut WHERE intervenant_code = :code AND annee_id = :annee";
        $iDef = $this->getEntityManager()->getConnection()->fetchAllAssociative($sql, ['code' => $code, 'annee' => $anneeId]);
        if (isset($iDef[0]['INTERVENANT_ID'])) {
            return (int)$iDef[0]['INTERVENANT_ID'];
        }

        $sql = "SELECT code FROM src_intervenant WHERE code = :code AND annee_id = :annee";
        $res = $connection->fetchAssociative($sql, ['code' => $intervenant->getCode(), 'annee' => $intervenant->getAnnee()->getId()]);
        return null;
    }

        return ($res !== false) && isset($res['CODE']) && ($intervenant->getCode() == $res['CODE']);


    /**
     * Retourne l'intervenant de l'année précédente
     *
     * @param Intervenant $intervenant
     * @param int         $anneeDiff
     *
     * @return Intervenant|null
     */
    public function getPrecedent (Intervenant $intervenant, int $anneeDiff = -1): ?Intervenant
    {
        $code        = $intervenant->getCode();
        $anneeId     = $this->getServiceContext()->getAnnee()->getId() + $anneeDiff;
        $statutId    = $intervenant->getStatut() ? $intervenant->getStatut()->getId() : null;
        $structureId = $intervenant->getStructure() ? $intervenant->getStructure()->getId() : null;

        $bones = $this->getBones(['CODE' => $code, 'ANNEE_ID' => $anneeId]);

        return $this->bestIntervenantByBones($bones, $code, $anneeId, $statutId, $structureId);
    }



    private function getIntervenantIdParDefaut(string $code, int $anneeId): ?int
    public function getByCodeRh (string $codeRh): ?Intervenant
    {
        if (!$code || !$anneeId) return null;
        $anneeId     = $this->getServiceContext()->getAnnee()->getId();
        $statutId    = null;
        $structureId = $this->getServiceContext()->getStructure();
        if ($structureId) $structureId = $structureId->getId();

        $sql  = "SELECT intervenant_id FROM intervenant_par_defaut WHERE intervenant_code = :code AND annee_id = :annee";
        $iDef = $this->getEntityManager()->getConnection()->fetchAllAssociative($sql, ['code' => $code, 'annee' => $anneeId]);
        if (isset($iDef[0]['INTERVENANT_ID'])) {
            return (int)$iDef[0]['INTERVENANT_ID'];
        $bones = $this->getBones(['CODE_RH' => $codeRh, 'ANNEE_ID' => $anneeId]);

        return $this->bestIntervenantByBones($bones, $codeRh, $anneeId, null, null);
    }

        return null;


    /**
     *
     * @param string $sourceCode
     * @param Annee  $annee
     *
     * @return Intervenant|null
     */
    public function getByUtilisateurCode (string $utilisateurCode): ?Intervenant
    {
        $anneeId     = $this->getServiceContext()->getAnnee()->getId();
        $statutId    = null;
        $structureId = $this->getServiceContext()->getStructure();
        if ($structureId) $structureId = $structureId->getId();

        $bones = $this->getBones(['UTILISATEUR_CODE' => $utilisateurCode, 'ANNEE_ID' => $anneeId]);
        $code  = null;
        foreach ($bones as $bone) {
            if (!$code) $code = $bone['CODE'];
            if ($code != $bone['CODE']) {
                throw new \Exception('Intervenants différents retournés');
            }
        }

        return $this->bestIntervenantByBones($bones, $code, $anneeId, $statutId, $structureId);
    }



    public function isImportable (Intervenant $intervenant): bool
    {
        $connection = $this->getEntityManager()->getConnection();

        $sqlEnabled = "SELECT sync_enabled FROM import_tables WHERE table_name = 'INTERVENANT'";
        $res        = $connection->fetchAssociative($sqlEnabled);
        if (false === $res || '0' == $res['SYNC_ENABLED']) return false;

        $sql = "SELECT code FROM src_intervenant WHERE code = :code AND annee_id = :annee";
        $res = $connection->fetchAssociative($sql, ['code' => $intervenant->getCode(), 'annee' => $intervenant->getAnnee()->getId()]);

        return ($res !== false) && isset($res['CODE']) && ($intervenant->getCode() == $res['CODE']);
    }


@@ -309,36 +326,6 @@ class IntervenantService extends AbstractEntityService



    /**
     * Retourne les identifiants des données concernés
     *
     * @param string|string[]|null $sourceCode
     * @param integer|null         $anneeId
     *
     * @return integer[]|null
     */
    protected function getId($column, $value, $anneeId = null)
    {
        if (empty($sourceCode)) return null;

        $sql = 'SELECT ID FROM INTERVENANT WHERE ' . $column . ' IN (:value)';
        if ($anneeId) {
            $sql .= ' AND ANNEE_ID = ' . (string)(int)$anneeId;
        }
        $stmt = $this->getEntityManager()->getConnection()->executeQuery(
            $sql,
            ['value' => (array)$value],
            ['value' => \Doctrine\DBAL\Connection::PARAM_INT_ARRAY]
        );
        if ($r = $stmt->fetch()) {
            return (int)$r['ID'];
        } else {
            return null;
        }
    }



    /**
     * @param $intervenant Intervenant
     *
@@ -407,28 +394,6 @@ class IntervenantService extends AbstractEntityService



    /**
     * Sauvegarde une entité
     *
     * @param Intervenant $entity
     *
     * @return Intervenant
     * @throws \RuntimeException
     */
    public function save($entity)
    {
        if (!$entity->getSource()) {
            $entity->setSource($this->getServiceSource()->getOse());
        }
        if (!$entity->getAnnee()) {
            $entity->setAnnee($this->getServiceContext()->getAnnee());
        }

        return parent::save($entity);
    }



    /**
     *
     * @param QueryBuilder|null $qb
@@ -603,6 +568,42 @@ class IntervenantService extends AbstractEntityService



    public function getByCode (string $code): ?Intervenant
    {
        $anneeId     = $this->getServiceContext()->getAnnee()->getId();
        $statutId    = null;
        $structureId = $this->getServiceContext()->getStructure();
        if ($structureId) $structureId = $structureId->getId();

        $bones = $this->getBones(['CODE' => $code, 'ANNEE_ID' => $anneeId]);

        return $this->bestIntervenantByBones($bones, $code, $anneeId, $statutId, $structureId);
    }



    /**
     * Sauvegarde une entité
     *
     * @param Intervenant $entity
     *
     * @return Intervenant
     * @throws \RuntimeException
     */
    public function save ($entity)
    {
        if (!$entity->getSource()) {
            $entity->setSource($this->getServiceSource()->getOse());
        }
        if (!$entity->getAnnee()) {
            $entity->setAnnee($this->getServiceContext()->getAnnee());
        }

        return parent::save($entity);
    }



    public function updateExportDate (Intervenant $intervenant): Intervenant
    {
        $date = new \DateTime();
@@ -628,4 +629,24 @@ class IntervenantService extends AbstractEntityService
        return $intervenant;
    }



    public function updateSource (Intervenant $intervenant): Intervenant
    {
        $config = \AppConfig::get('export-rh');
        if (!empty($config['sync-source'])) {
            //On regarde si le code fourni correspond bien à une source valide
            $source = $this->getServiceSource()->getByCode($config['sync-source']);
            if (!empty($source)) {
                $intervenant->setSource($source);
                $this->getEntityManager()->persist($intervenant);
                $this->getEntityManager()->flush();
                //On recalcul les tablaeux de bords de l'intervenant
                $this->getServiceWorkflow()->calculerTableauxBord([], $intervenant);
            }
        }

        return $intervenant;
    }

}
+48 −42
Original line number Diff line number Diff line
@@ -80,6 +80,44 @@ class ExportRhController extends AbstractController



    public function priseEnChargeAction ()
    {
        try {
            if ($this->getRequest()->isPost()) {
                $intervenant = $this->getEvent()->getParam('intervenant');

                if (!$intervenant) {
                    throw new \LogicException('Intervenant non précisé ou inexistant');
                }

                $posts  = $this->getRequest()->getPost();
                $result = $this->exportRhService->priseEnChargeIntrervenantRh($intervenant, $posts);
                if ($result !== false) {
                    // $this->exportRhService->cloreDossier($intervenant);
                    $this->flashMessenger()->addSuccessMessage('La prise en charge s\'est déroulée avec succés et le dossier a été cloturé');
                    $this->getServiceIntervenant()->updateExportDate($intervenant);
                    //On met à jour le code intervenant si l'option est activée
                    if ($this->exportRhService->haveToSyncCode()) {
                        $this->getServiceIntervenant()->updateCode($intervenant, $result);
                    }
                    //On met à jour le source code lors de la synchronisauot
                    if ($this->exportRhService->haveToSyncSource()) {
                        $this->getServiceIntervenant()->updateSource($intervenant);
                    }
                } else {
                    $this->flashMessenger()->addErrorMessage('Probleme prise en charge');
                }
            }
        } catch (\Exception $e) {

            $this->flashMessenger()->addErrorMessage($e->getMessage());
        }

        return $this->exporterAction();
    }



    public function exporterAction ()
    {

@@ -184,41 +222,6 @@ class ExportRhController extends AbstractController



    public function priseEnChargeAction()
    {
        try {
            if ($this->getRequest()->isPost()) {
                $intervenant = $this->getEvent()->getParam('intervenant');

                if (!$intervenant) {
                    throw new \LogicException('Intervenant non précisé ou inexistant');
                }

                $posts  = $this->getRequest()->getPost();
                $result = $this->exportRhService->priseEnChargeIntrervenantRh($intervenant, $posts);

                if ($result !== false) {
                    $this->exportRhService->cloreDossier($intervenant);
                    $this->flashMessenger()->addSuccessMessage('La prise en charge s\'est déroulée avec succés et le dossier a été cloturé');
                    $this->getServiceIntervenant()->updateExportDate($intervenant);
                    //On met à jour le code intervenant si l'option est activée
                    if ($this->exportRhService->haveToSyncCode()) {
                        $this->getServiceIntervenant()->updateCode($intervenant, $result);
                    }
                } else {
                    $this->flashMessenger()->addErrorMessage('Probleme prise en charge');
                }
            }
        } catch (\Exception $e) {

            $this->flashMessenger()->addErrorMessage($e->getMessage());
        }

        return $this->exporterAction();
    }



    public function renouvellementAction ()
    {
        try {
@@ -247,6 +250,9 @@ class ExportRhController extends AbstractController
                        if ($this->exportRhService->haveToSyncCode()) {
                            $this->getServiceIntervenant()->updateCode($intervenant, $result);
                        }
                        if ($this->exportRhService->haveToSyncSource()) {
                            $this->getServiceIntervenant()->updateSource($intervenant);
                        }
                    } else {
                        $this->flashMessenger()->addErrorMessage('Un problème est survenu lors de la tentative de renouvellement de l\'intervenant');
                    }
Loading