Browse Source

datapersister : parameters et organization

Vincent GUFFON 3 years ago
parent
commit
378e4697b0
29 changed files with 733 additions and 115 deletions
  1. 6 0
      config/packages/dev/messenger.yaml
  2. 1 0
      config/packages/messenger.yaml
  3. 10 0
      config/services.yaml
  4. 51 0
      src/DataPersister/Organization/OrganizationDataPersister.php
  5. 64 0
      src/DataPersister/Organization/ParametersDataPersister.php
  6. 1 0
      src/Doctrine/Access/CurrentAccessExtension.php
  7. 48 0
      src/Doctrine/Education/CurrentEducationNotationConfigExtension.php
  8. 16 0
      src/Entity/Access/Access.php
  9. 44 0
      src/Entity/Education/EducationCurriculum.php
  10. 188 0
      src/Entity/Education/EducationNotationConfig.php
  11. 55 1
      src/Entity/Organization/Organization.php
  12. 0 16
      src/Entity/Organization/Parameters.php
  13. 0 68
      src/EventListener/Organization/OrganizationChangedSubscriber.php
  14. 17 0
      src/Message/Command/Parameters/AverageChange.php
  15. 20 0
      src/Message/Handler/Parameters/AverageChangeHandler.php
  16. 16 0
      src/Repository/Education/EducationCurriculumRepository.php
  17. 16 0
      src/Repository/Education/EducationNotationConfigRepository.php
  18. 1 1
      src/Repository/Organization/OrganizationAddressPostalRepository.php
  19. 1 1
      src/Service/Access/AdminAccessUtils.php
  20. 0 1
      src/Service/Access/Utils.php
  21. 7 3
      src/Service/Core/ContactPointUtils.php
  22. 29 0
      src/Service/Organization/OnOrganizationChange.php
  23. 40 0
      src/Service/Organization/OnParametersChange.php
  24. 0 1
      src/Service/ServiceIterator/CurrentAccessExtensionIterator.php
  25. 1 1
      tests/Service/Access/UtilsTest.php
  26. 1 1
      tests/Service/Core/ContactPointUtilsTest.php
  27. 39 0
      tests/Service/Organization/OnOrganizationChangeTest.php
  28. 61 0
      tests/Service/Organization/OnParametersChangeTest.php
  29. 0 21
      tests/Service/ServiceIterator/CurrentAccessExtensionIteratorTest.php

+ 6 - 0
config/packages/dev/messenger.yaml

@@ -0,0 +1,6 @@
+framework:
+    messenger:
+        transports:
+            # https://symfony.com/doc/current/messenger.html#transport-configuration
+            async: 'sync://'
+            failed: 'sync://'

+ 1 - 0
config/packages/messenger.yaml

@@ -12,3 +12,4 @@ framework:
         routing:
             # Route your messages to the transports
             'App\Message\Command\Export': async
+            'App\Message\Command\Parameters\AverageChange': async

+ 10 - 0
config/services.yaml

@@ -90,3 +90,13 @@ services:
     App\EventListener\DoctrineFilter\DoctrineFilterListener:
         tags:
             - { name: kernel.event_listener, event: kernel.request }
+
+    #########################################
+    ##  DATAPERSISTER ##
+    App\DataPersister\Organization\ParametersDataPersister:
+        bind:
+            $decorated: '@api_platform.doctrine.orm.data_persister'
+
+    App\DataPersister\Organization\OrganizationDataPersister:
+        bind:
+            $decorated: '@api_platform.doctrine.orm.data_persister'

+ 51 - 0
src/DataPersister/Organization/OrganizationDataPersister.php

@@ -0,0 +1,51 @@
+<?php
+declare(strict_types=1);
+
+namespace App\DataPersister\Organization;
+
+use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
+use App\Entity\Organization\Organization;
+use App\Service\Organization\OnOrganizationChange;
+use Exception;
+
+/**
+ * Classe OrganizationDataPersister qui est un custom dataPersister gérant la resource Organization
+ */
+class OrganizationDataPersister implements ContextAwareDataPersisterInterface
+{
+    public function __construct(
+        private ContextAwareDataPersisterInterface $decorated,
+        private OnOrganizationChange $onOrganizationChange
+    )
+    { }
+
+    public function supports($data, array $context = []): bool
+    {
+        return $data instanceof Organization;
+    }
+
+    /**
+     * @param Organization $data
+     * @param array $context
+     * @return object|void
+     */
+    public function persist($data, array $context = [])
+    {
+        $this->prePersist($context['previous_data'], $data);
+
+        $result = $this->decorated->persist($data, $context);
+
+        return $result;
+    }
+
+    public function remove($data, array $context = [])
+    {
+        throw new Exception('not supported', 500);
+    }
+
+    public function prePersist(Organization $previousOrganization, Organization $organization): void{
+        if($previousOrganization->getLegalStatus() != $organization->getLegalStatus()){
+            $this->onOrganizationChange->onLegalStatusChange($organization);
+        }
+    }
+}

