Commit 28f354a2 authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

WIP

parent a8f47bcf
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -163,3 +163,52 @@ from PROFIL_TO_ROLE p2r
where not exists (select * from role_privilege where role_id = p2r.role_id and privilege_id = pp.privilege_id)
;


--
-- Nouvelles colonnes dans these_annee_univ (pour le traitement des IA) :
--   - témoin indiquant s'il s'agit de l'année de 1ere inscription ;
--   - lien vers l'inscription administrative concernée.
--
alter table these_annee_univ add inscription_administrative_id bigint references inscription_administrative;
create index these_annee_univ_ia on these_annee_univ (inscription_administrative_id);
alter table these_annee_univ add est_1ere_annee_inscription bool default false not null;
create or replace view v_these_annee_univ_first(id, source_code, source_id, these_id, annee_univ, histo_createur_id, histo_creation, histo_modificateur_id, histo_modification, histo_destructeur_id, histo_destruction) as
WITH firsts(source_code) AS (
    SELECT DISTINCT first_value(these_annee_univ.source_code) OVER (PARTITION BY these_annee_univ.these_id ORDER BY these_annee_univ.annee_univ) AS first_value
    FROM these_annee_univ
    WHERE these_annee_univ.histo_destruction IS NULL
)
SELECT au.id,
       au.source_code,
       au.source_id,
       au.these_id,
       au.annee_univ,
       au.histo_createur_id,
       au.histo_creation,
       au.histo_modificateur_id,
       au.histo_modification,
       au.histo_destructeur_id,
       au.histo_destruction
FROM these_annee_univ au
         JOIN firsts fi ON au.source_code::text = fi.source_code::text
where au.source_id <> 1
union
SELECT au.id,
       au.source_code,
       au.source_id,
       au.these_id,
       au.annee_univ,
       au.histo_createur_id,
       au.histo_creation,
       au.histo_modificateur_id,
       au.histo_modification,
       au.histo_destructeur_id,
       au.histo_destruction
FROM these_annee_univ au
where est_1ere_annee_inscription = true;
/* future update à lancer lorsqu'on débranchera l'import Apogée/Physalis :
update these_annee_univ tau set est_1ere_annee_inscription = true where tau.source_id <> 1 and tau.id in (
    SELECT DISTINCT first_value(id) OVER (PARTITION BY these_id ORDER BY annee_univ) AS first_value
    FROM these_annee_univ
    WHERE histo_destruction IS NULL
);*/
+128 −0
Original line number Diff line number Diff line
<?php

namespace Application;

use UnicaenApp\Traits\MessageAwareInterface;
use UnicaenApp\Util;

trait MessageAwareTrait
{
    protected array $messages = [];
    
    /**
     * Spécifie les messages courants (remplaçant les messages existants).
     */
    public function setMessages(array $messages): static
    {
        $this->messages = array();
        foreach ($messages as $severity => $message) {
            $this->addMessage($message, $severity);
        }
        return $this;
    }
    
    /**
     * Spécifie l'unique message courant.
     * 
     * @param string $message Message
     * @param string|null $severity Ex: MessageAwareInterface::INFO
     */
    public function setMessage(string $message, ?string $severity = null): static
    {
        return $this->setMessages(array($severity => $message));
    }
    
    /**
     * Indique si cette aide de vue contient des messages actuellement.
     * 
     * @param string|null $severity Seule sévérité éventuelle à prendre en compte, ex: MessageAwareInterface::INFO
     */
    public function hasMessages(?string $severity = null): bool
    {
        if ($severity !== null) {
            return array_key_exists($severity, $this->messages) && $this->messages[$severity];
        }
        return array_values($this->messages)[0] ?? false;
    }

    /**
     * Retourne les messages courants.
     *
     * @param string|null $severity Seule sévérité éventuelle à prendre en compte, ex: MessageAwareInterface::INFO
     */
    public function getMessages(?string $severity = null): array
    {
        if ($severity !== null) {
            return $this->messages[$severity] ?? [];
        }
        return $this->messages;
    }
    
    /**
     * Retourne les messages courants en une seule chaîne de caractères.
     * 
     * @param string $glue Séparateur à utiliser (PHP_EOL par défaut)
     * @param string|null $severity Seule sévérité éventuelle à prendre en compte, ex: MessageAwareInterface::INFO
     */
    public function getMessage(string $glue = PHP_EOL, ?string $severity = null): string
    {
        $messages = $this->getMessages($severity);
        
        return implode($glue, Util::extractArrayLeafNodes($messages));
    }

