Loading CHANGELOG.md +1 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ Journal des modifications - [FIX] Formation : plantage lors de l'ouverture de la page de modification d'une Formation. - [FIX] Script de purge des fichiers temporaires : correction pour ce qui concerne la génération XML/TEF (envoi vers step-star). - Indicateur au format Thèse : inclusion de la colonne 'etat_these' et d'une colonne facultative 'extra'. - Soutenance Thèse : ajout d'une alerte quand une association membre=>acteur est incorrecte en raison du rôle inadéquat de l'acteur. 10.4.0 ------ Loading module/Acteur/src/Acteur/Entity/Db/Repository/AbstractActeurRepository.php +2 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,8 @@ abstract class AbstractActeurRepository extends DefaultEntityRepository public function findActeurByEntity(These|HDR $entity): array { $qb = $this->createQueryBuilder('a') ->addSelect('role')->join('a.role', 'role'); ->addSelect('role')->join('a.role', 'role') ->andWhereNotHistorise('a'); if ($entity instanceof These) { $qb->andWhere('a.these = :entity'); Loading module/Soutenance/src/Soutenance/Assertion/PresoutenanceAssertion.php +6 −7 Original line number Diff line number Diff line Loading @@ -77,8 +77,7 @@ class PresoutenanceAssertion extends AbstractAssertion case PresoutenancePrivileges::PRESOUTENANCE_DATE_RETOUR_MODIFICATION: $etatObject = $this->entity instanceof These ? $this->entity->getEtatThese() : $this->entity->getEtatHDR(); if ($etatObject === These::ETAT_SOUTENUE || $etatObject === HDR::ETAT_SOUTENUE) return false; $role = $this->userContextService->getSelectedIdentityRole(); return (($role->getCode() === Role::CODE_BDD || Role::CODE_GEST_HDR) && $role->getStructure() === $this->entity->getEtablissement()->getStructure()); return true; case HDRPrivileges::HDR_DONNER_RESULTAT: case ThesePrivileges::THESE_DONNER_RESULTAT: /** @var Proposition $p */ Loading module/Soutenance/src/Soutenance/Controller/PresoutenanceController.php +15 −58 Original line number Diff line number Diff line Loading @@ -94,73 +94,32 @@ abstract class PresoutenanceController extends AbstractSoutenanceController } /** * Ici on affecte au membre des acteurs qui remonte des SIs des établissements * Puis on affecte les rôles rapporteurs et membres * QUID :: Président ... * Création du lien entre la saisie libre d'un membre du jury et un acteur de thèse importé du SI de l'établissement. */ public function associerJuryAction() : ViewModel { $this->initializeFromType(false, false); /** @var Membre[] $membres */ // $membres = $this->proposition->getMembres(); $membre = $this->getMembreService()->getRequestedMembre($this); $membre = $this->membreService->getRequestedMembre($this); /** Ici, on prépare la liste des acteurs correspondant aux différents rôles pour le Select du formulaire * d'association. On part du principe : * - qu'un Rapporteur du jury est Rapporteur et Membre du jury, * - qu'un Rapporteur absent est Rapporteur, * - qu'un Membre du jury est Membre du jury. */ // Préparation de la liste des acteurs sélectionnables en fonction du rôle du membre $acteurs = $this->type === Proposition::ROUTE_PARAM_PROPOSITION_THESE ? $this->acteurService->getRepository()->findActeurByThese($this->entity) : $this->acteurService->getRepository()->findActeurByHDR($this->entity); $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { return $a->estNonHistorise();}); switch ($membre->getRole()) { case Membre::RAPPORTEUR_JURY : case Membre::RAPPORTEUR_VISIO : $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { /** @var Profil $profil */ $profil = $a->getRole()->getProfil(); return $profil?->getRoleCode() === 'R'; }); break; case Membre::RAPPORTEUR_ABSENT : $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { /** @var Profil $profil */ $profil = $a->getRole()->getProfil(); return $profil?->getRoleCode() === 'R'; }); break; case Membre::MEMBRE_JURY : $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { /** @var Profil $profil */ $profil = $a->getRole()->getProfil(); return $profil?->getRoleCode() === 'M'; }); break; } $acteurs_libres = []; /** @var ActeurThese|ActeurHDR $acteur */ $roleActeur = Membre::ROLE_MEMBRE_TO_ROLE_ACTEUR[$membre->getRole()] ?? null; if ($roleActeur) { $acteurs = array_filter($acteurs, fn(ActeurThese|ActeurHDR $a) => $a->getRole()->getCode() === $roleActeur ); } $acteursDisponibles = []; foreach ($acteurs as $acteur) { // à avoir si ça pose des problèmes // si l'acteur n'est pas encore associé à un membre, // ou que la proposition associée au membre n'est pas la même que celle actuelle // Un acteur est sélectionnable/disponible s'il n'est pas encore associé à un membre, // ou si la proposition associée au membre n'est pas la même que celle actuelle // (dans le cas d'une première prop. rejetée) if (!$acteur->getMembre() || $acteur->getMembre()->getProposition()->getId() !== $this->proposition->getId()) { $acteurs_libres[] = $acteur; } // $libre = true; // foreach ($membres as $membre_) { // $acteur_ = $this->acteurService->getRepository()->findActeurForSoutenanceMembre($membre_); //// if ($membre_->getActeur() && $membre_->getActeur()->getId() === $acteur->getId()) { // if ($acteur_ && $acteur_->getId() === $acteur->getId()) { // $libre = false; // break; // } // } // if ($libre) $acteurs_libres[] = $acteur; $acteursDisponibles[] = $acteur; } } $request = $this->getRequest(); Loading @@ -172,9 +131,6 @@ abstract class PresoutenanceController extends AbstractSoutenanceController if (! isset($acteur)) throw new RuntimeException("Aucun acteur à associer !"); // //mise à jour du membre de soutenance // $membre->setActeur($acteur); // $this->getMembreService()->update($membre); $acteur->setMembre($membre); $this->acteurService->save($acteur); $this->flashMessenger()->addSuccessMessage($membre->getDenomination()." a bien été associé à un acteur."); Loading @@ -190,11 +146,12 @@ abstract class PresoutenanceController extends AbstractSoutenanceController $vm->setTemplate('soutenance/presoutenance/associer-jury'); $vm->setVariables([ 'title' => "Association de " . $membre->getDenomination() . " à un acteur " . $this->appInfos()->getNom(), 'acteurs' => $acteurs_libres, 'acteurs' => $acteursDisponibles, 'membre' => $membre, 'entity' => $this->entity, 'typeProposition' => $this->type ]); return $vm; } Loading module/Soutenance/src/Soutenance/Controller/These/Presoutenance/PresoutenanceTheseController.php +26 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ class PresoutenanceTheseController extends PresoutenanceController $this->initializeFromType(); /** @var Membre[] $membres */ $membres = $this->proposition->getMembres()->toArray(); $membres = $this->membreService->findMembresForProposition($this->proposition); $acteursMembres = $this->acteurService->getRepository()->findActeursForSoutenanceMembres($membres); $rapporteurs = $this->propositionService->getRapporteurs($this->proposition); Loading @@ -88,6 +88,30 @@ class PresoutenanceTheseController extends PresoutenanceController $validationBDD = $this->validationService->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_VALIDATION_PROPOSITION_BDD, $this->entity); $validationPDC = $this->validationService->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_PAGE_DE_COUVERTURE, $this->entity); // alerte en cas de membre associé à un acteur dont le rôle ne colle plus /** @var ActeurThese $acteur */ $alertesAssociation = []; foreach (array_filter($acteursMembres) as $membreId => $acteur) { $membre = $membres[$membreId]; $codeRoleAttendu = Membre::ROLE_MEMBRE_TO_ROLE_ACTEUR[$membre->getRole()] ?? null; if ($codeRoleAttendu === null) { continue; } if ($acteur->getRole()->getCode() !== $codeRoleAttendu) { $roleAttendu = $this->applicationRoleService->getRepo()->findOneByCodeAndStructureConcrete($codeRoleAttendu, $this->entity->getEtablissement()); $alertesAssociation[$membreId] = sprintf( "L'association du membre « %s / %s » à l'acteur « %s / %s » (id %d) est incorrecte, " . "elle devrait être faite avec un acteur ayant le rôle « %s ».", $membre->getDenomination(), $membre->getRole(), $acteur->getIndividu(), $acteur->getRole(), $acteur->getId(), $roleAttendu, ); } } /** Parametres ---------------------------------------------------------------------------------------------- */ try { $deadline = $this->parametreService->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DELAI_RETOUR); Loading Loading @@ -116,6 +140,7 @@ class PresoutenanceTheseController extends PresoutenanceController 'validationPDC' => $validationPDC, 'justificatifsOk' => $justificatifsOk, 'justificatifs' => $justificatifs, 'alertesAssociation' => $alertesAssociation, 'deadline' => $deadline, Loading Loading
CHANGELOG.md +1 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ Journal des modifications - [FIX] Formation : plantage lors de l'ouverture de la page de modification d'une Formation. - [FIX] Script de purge des fichiers temporaires : correction pour ce qui concerne la génération XML/TEF (envoi vers step-star). - Indicateur au format Thèse : inclusion de la colonne 'etat_these' et d'une colonne facultative 'extra'. - Soutenance Thèse : ajout d'une alerte quand une association membre=>acteur est incorrecte en raison du rôle inadéquat de l'acteur. 10.4.0 ------ Loading
module/Acteur/src/Acteur/Entity/Db/Repository/AbstractActeurRepository.php +2 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,8 @@ abstract class AbstractActeurRepository extends DefaultEntityRepository public function findActeurByEntity(These|HDR $entity): array { $qb = $this->createQueryBuilder('a') ->addSelect('role')->join('a.role', 'role'); ->addSelect('role')->join('a.role', 'role') ->andWhereNotHistorise('a'); if ($entity instanceof These) { $qb->andWhere('a.these = :entity'); Loading
module/Soutenance/src/Soutenance/Assertion/PresoutenanceAssertion.php +6 −7 Original line number Diff line number Diff line Loading @@ -77,8 +77,7 @@ class PresoutenanceAssertion extends AbstractAssertion case PresoutenancePrivileges::PRESOUTENANCE_DATE_RETOUR_MODIFICATION: $etatObject = $this->entity instanceof These ? $this->entity->getEtatThese() : $this->entity->getEtatHDR(); if ($etatObject === These::ETAT_SOUTENUE || $etatObject === HDR::ETAT_SOUTENUE) return false; $role = $this->userContextService->getSelectedIdentityRole(); return (($role->getCode() === Role::CODE_BDD || Role::CODE_GEST_HDR) && $role->getStructure() === $this->entity->getEtablissement()->getStructure()); return true; case HDRPrivileges::HDR_DONNER_RESULTAT: case ThesePrivileges::THESE_DONNER_RESULTAT: /** @var Proposition $p */ Loading
module/Soutenance/src/Soutenance/Controller/PresoutenanceController.php +15 −58 Original line number Diff line number Diff line Loading @@ -94,73 +94,32 @@ abstract class PresoutenanceController extends AbstractSoutenanceController } /** * Ici on affecte au membre des acteurs qui remonte des SIs des établissements * Puis on affecte les rôles rapporteurs et membres * QUID :: Président ... * Création du lien entre la saisie libre d'un membre du jury et un acteur de thèse importé du SI de l'établissement. */ public function associerJuryAction() : ViewModel { $this->initializeFromType(false, false); /** @var Membre[] $membres */ // $membres = $this->proposition->getMembres(); $membre = $this->getMembreService()->getRequestedMembre($this); $membre = $this->membreService->getRequestedMembre($this); /** Ici, on prépare la liste des acteurs correspondant aux différents rôles pour le Select du formulaire * d'association. On part du principe : * - qu'un Rapporteur du jury est Rapporteur et Membre du jury, * - qu'un Rapporteur absent est Rapporteur, * - qu'un Membre du jury est Membre du jury. */ // Préparation de la liste des acteurs sélectionnables en fonction du rôle du membre $acteurs = $this->type === Proposition::ROUTE_PARAM_PROPOSITION_THESE ? $this->acteurService->getRepository()->findActeurByThese($this->entity) : $this->acteurService->getRepository()->findActeurByHDR($this->entity); $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { return $a->estNonHistorise();}); switch ($membre->getRole()) { case Membre::RAPPORTEUR_JURY : case Membre::RAPPORTEUR_VISIO : $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { /** @var Profil $profil */ $profil = $a->getRole()->getProfil(); return $profil?->getRoleCode() === 'R'; }); break; case Membre::RAPPORTEUR_ABSENT : $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { /** @var Profil $profil */ $profil = $a->getRole()->getProfil(); return $profil?->getRoleCode() === 'R'; }); break; case Membre::MEMBRE_JURY : $acteurs = array_filter($acteurs, function (ActeurThese|ActeurHDR $a) { /** @var Profil $profil */ $profil = $a->getRole()->getProfil(); return $profil?->getRoleCode() === 'M'; }); break; } $acteurs_libres = []; /** @var ActeurThese|ActeurHDR $acteur */ $roleActeur = Membre::ROLE_MEMBRE_TO_ROLE_ACTEUR[$membre->getRole()] ?? null; if ($roleActeur) { $acteurs = array_filter($acteurs, fn(ActeurThese|ActeurHDR $a) => $a->getRole()->getCode() === $roleActeur ); } $acteursDisponibles = []; foreach ($acteurs as $acteur) { // à avoir si ça pose des problèmes // si l'acteur n'est pas encore associé à un membre, // ou que la proposition associée au membre n'est pas la même que celle actuelle // Un acteur est sélectionnable/disponible s'il n'est pas encore associé à un membre, // ou si la proposition associée au membre n'est pas la même que celle actuelle // (dans le cas d'une première prop. rejetée) if (!$acteur->getMembre() || $acteur->getMembre()->getProposition()->getId() !== $this->proposition->getId()) { $acteurs_libres[] = $acteur; } // $libre = true; // foreach ($membres as $membre_) { // $acteur_ = $this->acteurService->getRepository()->findActeurForSoutenanceMembre($membre_); //// if ($membre_->getActeur() && $membre_->getActeur()->getId() === $acteur->getId()) { // if ($acteur_ && $acteur_->getId() === $acteur->getId()) { // $libre = false; // break; // } // } // if ($libre) $acteurs_libres[] = $acteur; $acteursDisponibles[] = $acteur; } } $request = $this->getRequest(); Loading @@ -172,9 +131,6 @@ abstract class PresoutenanceController extends AbstractSoutenanceController if (! isset($acteur)) throw new RuntimeException("Aucun acteur à associer !"); // //mise à jour du membre de soutenance // $membre->setActeur($acteur); // $this->getMembreService()->update($membre); $acteur->setMembre($membre); $this->acteurService->save($acteur); $this->flashMessenger()->addSuccessMessage($membre->getDenomination()." a bien été associé à un acteur."); Loading @@ -190,11 +146,12 @@ abstract class PresoutenanceController extends AbstractSoutenanceController $vm->setTemplate('soutenance/presoutenance/associer-jury'); $vm->setVariables([ 'title' => "Association de " . $membre->getDenomination() . " à un acteur " . $this->appInfos()->getNom(), 'acteurs' => $acteurs_libres, 'acteurs' => $acteursDisponibles, 'membre' => $membre, 'entity' => $this->entity, 'typeProposition' => $this->type ]); return $vm; } Loading
module/Soutenance/src/Soutenance/Controller/These/Presoutenance/PresoutenanceTheseController.php +26 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ class PresoutenanceTheseController extends PresoutenanceController $this->initializeFromType(); /** @var Membre[] $membres */ $membres = $this->proposition->getMembres()->toArray(); $membres = $this->membreService->findMembresForProposition($this->proposition); $acteursMembres = $this->acteurService->getRepository()->findActeursForSoutenanceMembres($membres); $rapporteurs = $this->propositionService->getRapporteurs($this->proposition); Loading @@ -88,6 +88,30 @@ class PresoutenanceTheseController extends PresoutenanceController $validationBDD = $this->validationService->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_VALIDATION_PROPOSITION_BDD, $this->entity); $validationPDC = $this->validationService->getRepository()->findValidationByCodeAndThese(TypeValidation::CODE_PAGE_DE_COUVERTURE, $this->entity); // alerte en cas de membre associé à un acteur dont le rôle ne colle plus /** @var ActeurThese $acteur */ $alertesAssociation = []; foreach (array_filter($acteursMembres) as $membreId => $acteur) { $membre = $membres[$membreId]; $codeRoleAttendu = Membre::ROLE_MEMBRE_TO_ROLE_ACTEUR[$membre->getRole()] ?? null; if ($codeRoleAttendu === null) { continue; } if ($acteur->getRole()->getCode() !== $codeRoleAttendu) { $roleAttendu = $this->applicationRoleService->getRepo()->findOneByCodeAndStructureConcrete($codeRoleAttendu, $this->entity->getEtablissement()); $alertesAssociation[$membreId] = sprintf( "L'association du membre « %s / %s » à l'acteur « %s / %s » (id %d) est incorrecte, " . "elle devrait être faite avec un acteur ayant le rôle « %s ».", $membre->getDenomination(), $membre->getRole(), $acteur->getIndividu(), $acteur->getRole(), $acteur->getId(), $roleAttendu, ); } } /** Parametres ---------------------------------------------------------------------------------------------- */ try { $deadline = $this->parametreService->getValeurForParametre(SoutenanceParametres::CATEGORIE, SoutenanceParametres::DELAI_RETOUR); Loading Loading @@ -116,6 +140,7 @@ class PresoutenanceTheseController extends PresoutenanceController 'validationPDC' => $validationPDC, 'justificatifsOk' => $justificatifsOk, 'justificatifs' => $justificatifs, 'alertesAssociation' => $alertesAssociation, 'deadline' => $deadline, Loading