+ 64 - 0
src/DataPersister/Organization/ParametersDataPersister.php

@@ -0,0 +1,64 @@
+<?php
+declare(strict_types=1);
+
+namespace App\DataPersister\Organization;
+
+use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
+use App\Entity\Organization\Parameters;
+use App\Message\Command\Parameters\AverageChange;
+use App\Service\Organization\OnParametersChange;
+use Exception;
+use Symfony\Component\Messenger\MessageBusInterface;
+
+/**
+ * Classe ParametersDataPersister qui est un custom dataPersister gérant la resource Parameters
+ */
+class ParametersDataPersister implements ContextAwareDataPersisterInterface
+{
+    public function __construct(
+        private ContextAwareDataPersisterInterface $decorated,
+        private MessageBusInterface $messageBus,
+        private OnParametersChange $onParametersChange
+    )
+    { }
+
+    public function supports($data, array $context = []): bool
+    {
+        return $data instanceof Parameters;
+    }
+
+    /**
+     * @param Parameters $data
+     * @param array $context
+     * @return object|void
+     */
+    public function persist($data, array $context = [])
+    {
+        $this->prePersist($context['previous_data'], $data);
+
+        $result = $this->decorated->persist($data, $context);
+
+        $this->postPersist($context['previous_data'], $data);
+
+        return $result;
+    }
+
+    public function remove($data, array $context = [])
+    {
+        throw new Exception('not supported', 500);
+    }
+
+    public function prePersist(Parameters $previousParameters, Parameters $parameters): void{
+        if($previousParameters->getAdvancedEducationNotationType() != $parameters->getAdvancedEducationNotationType()){
+            $this->onParametersChange->onAdvancedEducationNotationType($parameters);
+        }
+    }
+
+    public function postPersist(Parameters $previousParameters, Parameters $parameters): void{
+        if($previousParameters->getAverage() != $parameters->getAverage()){
+            $this->messageBus->dispatch(
+                new AverageChange($parameters->getId())
+            );
+        }
+    }
+}

+ 1 - 0
src/Doctrine/Access/CurrentAccessExtension.php

@@ -38,6 +38,7 @@ final class CurrentAccessExtension implements QueryCollectionExtensionInterface,
         if (Access::class !== $resourceClass) {
             return;
         }
+
         /** @var Access $currentUser */
         $currentUser = $this->security->getUser();
         $rootAlias = $queryBuilder->getRootAliases()[0];

+ 48 - 0
src/Doctrine/Education/CurrentEducationNotationConfigExtension.php

@@ -0,0 +1,48 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Education;
+
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
+use App\Entity\Access\Access;
+use App\Entity\Education\Cycle;
+use App\Entity\Education\EducationNotationConfig;
+use Doctrine\ORM\QueryBuilder;
+use Symfony\Component\Security\Core\Security;
+
+/**
+ * Class CurrentEducationNotationConfigExtension : Filtre de sécurité par défaut pour une resource EducationNotationConfig
+ * @package App\Doctrine\Core
+ */
+final class CurrentEducationNotationConfigExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
+{
+    public function __construct(private Security $security)
+    { }
+
+    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName): void
+    {
+        if (EducationNotationConfig::class !== $resourceClass) {
+            return;
+        }
+
+        /** @var Access $currentUser */
+        $currentUser = $this->security->getUser();
+        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $queryBuilder
+            ->andWhere(sprintf('%s.organization = :organization', $rootAlias))
+            ->setParameter('organization', $currentUser->getOrganization())
+        ;
+    }
+}

+ 16 - 0
src/Entity/Access/Access.php

@@ -4,6 +4,7 @@ declare(strict_types=1);
 namespace App\Entity\Access;
 
 use ApiPlatform\Core\Annotation\ApiFilter;