    /**
     * Ajoute un message.
     *
     * @param string $message  Message
     * @param string|null $severity Sévérité, ex: MessageAwareInterface::INFO
     * @param int|null $priority Permet d'ordonner les messages au sein d'une même sévérité
     */
    public function addMessage(string $message, ?string $severity = null, ?int $priority = 0): static
    {
        if (!$severity || !is_string($severity)) {
            $severity = MessageAwareInterface::INFO;
        }
        if (!isset($this->messages[$severity])) {
            $this->messages[$severity] = [];
        }
        if (!in_array($message, $this->messages[$severity])) {
            while (array_key_exists($priority, $this->messages[$severity])) { // recherche priorité disponible
                $priority++;
            }
            $this->messages[$severity][$priority] = $message;
            ksort($this->messages[$severity]);
        }
        return $this;
    }
    
    /**
     * Ajoute plusieurs messages.
     * 
     * @param array $messages [Sévérité => Message]
     */
    public function addMessages(array $messages): static
    {
        foreach ($messages as $severity => $message) {
            $this->addMessage($message, $severity);
        }
        
        return $this;
    }
    
    /**
     * Supprime tous les messages courants.
     * 
     * @param string|null $severity Seule sévérité éventuelle à prendre en compte, ex: MessageAwareInterface::INFO
     */
    public function clearMessages(?string $severity = null): static
    {
        if ($severity && array_key_exists($severity, $this->getMessages())) {
            $this->messages[$severity] = array();
        }
        else {
            $this->messages = array();
        }
        return $this;
    }
}
 No newline at end of file
+54 −5
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ use Admission\Service\Admission\AdmissionServiceAwareTrait;
use Doctorant\Entity\Db\Doctorant;
use Doctorant\Service\DoctorantServiceAwareTrait;
use Exception;
use Individu\Entity\Db\Individu;
use Individu\Service\IndividuServiceAwareTrait;
use InscriptionAdministrative\Entity\Db\InscriptionAdministrativeApprenant;
use InscriptionAdministrative\Entity\Db\InscriptionAdministrativeDoctorant;
@@ -16,8 +15,12 @@ use InscriptionAdministrative\Process\AbstractProcess;
use InscriptionAdministrative\Rule\Reception\ReceptionRuleAwareTrait;
use InscriptionAdministrative\Service\InscriptionAdministrativeServiceAwareTrait;
use RuntimeException;
use These\Entity\Db\These;
use These\Entity\Db\TheseAnneeUniv;
use These\Service\These\TheseServiceAwareTrait;
use These\Service\TheseAnneeUniv\TheseAnneeUnivServiceAwareTrait;
use UnicaenApp\Traits\MessageAwareInterface;
use Webmozart\Assert\Assert;

class ReceptionProcess extends AbstractProcess
{
@@ -26,6 +29,7 @@ class ReceptionProcess extends AbstractProcess
    use IndividuServiceAwareTrait;
    use DoctorantServiceAwareTrait;
    use TheseServiceAwareTrait;
    use TheseAnneeUnivServiceAwareTrait;
    use AdmissionServiceAwareTrait;

    use InscriptionAdministrativeAwareTrait;
@@ -35,6 +39,8 @@ class ReceptionProcess extends AbstractProcess

    private ?Admission $admission;
    private ?Doctorant $doctorant = null;
    private ?These $these = null;
    private ?TheseAnneeUniv $theseAnneeUniv = null;

    private ReceptionProcessResult $result;

@@ -106,6 +112,15 @@ class ReceptionProcess extends AbstractProcess
        if ($this->receptionRule->canCreateThese()) {
            $this->admission = $this->receptionRule->getAdmission();
            $this->createTheseFromAdmission();
        } else {
            $this->these = $this->receptionRule->getThese(); // évite de fetcher à nouveau la thèse
        }

        if ($this->receptionRule->canCreateTheseAnneeUniv()) {
            $this->createTheseAnneeUnivFromInscriptionAdministrative();
        }
        if ($this->receptionRule->canLinkTheseAnneeUnivToInscriptionAdministrative()) {
            $this->linkTheseAnneeUnivToInscriptionAdministrative();
        }