+use App\Entity\Education\EducationNotationConfig;
 use App\Entity\Organization\Parameters;
 use App\Filter\Person\FullNameFilter;
 use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\BooleanFilter;
@@ -113,6 +114,9 @@ class Access implements UserInterface
     #[ORM\ManyToOne(inversedBy: 'publicationDirectors')]
     private ?Parameters $publicationDirector;
 
+    #[ORM\ManyToOne(inversedBy: 'teachers')]
+    private ?EducationNotationConfig $educationNotationConfig;
+
     #[Pure] public function __construct()
     {
         $this->personActivity = new ArrayCollection();
@@ -518,6 +522,18 @@ class Access implements UserInterface
         return $this;
     }
 
+    public function getEducationNotationConfig(): ?EducationNotationConfig
+    {
+        return $this->educationNotationConfig;
+    }
+
+    public function setEducationNotationConfig(?EducationNotationConfig $educationNotationConfig): self
+    {
+        $this->educationNotationConfig = $educationNotationConfig;
+
+        return $this;
+    }
+
     #[Pure] public function getUserIdentifier(): string
     {
         return $this->person->getUsername();

+ 44 - 0
src/Entity/Education/EducationCurriculum.php

@@ -0,0 +1,44 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Education;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Repository\Education\EducationCurriculumRepository;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Curriculum éducatif; composé d'un cycle, d'une année et d'un niveau
+ */
+#[ApiResource(
+    collectionOperations: [],
+    itemOperations: []
+)]
+#[ORM\Entity(repositoryClass: EducationCurriculumRepository::class)]
+class EducationCurriculum
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'educationCurriculums')]
+    private ?EducationNotationConfig $educationNotationConfig;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function setEducationNotationConfig(?EducationNotationConfig $educationNotationConfig): self
+    {
+        $this->educationNotationConfig = $educationNotationConfig;
+
+        return $this;
+    }
+
+    public function getEducationNotationConfig(): ?EducationNotationConfig
+    {
+        return $this->educationNotationConfig;
+    }
+}

+ 188 - 0
src/Entity/Education/EducationNotationConfig.php

@@ -0,0 +1,188 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Education;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Annotation\OrganizationDefaultValue;
+use App\Entity\Access\Access;
+use App\Repository\Education\EducationNotationConfigRepository;
+use App\Entity\Organization\Organization;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Configuration des grilles d'évaluation
+ */
+#[ApiResource(
+    collectionOperations: [
+        "get" => ["security" => "is_granted('ROLE_PEDAGOGICS_ADMINISTRATION_VIEW')"]
+    ],
+    itemOperations: [
+        "get" => ["security" => "is_granted('ROLE_PEDAGOGICS_ADMINISTRATION_VIEW') and object.getOrganization().getId() == user.getOrganization().getId()"],
+        "put" => ["security" => "object.getOrganization().getId() == user.getOrganization().getId()"],
+    ],
+    attributes: ["security" => "is_granted('ROLE_PEDAGOGICS_ADMINISTRATION')"]
+)]
+#[ORM\Entity(repositoryClass: EducationNotationConfigRepository::class)]
+#[OrganizationDefaultValue(fieldName: "organization")]
+class EducationNotationConfig
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'educationNotationConfigs')]
+    private Organization $organization;
+
+    #[ORM\Column(length: 255)]
+    private string $label;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $isActive = true;
+
+    #[ORM\Column(type: 'text', nullable: true)]
+    private ?string $description;
+
+    #[ORM\Column(options: ['default' => 1])]
+    #[Assert\GreaterThanOrEqual(1, message: 'greaterThanOrEqual1')]
+    #[Assert\LessThanOrEqual(10, message: 'lessThanOrEqual10')]
+    private int $coefficient = 1;
+
+    #[ORM\OneToMany( mappedBy: 'educationNotationConfig', targetEntity: Access::class)]
+    private Collection $teachers;
+
+    #[ORM\OneToMany( mappedBy: 'educationNotationConfig', targetEntity: EducationCurriculum::class)]
+    private Collection $educationCurriculums;
+
+
+    #[Pure] public function __construct() {
+        $this->teachers = new ArrayCollection();
+        $this->educationCurriculums = new ArrayCollection();
+    }
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setLabel(string $label): self
+    {
+        $this->label = $label;
+
+        return $this;
+    }
+
+    public function getLabel(): string
+    {
+        return $this->label;
+    }
+
+    public function setIsActive(bool $isActive): self
+    {
+        $this->isActive = $isActive;
+
+        return $this;
+    }
+
+    public function getIsActive(): bool
+    {
+        return $this->isActive;
+    }
+
+    public function setDescription(?string $description): self
+    {
+        $this->description = $description;
+
+        return $this;
+    }
+
+    public function getDescription(): ?string
+    {
+        return $this->description;
+    }
+
+    public function setCoefficient(?int $coefficient): self
+    {
+        if($coefficient === null) $coefficient = 1;
+        $this->coefficient = $coefficient;
+
+        return $this;
+    }
+
+    public function getCoefficient(): int
+    {
+        return $this->coefficient;
+    }
+
+
+    public function addTeacher(Access $teacher): self
+    {
+        if (!$this->teachers->contains($teacher)) {
+            $this->teachers[] = $teacher;
+            $teacher->setEducationNotationConfig($this);
+        }
+
+        return $this;
+    }
+
+    public function removeTeacher(Access $teacher): self
+    {
+        if ($this->teachers->removeElement($teacher)) {
+            // set the owning side to null (unless already changed)
+            if ($teacher->getEducationNotationConfig() === $this) {
+                $teacher->setEducationNotationConfig(null);
+            }
+        }
+        return $this;
+    }
+
+    public function getTeachers(): Collection
+    {
+        return $this->teachers;
+    }
+
+
+    public function addEducationCurriculum(EducationCurriculum $educationCurriculums): self
+    {
+        if (!$this->educationCurriculums->contains($educationCurriculums)) {
+            $this->educationCurriculums[] = $educationCurriculums;
+            $educationCurriculums->setEducationNotationConfig($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationCurriculum(EducationCurriculum $educationCurriculums): self
+    {
+        if ($this->educationCurriculums->removeElement($educationCurriculums)) {
+            // set the owning side to null (unless already changed)
+            if ($educationCurriculums->getEducationNotationConfig() === $this) {
+                $educationCurriculums->setEducationNotationConfig(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getEducationCurriculums(): Collection
+    {
+        return $this->educationCurriculums;
+    }
+}

+ 55 - 1
src/Entity/Organization/Organization.php

@@ -11,6 +11,7 @@ use App\Entity\Core\BankAccount;
 use App\Entity\Core\ContactPoint;
 use App\Entity\Core\File;
 use App\Entity\Education\Cycle;
+use App\Entity\Education\EducationNotationConfig;
 use App\Entity\Network\NetworkOrganization;
 use App\Repository\Organization\OrganizationRepository;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -67,6 +68,9 @@ class Organization
     #[ORM\OneToMany(mappedBy: 'parent', targetEntity: NetworkOrganization::class, orphanRemoval: true)]
     private Collection $networkOrganizationChildren;
 
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: EducationNotationConfig::class, orphanRemoval: true)]
+    private Collection $educationNotationConfigs;
+
     #[ORM\OneToOne( inversedBy: 'organization', targetEntity: Parameters::class)]
     #[ORM\JoinColumn(nullable: false)]
     private Parameters $parameters;
@@ -75,7 +79,7 @@ class Organization
     #[ApiSubresource]
     private BillingSetting $billingSetting;
 
-    #[ORM\Column(length: 255, nullable: true)]
+    #[ORM\Column(type: 'text', nullable: true)]
     private ?string $description = null;
 
     #[ORM\Column(type: 'date', nullable: true)]
@@ -228,6 +232,7 @@ class Organization
         $this->organizationLicences = new ArrayCollection();
         $this->organizationArticles = new ArrayCollection();
         $this->cycles = new ArrayCollection();
+        $this->educationNotationConfigs = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -971,8 +976,57 @@ class Organization
         return $this;
     }
 
+    public function addCycle(Cycle $cycle): self
+    {
+        if (!$this->cycles->contains($cycle)) {
+            $this->cycles[] = $cycle;
+            $cycle->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeCycle(Cycle $cycle): self
+    {
+        if ($this->cycles->removeElement($cycle)) {
+            // set the owning side to null (unless already changed)
+            if ($cycle->getOrganization() === $this) {
+                $cycle->setOrganization(null);
+            }
+        }
+
+        return $this;
+    }
+
     public function getCycles(): Collection
     {
         return $this->cycles;
     }
+
+    public function addEducationNotationConfig(EducationNotationConfig $educationNotationConfig): self
+    {
+        if (!$this->educationNotationConfigs->contains($educationNotationConfig)) {
+            $this->educationNotationConfigs[] = $educationNotationConfig;
+            $educationNotationConfig->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationNotationConfig(EducationNotationConfig $educationNotationConfig): self
+    {
+        if ($this->educationNotationConfigs->removeElement($educationNotationConfig)) {
+            // set the owning side to null (unless already changed)
+            if ($educationNotationConfig->getOrganization() === $this) {
+                $educationNotationConfig->setOrganization(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getEducationNotationConfigs(): Collection
+    {
+        return $this->educationNotationConfigs;
+    }
 }

+ 0 - 16
src/Entity/Organization/Parameters.php

@@ -624,20 +624,4 @@ class Parameters
 
         return $this;
     }
-
-    /**
-     * @return File
-     */
-    public function getQrCode(): File
-    {
-        return $this->qrCode;
-    }
-
-    /**
-     * @param File $qrCode
-     */
-    public function setQrCode(File $qrCode): void
-    {
-        $this->qrCode = $qrCode;
-    }
 }

+ 0 - 68
src/EventListener/Organization/OrganizationChangedSubscriber.php

@@ -1,68 +0,0 @@
-<?php
-declare(strict_types=1);
-
-namespace App\EventListener\Organization;
-
-use App\Entity\Billing\BillingSetting;
-use App\Entity\Organization\Organization;
-use App\Entity\Organization\Parameters;
-use App\Enum\Organization\LegalEnum;
-use App\EventListener\Helper;
-use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
-use Doctrine\ORM\EntityManagerInterface;
-use Doctrine\ORM\Event\OnFlushEventArgs;
-use Doctrine\ORM\Events;
-
-/**
- * Classe subscriber qui doit intervenir quand on flush une entité Organization
- */
-class OrganizationChangedSubscriber implements EventSubscriberInterface
-{
-    use Helper;
-
-    /**
-     * On souscrit à l'événement OnFlush
-     * @return array
-     */
-    public function getSubscribedEvents(): array
-    {
-        return [
-            Events::onFlush
-        ];
-    }
-
-    /**
-     * onFlush Event
-     * @param OnFlushEventArgs $onFlushEventArgs
-     */
-    public function onFlush(OnFlushEventArgs $onFlushEventArgs){
-        $entityManager = $onFlushEventArgs->getEntityManager();
-        $uow = $entityManager->getUnitOfWork();
-        foreach ($uow->getScheduledEntityUpdates() as $entityUpdate){
-            if($entityUpdate instanceof Organization){
-                //Si dans l'update de l'entité, on modifie le champs "legalStatus"
-                if($this->hasChangeField($entityManager, $entityUpdate, 'legalStatus'))
-                    $this->handleLegalStatusChanged($entityUpdate, $entityManager);
-            }
-        }
-    }
-
-    /**
-     * Changement qui doivent être fait si le statut légale d'une structure est changé.
-     * @param Organization $organization
-     * @param EntityManagerInterface $entityManager
-     */
-    public function handleLegalStatusChanged(Organization $organization, EntityManagerInterface $entityManager){
-        //Si le nouveau status légal n'est pas "Association Loi 1901"
-        if($organization->getLegalStatus() !== LegalEnum::ASSOCIATION_LAW_1901()->getValue()){
-            $organization->getParameters()->setShowAdherentList(false);
-            $entityManager->getUnitOfWork()->computeChangeSet($entityManager->getClassMetadata(Parameters::class), $organization->getParameters());
-        }
-
-        //Si le nouveau status légal est "Société commerciale"
-        if($organization->getLegalStatus() === LegalEnum::COMMERCIAL_SOCIETY()->getValue()){
-            $organization->getBillingSetting()->setApplyVat(true);
-            $entityManager->getUnitOfWork()->computeChangeSet($entityManager->getClassMetadata(BillingSetting::class), $organization->getBillingSetting());
-        }
-    }
-}

+ 17 - 0
src/Message/Command/Parameters/AverageChange.php

@@ -0,0 +1,17 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Message\Command\Parameters;
+
+/**
+ * Classe AverageChange qui contiendras le message pour AverageChange
+ */
+class AverageChange
+{
+    public function __construct(private int $parametersId)
+    { }
+
+    public function getParametersId(){
+        return $this->parametersId;
+    }
+}

+ 20 - 0
src/Message/Handler/Parameters/AverageChangeHandler.php

@@ -0,0 +1,20 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Message\Handler\Parameters;
+
+use App\Message\Command\Parameters\AverageChange;
+use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
+
+class AverageChangeHandler implements MessageHandlerInterface
+{
+    public function __construct(
+    ) {}
+
+    public function __invoke(AverageChange $averageChange)
+    {
+        /**
+         * @todo Si on utilise toujours ES, il faut ici repopuler les educationNotations qui ont changées afin de mettre les bonnes notes
+         */
+    }
+}

+ 16 - 0
src/Repository/Education/EducationCurriculumRepository.php

@@ -0,0 +1,16 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Repository\Education;
+
+use App\Entity\Education\EducationCurriculum;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Persistence\ManagerRegistry;
+
+class EducationCurriculumRepository extends ServiceEntityRepository
+{
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, EducationCurriculum::class);
+    }
+}

+ 16 - 0
src/Repository/Education/EducationNotationConfigRepository.php

@@ -0,0 +1,16 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Repository\Education;
+
+use App\Entity\Education\EducationNotationConfig;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Persistence\ManagerRegistry;
+
+class EducationNotationConfigRepository extends ServiceEntityRepository
+{
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, EducationNotationConfig::class);
+    }
+}

+ 1 - 1
src/Repository/Organization/OrganizationAddressPostalRepository.php

@@ -27,7 +27,7 @@ class OrganizationAddressPostalRepository extends ServiceEntityRepository
      * @param Organization $organization
      * @return array|null
      */
-    public function getByType(String $type, Organization $organization): array | null{
+    public function getByType(String $type, Organization $organization): ?array{
         return $this->createQueryBuilder('organizationAddressPostal')
             ->where('organizationAddressPostal.type = :type')
             ->andWhere('organizationAddressPostal.organization = :organization')

+ 1 - 1
src/Service/Access/AdminAccessUtils.php

@@ -26,7 +26,7 @@ class AdminAccessUtils
      * @return AdminAccess|null
      * @see AdminAccessUtilsTest::testGetAdminAccess()
      */
-    public function getAdminAccess(Organization $organization): AdminAccess | null{
+    public function getAdminAccess(Organization $organization): ?AdminAccess{
         $administrator = $this->accessUtils->getAdminAccess($organization);
         if(!$administrator) return null;
 

+ 0 - 1
src/Service/Access/Utils.php

@@ -18,7 +18,6 @@ class Utils
 {
     public function __construct(
         private RoleHierarchyInterface $roleHierarchy,
-        private HandleOptionalsRoles $handleOptionalsRoles,
         private AccessRepository $accessRepository,
         private OptionalsRolesIterator $optionalsRolesIterator
     )

+ 7 - 3
src/Service/Core/ContactPointUtils.php

@@ -21,12 +21,16 @@ class ContactPointUtils
     /**
      * Renvoie le point de contact principal de l'Access passé en paramètre
      * @param Access $access
-     * @return array|null
+     * @return ContactPoint|null
      * @see ContactPointUtilsTest::testGetPersonContactPointPrincipal()
      */
-    public function getPersonContactPointPrincipal(Access $access): ContactPoint | null{
+    public function getPersonContactPointPrincipal(Access $access): ?ContactPoint{
         $contactPoint = $this->contactPointRepository->getByTypeAndPerson(ContactPointTypeEnum::PRINCIPAL()->getValue(), $access->getPerson());
         if(count($contactPoint) !== 1) return null;
-        else return $contactPoint[0];
+
+        if ($contactPoint[0] instanceof ContactPoint) {
+            return $contactPoint[0];
+        }
+        throw new \InvalidArgumentException('Value must be a ContactPoint');
     }
 }

+ 29 - 0
src/Service/Organization/OnOrganizationChange.php

@@ -0,0 +1,29 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Organization;
+
+use App\Entity\Organization\Organization;
+use App\Enum\Organization\LegalEnum;
+use App\Test\Service\Organization\OnOrganizationChangeTest;
+
+/**
+ * Classe OnOrganizationChange qui comporte toutes les opérations automatiquent se produisant lors de l'évolution d'une organisation
+ */
+class OnOrganizationChange
+{
+    /**
+     * Si le statut de l'organization évolue, on doit faire évoluer d'autre paramètres.
+     * @param Organization $organization
+     * @see OnOrganizationChangeTest::testOnLegalStatusChange()
+     */
+    public function onLegalStatusChange(Organization $organization): void{
+        if($organization->getLegalStatus() !== LegalEnum::ASSOCIATION_LAW_1901()->getValue()){
+            $organization->getParameters()->setShowAdherentList(false);
+        }
+
+        if($organization->getLegalStatus() === LegalEnum::COMMERCIAL_SOCIETY()->getValue()){
+            $organization->getBillingSetting()->setApplyVat(true);
+        }
+    }
+}

+ 40 - 0
src/Service/Organization/OnParametersChange.php

@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Service\Organization;
+
+use App\Entity\Education\EducationNotationConfig;
+use App\Entity\Organization\Parameters;
+use App\Enum\Education\AdvancedEducationNotationTypeEnum;
+use App\Repository\Education\EducationNotationConfigRepository;
+use App\Test\Service\Organization\OnParametersChangeTest;
+
+/**
+ * Classe OnParametersChange qui comporte toutes les opérations automatiquent se produisant lors de l'évolution des paramètres
+ */
+class OnParametersChange
+{
+    public function __construct(){ }
+
+    /**
+     * Si le le type de grilles d'évaluation évolue, il faut "nettoyer" les curriculums/teachers associés au type précédent
+     * @param Parameters $parameters
+     * @see OnParametersChangeTest::testOnAdvancedEducationNotationTypeByTeachers()
+     * @see OnParametersChangeTest::testOnAdvancedEducationNotationTypeByEducation()
+     */
+    public function onAdvancedEducationNotationType(Parameters $parameters): void {
+        foreach ($parameters->getOrganization()->getEducationNotationConfigs() as $educationNotationConfig){
+            /** @var EducationNotationConfig $educationNotationConfig */
+            if($parameters->getAdvancedEducationNotationType() === AdvancedEducationNotationTypeEnum::BY_TEACHER()->getValue()){
+                foreach ($educationNotationConfig->getEducationCurriculums() as $educationCurriculum){
+                    $educationCurriculum->setEducationNotationConfig(null);
+                }
+            }else{
+                foreach ($educationNotationConfig->getTeachers() as $teacher){
+                    $teacher->setEducationNotationConfig(null);
+                }
+            }
+        }
+    }
+}

+ 0 - 1
src/Service/ServiceIterator/CurrentAccessExtensionIterator.php

@@ -17,6 +17,5 @@ class CurrentAccessExtensionIterator{
             if($extension->support($operationName))
                 return $extension->addWhere($queryBuilder);
         }
-        throw new Exception('no extension found for this operation');
     }
 }

+ 1 - 1
tests/Service/Access/UtilsTest.php

@@ -31,7 +31,7 @@ class UtilsTest extends TestCase
 
         $this->accessRepositoryMock = $this->getMockBuilder(AccessRepository::class)->disableOriginalConstructor()->getMock();
 
-        $this->utils = new Utils($roleHierarchyMock, $optionalsRolesIteratorMock);
+        $this->utils = new Utils($roleHierarchyMock,  $this->accessRepositoryMock, $optionalsRolesIteratorMock);
     }
 
     /**

+ 1 - 1
tests/Service/Core/ContactPointUtilsTest.php

@@ -34,7 +34,7 @@ class ContactPointUtilsTest extends TestCase
         $this->contactPointRepositoryMock
             ->method('getByTypeAndPerson')
             ->with(ContactPointTypeEnum::PRINCIPAL()->getValue(), $access->getPerson())
-            ->willReturn(new ContactPoint());
+            ->willReturn([new ContactPoint()]);
 
         $this->assertInstanceOf(ContactPoint::class, $this->contactPointUtils->getPersonContactPointPrincipal($access));
     }

+ 39 - 0
tests/Service/Organization/OnOrganizationChangeTest.php

@@ -0,0 +1,39 @@
+<?php
+namespace App\Test\Service\Organization;
+
+use App\Entity\Billing\BillingSetting;
+use App\Entity\Organization\Organization;
+use App\Entity\Organization\Parameters;
+use App\Enum\Organization\LegalEnum;
+use App\Service\Organization\OnOrganizationChange;
+use PHPUnit\Framework\TestCase;
+
+class OnOrganizationChangeTest extends TestCase
+{
+    private Organization $organization;
+    private OnOrganizationChange $onOrganizationChange;
+
+    public function setUp():void
+    {
+        $this->organization = new Organization();
+        $this->onOrganizationChange = new OnOrganizationChange();
+    }
+
+    /**
+     * @see OnOrganizationChange::onLegalStatusChange()
+     */
+    public function testOnLegalStatusChange(){
+        $this->organization->setLegalStatus(LegalEnum::COMMERCIAL_SOCIETY()->getValue());
+        $parameters = new Parameters();
+        $parameters->setShowAdherentList(true);
+        $billingSettings = new BillingSetting();
+        $billingSettings->setApplyVat(false);
+        $this->organization->setParameters($parameters);
+        $this->organization->setBillingSetting($billingSettings);
+
+        $this->onOrganizationChange->onLegalStatusChange($this->organization);
+
+        $this->assertFalse($this->organization->getParameters()->getShowAdherentList());
+        $this->assertTrue($this->organization->getBillingSetting()->getApplyVat());
+    }
+}

+ 61 - 0
tests/Service/Organization/OnParametersChangeTest.php

@@ -0,0 +1,61 @@
+<?php
+namespace App\Test\Service\Organization;
+
+use App\Entity\Access\Access;
+use App\Entity\Education\EducationCurriculum;
+use App\Entity\Education\EducationNotationConfig;
+use App\Entity\Organization\Organization;
+use App\Entity\Organization\Parameters;
+use App\Enum\Education\AdvancedEducationNotationTypeEnum;
+use App\Service\Organization\OnParametersChange;
+use PHPUnit\Framework\TestCase;
+
+class OnParametersChangeTest extends TestCase
+{
+    private Parameters $parameters;
+    private OnParametersChange $onParametersChange;
+
+    public function setUp():void
+    {
+        $this->parameters = new Parameters();
+        $this->onParametersChange = new OnParametersChange();
+    }
+
+    /**
+     * @see OnParametersChange::onAdvancedEducationNotationType()
+     */
+    public function testOnAdvancedEducationNotationTypeByTeachers(){
+        $educationNotationConfig = new EducationNotationConfig();
+        $educationCurriculum = new EducationCurriculum();
+        $educationNotationConfig->addEducationCurriculum($educationCurriculum);
+
+        $organization = new Organization();
+        $organization->addEducationNotationConfig($educationNotationConfig);
+
+        $this->parameters->setAdvancedEducationNotationType(AdvancedEducationNotationTypeEnum::BY_TEACHER()->getValue());
+        $this->parameters->setOrganization($organization);
+
+        $this->assertCount(1, $educationNotationConfig->getEducationCurriculums());
+        $this->onParametersChange->onAdvancedEducationNotationType($this->parameters);
+        $this->assertNull($educationNotationConfig->getEducationCurriculums()->first()->getEducationNotationConfig());
+    }
+
+    /**
+     * @see OnParametersChange::onAdvancedEducationNotationType()
+     */
+    public function testOnAdvancedEducationNotationTypeByEducation(){
+        $educationNotationConfig = new EducationNotationConfig();
+        $teacher = new Access();
+        $educationNotationConfig->addTeacher($teacher);
+
+        $organization = new Organization();
+        $organization->addEducationNotationConfig($educationNotationConfig);
+
+        $this->parameters->setAdvancedEducationNotationType(AdvancedEducationNotationTypeEnum::BY_EDUCATION()->getValue());
+        $this->parameters->setOrganization($organization);
+
+        $this->assertCount(1, $educationNotationConfig->getTeachers());
+        $this->onParametersChange->onAdvancedEducationNotationType($this->parameters);
+        $this->assertNull($educationNotationConfig->getTeachers()->first()->getEducationNotationConfig());
+    }
+}

+ 0 - 21
tests/Service/ServiceIterator/CurrentAccessExtensionIteratorTest.php

@@ -31,25 +31,4 @@ class CurrentAccessExtensionIteratorTest extends TestCase
 
         $this->assertEquals(true, $actualExt);
     }
-
-    public function testAddWhereError() {
-        $queryBuilder = $this->getMockBuilder(QueryBuilder::class)
-            ->disableOriginalConstructor()
-            ->getMock();
-
-        $mocker = $this->getMockBuilder(AccessExtensionInterface::class);
-
-        $ext1 = $mocker->getMock();
-        $ext1->method('support')->willReturn(false);
-
-        $ext2 = $mocker->getMock();
-        $ext2->method('support')->willReturn(false);
-
-        $extensions = [$ext1, $ext2];
-
-        $iterator = new CurrentAccessExtensionIterator($extensions);
-
-        $this->expectException(Exception::class);
-        $iterator->addWhere($queryBuilder, 'foo');
-    }
 }