        if ($this->receptionRule->canLinkAdmissionToDoctorant()) {
@@ -152,17 +167,51 @@ class ReceptionProcess extends AbstractProcess

    private function createTheseFromAdmission(): void
    {
        $these = $this->theseService->newTheseFromAdmission($this->admission, $this->doctorant);
        $this->theseService->saveThese($these);
        $this->these = $this->theseService->newTheseFromAdmission($this->admission, $this->doctorant);
        $this->theseService->saveThese($this->these);

        $message = sprintf(
            "La thèse %s a été créée pour le doctorant %s à partir du dossier d'admission.",
            $these->getId(),
            $this->these->getId(),
            $this->doctorant->getId(),
        );
        $this->result->addMessage($message, MessageAwareInterface::INFO);
        $this->result->setIsTheseCreated(true);
        $this->result->setCreatedThese($these);
        $this->result->setCreatedThese($this->these);
    }

    private function createTheseAnneeUnivFromInscriptionAdministrative(): void
    {
        Assert::notNull($this->these, "Incohérence dans l'algo : une thèse devrait être dispo !"); // todo : généraliser ce type de vérif ?

        $annee = $this->inscriptionAdministrative->getPeriodeAnneeUniversitaire();

        $this->theseAnneeUniv = $this->theseAnneeUnivService->newTheseAnneeUniv($annee);
        $this->theseAnneeUniv->setThese($this->these);
        $this->theseAnneeUniv->setInscriptionAdministrative($this->inscriptionAdministrative);
        $this->theseAnneeUnivService->save($this->theseAnneeUniv);

        $message = sprintf(
            "L'année universitaire %s a été créée pour la thèse %s à partir de l'inscription administrative.",
            $this->theseAnneeUniv,
            $this->these->getId(),
        );
        $this->result->addMessage($message, MessageAwareInterface::INFO);
        $this->result->setIsTheseAnneeUnivCreated(true);
        $this->result->setCreatedTheseAnneeUniv($this->theseAnneeUniv);
    }

    private function linkTheseAnneeUnivToInscriptionAdministrative(): void
    {
        $this->theseAnneeUniv = $this->receptionRule->getTheseAnneeUniv();
        $this->theseAnneeUniv->setInscriptionAdministrative($this->inscriptionAdministrative);
        $this->theseAnneeUnivService->save($this->theseAnneeUniv);

        $message = sprintf(
            "Le lien entre l'année universitaire %s et l'inscription administrative a été effectué.",
            $this->theseAnneeUniv,
        );
        $this->result->addMessage($message, MessageAwareInterface::INFO);
    }

    private function updateCodeApprenantDoctorantFromApprenant(): void
+5 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ use InscriptionAdministrative\Service\InscriptionAdministrativeService;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerInterface;
use These\Service\These\TheseService;
use These\Service\TheseAnneeUniv\TheseAnneeUnivService;

class ReceptionProcessFactory implements FactoryInterface
{
@@ -41,6 +42,10 @@ class ReceptionProcessFactory implements FactoryInterface
        $theseService = $container->get(TheseService::class);
        $service->setTheseService($theseService);

        /** @var TheseAnneeUnivService $theseAnneeUnivService */
        $theseAnneeUnivService = $container->get(TheseAnneeUnivService::class);
        $service->setTheseAnneeUnivService($theseAnneeUnivService);

        /** @var AdmissionService $admissionService */
        $admissionService = $container->get(AdmissionService::class);
        $service->setAdmissionService($admissionService);
+25 −0
Original line number Diff line number Diff line
@@ -6,13 +6,16 @@ use Admission\Entity\Db\Admission;
use Doctorant\Entity\Db\Doctorant;
use InscriptionAdministrative\Process\ProcessResult;
use These\Entity\Db\These;
use These\Entity\Db\TheseAnneeUniv;

class ReceptionProcessResult extends ProcessResult
{
    private ?Admission $foundAdmissionValidee = null;
    private ?Doctorant $doctorant = null;
    private ?These $createdThese = null;
    private ?TheseAnneeUniv $createdTheseAnneeUniv = null;
    private bool $isTheseCreated = false;
    private bool $isTheseAnneeUnivCreated = false;
    private bool $isDoctorantCreated = false;
    private bool $isDoctorantUpdated = false;

@@ -27,6 +30,17 @@ class ReceptionProcessResult extends ProcessResult
        return $this;
    }

    public function isTheseAnneeUnivCreated(): bool
    {
        return $this->isTheseAnneeUnivCreated;
    }

    public function setIsTheseAnneeUnivCreated(bool $isTheseAnneeUnivCreated): self
    {
        $this->isTheseAnneeUnivCreated = $isTheseAnneeUnivCreated;
        return $this;
    }

    public function setCreatedThese(?These $createdThese): self
    {
        $this->createdThese = $createdThese;
@@ -38,6 +52,17 @@ class ReceptionProcessResult extends ProcessResult
        return $this->createdThese;
    }

    public function setCreatedTheseAnneeUniv(?TheseAnneeUniv $createdTheseAnneeUniv): self
    {
        $this->createdTheseAnneeUniv = $createdTheseAnneeUniv;
        return $this;
    }

    public function getCreatedTheseAnneeUniv(): ?TheseAnneeUniv
    {
        return $this->createdTheseAnneeUniv;
    }

    public function isDoctorantCreated(): bool
    {
        return $this->isDoctorantCreated;
Loading