Browse Source

Merge branch 'feature/Bttf-51' into develop

Vincent GUFFON 4 years ago
parent
commit
7529b6cea4
33 changed files with 855 additions and 89 deletions
  1. 29 12
      config/packages/doctrine.yaml
  2. 7 0
      src/ApiResources/ApiResourcesInterface.php
  3. 68 0
      src/ApiResources/Cotisation/Cotisation.php
  4. 3 1
      src/ApiResources/Dolibarr/DolibarrAccount.php
  5. 8 2
      src/ApiResources/Dolibarr/DolibarrBill.php
  6. 8 2
      src/ApiResources/Dolibarr/DolibarrContract.php
  7. 8 2
      src/ApiResources/Dolibarr/DolibarrContractLine.php
  8. 2 1
      src/ApiResources/Enum/Enum.php
  9. 3 1
      src/ApiResources/Mobyt/MobytUserStatus.php
  10. 3 1
      src/ApiResources/Profile/AccessProfile.php
  11. 23 2
      src/ApiResources/Profile/OrganizationProfile.php
  12. 2 1
      src/ApiResources/Utils/GpsCoordinate.php
  13. 2 1
      src/ApiResources/Utils/Siret.php
  14. 34 0
      src/DataProvider/Cotisation/CotisationDataProvider.php
  15. 1 0
      src/Entity/Access/Access.php
  16. 6 3
      src/Entity/Core/Notification.php
  17. 4 5
      src/Entity/Traits/ActivityPeriodTrait.php
  18. 17 0
      src/Enum/Cotisation/AlertStateEnum.php
  19. 57 0
      src/EventSubscriber/ApiResourcesValidatorSubscriber.php
  20. 87 0
      src/Repository/Cotisation/CotisationApiResourcesRepository.php
  21. 51 0
      src/Security/Voter/CotisationVoter.php
  22. 1 1
      src/Service/Access/AccessProfileCreator.php
  23. 35 0
      src/Service/Cotisation/CotisationCreator.php
  24. 74 10
      src/Service/Cotisation/Utils.php
  25. 24 2
      src/Service/Network/Utils.php
  26. 6 3
      src/Service/Organization/OrganizationProfileCreator.php
  27. 22 0
      src/Service/Organization/Utils.php
  28. 4 4
      src/Service/Utils/DatesUtils.php
  29. 194 8
      tests/Service/Cotisation/UtilsTest.php
  30. 29 0
      tests/Service/Network/UtilsTest.php
  31. 17 0
      tests/Service/Organization/UtilsTest.php
  32. 0 27
      tests/Service/Utils/DatesTest.php
  33. 26 0
      tests/Service/Utils/DatesUtilsTest.php

+ 29 - 12
config/packages/doctrine.yaml

@@ -1,17 +1,34 @@
 doctrine:
     dbal:
-        url: '%env(resolve:DATABASE_URL)%'
+        default_connection: default
+        connections:
+            default:
+                url: '%env(resolve:DATABASE_URL)%'
+
+                # IMPORTANT: You MUST configure your server version,
+                # either here or in the DATABASE_URL env var (see .env file)
+                server_version: '5.7'
+
+            adminassos:
+                url: '%env(resolve:DATABASE_ADMINASSOS_URL)%'
+
+                # IMPORTANT: You MUST configure your server version,
+                # either here or in the DATABASE_URL env var (see .env file)
+                server_version: '5.7'
 
-        # IMPORTANT: You MUST configure your server version,
-        # either here or in the DATABASE_URL env var (see .env file)
-        server_version: '5.7'
     orm:
+        default_entity_manager: default
         auto_generate_proxy_classes: true
-        auto_mapping: true
-        mappings:
-            App:
-                is_bundle: false
-                type: attribute
-                dir: '%kernel.project_dir%/src/Entity'
-                prefix: 'App\Entity'
-                alias: App
+        entity_managers:
+            default:
+                connection: default
+                auto_mapping: true
+                mappings:
+                    App:
+                        is_bundle: false
+                        type: attribute
+                        dir: '%kernel.project_dir%/src/Entity'
+                        prefix: 'App\Entity'
+                        alias: App
+            adminassos:
+                connection: adminassos

+ 7 - 0
src/ApiResources/ApiResourcesInterface.php

@@ -0,0 +1,7 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources;
+
+interface ApiResourcesInterface{
+}

+ 68 - 0
src/ApiResources/Cotisation/Cotisation.php

@@ -0,0 +1,68 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Cotisation;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Classe resource qui contient les informations des cotisations de la 5.9
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get' => [
+            'method' => 'GET',
+            'path' => '/cotisations/{organizationId}',
+            'security' => 'is_granted("COTISATION_CALL", object)',
+        ]
+    ]
+)]
+class Cotisation implements ApiResourcesInterface
+{
+    #[ApiProperty(identifier: true)]
+    private int $organizationId;
+
+    #[Assert\Choice(callback: ['\App\Enum\Cotisation\AlertStateEnum', 'toArray'], message: 'invalid-alert-state-enum')]
+    private ?string $alertState = null;
+
+    private ?int $cotisationYear = null;
+
+    public function getOrganizationId(): ?int
+    {
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(?int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+        return $this;
+    }
+
+    public function getAlertState(): ?string
+    {
+        return $this->alertState;
+    }
+
+    public function setAlertState(?string $alertState): self
+    {
+        $this->alertState = $alertState;
+        return $this;
+    }
+
+    public function getCotisationYear(): ?int
+    {
+        return $this->cotisationYear;
+    }
+
+    public function setCotisationYear(?int $cotisationYear): self
+    {
+        $this->cotisationYear = $cotisationYear;
+
+        return $this;
+    }
+}

+ 3 - 1
src/ApiResources/Dolibarr/DolibarrAccount.php

@@ -5,6 +5,7 @@ namespace App\ApiResources\Dolibarr;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use JetBrains\PhpStorm\Pure;
@@ -15,6 +16,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
  * (aussi nommé 'ThirdParty' ou 'Society' dans dolibarr)
  */
 #[ApiResource(
+    collectionOperations:[],
     itemOperations: [
         'get' => [
             'security' => '(is_granted("ROLE_ADMIN_CORE") or 
@@ -32,7 +34,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
     ],
     compositeIdentifier: false,
 )]
-class DolibarrAccount
+class DolibarrAccount implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     #[Groups('dolibarr_get')]

+ 8 - 2
src/ApiResources/Dolibarr/DolibarrBill.php

@@ -5,13 +5,19 @@ namespace App\ApiResources\Dolibarr;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
  * Bill of a society, retrieved from dolibarr
  */
-#[ApiResource]
-class DolibarrBill
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class DolibarrBill implements ApiResourcesInterface
 {
     /**
      * Id of the dolibarr bill ( = invoice)

+ 8 - 2
src/ApiResources/Dolibarr/DolibarrContract.php

@@ -5,6 +5,7 @@ namespace App\ApiResources\Dolibarr;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use JetBrains\PhpStorm\Pure;
@@ -13,8 +14,13 @@ use Symfony\Component\Serializer\Annotation\Groups;
 /**
  * Contract of a society, retrieved from dolibarr
  */
-#[ApiResource]
-class DolibarrContract
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class DolibarrContract implements ApiResourcesInterface
 {
     /**
      * Reference of the dolibarr contract

+ 8 - 2
src/ApiResources/Dolibarr/DolibarrContractLine.php

@@ -5,13 +5,19 @@ namespace App\ApiResources\Dolibarr;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
  *  Lines (services) included in a society contract, as retrieved from dolibarr
  */
-#[ApiResource]
-class DolibarrContractLine
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class DolibarrContractLine implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     #[Groups('dolibarr_get')]

+ 2 - 1
src/ApiResources/Enum/Enum.php

@@ -5,6 +5,7 @@ namespace App\ApiResources\Enum;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 
 /**
  * Classe resource qui contient les champs disponibles lors d'un appel à enum.
@@ -18,7 +19,7 @@ use ApiPlatform\Core\Annotation\ApiResource;
         ]
     ]
 )]
-class Enum
+class Enum implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     private string $name;

+ 3 - 1
src/ApiResources/Mobyt/MobytUserStatus.php

@@ -5,12 +5,14 @@ namespace App\ApiResources\Mobyt;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
  * Statut de l'utilisateur Mobyt correspondant à l'organization donnée en paramètre
  */
 #[ApiResource(
+    collectionOperations:[],
     itemOperations: [
         'get' => [
             'security' => 'is_granted("ROLE_TEXTO") and object.getOrganizationId() == user.getOrganization().getId()',
@@ -20,7 +22,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
         ],
     ]
 )]
-class MobytUserStatus
+class MobytUserStatus implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     private int $organizationId;

+ 3 - 1
src/ApiResources/Profile/AccessProfile.php

@@ -5,6 +5,7 @@ namespace App\ApiResources\Profile;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Serializer\Annotation\Groups;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -14,6 +15,7 @@ use Doctrine\Common\Collections\Collection;
  * Classe resource qui contient les champs disponibles lors d'un appel à my_profile.
  */
 #[ApiResource(
+    collectionOperations:[],
     itemOperations: [
         'get' => [
             'normalization_context' => [
@@ -25,7 +27,7 @@ use Doctrine\Common\Collections\Collection;
         ]
     ]
 )]
-class AccessProfile
+class AccessProfile implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     #[Groups('access_profile_read')]

+ 23 - 2
src/ApiResources/Profile/OrganizationProfile.php

@@ -4,6 +4,7 @@ declare(strict_types=1);
 namespace App\ApiResources\Profile;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
+use App\ApiResources\ApiResourcesInterface;
 use Symfony\Component\Serializer\Annotation\Groups;
 use ApiPlatform\Core\Annotation\ApiResource;
 
@@ -11,8 +12,13 @@ use ApiPlatform\Core\Annotation\ApiResource;
  * Classe resource qui contient les champs relatifs aux organizations présentent dans la requete my_profile.
  */
 
-#[ApiResource]
-class OrganizationProfile
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class OrganizationProfile implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     #[Groups('access_profile_read')]
@@ -45,6 +51,9 @@ class OrganizationProfile
     #[Groups('access_profile_read')]
     private bool $showAdherentList = false;
 
+    #[Groups('access_profile_read')]
+    private ?int $currentYear = null;
+
     public function getId(): ?int
     {
         return $this->id;
@@ -164,4 +173,16 @@ class OrganizationProfile
 
         return $this;
     }
+
+    public function getCurrentYear(): ?int
+    {
+        return $this->currentYear;
+    }
+
+    public function setCurrentYear(?int $currentYear): self
+    {
+        $this->currentYear = $currentYear;
+
+        return $this;
+    }
 }

+ 2 - 1
src/ApiResources/Utils/GpsCoordinate.php

@@ -5,6 +5,7 @@ namespace App\ApiResources\Utils;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 
 /**
  * Classe resource qui contient les champs de recherche des coordonnées GPS d'une adresse
@@ -24,7 +25,7 @@ use ApiPlatform\Core\Annotation\ApiResource;
     ],
     compositeIdentifier: false
 )]
-class GpsCoordinate
+class GpsCoordinate implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     private float $latitude;

+ 2 - 1
src/ApiResources/Utils/Siret.php

@@ -5,6 +5,7 @@ namespace App\ApiResources\Utils;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 
 /**
  * Classe resource qui contient les champs de vérification d'un siret
@@ -19,7 +20,7 @@ use ApiPlatform\Core\Annotation\ApiResource;
         ]
     ]
 )]
-class Siret
+class Siret implements ApiResourcesInterface
 {
     #[ApiProperty(identifier: true)]
     private ?string $number = null;

+ 34 - 0
src/DataProvider/Cotisation/CotisationDataProvider.php

@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\DataProvider\Cotisation;
+
+use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use App\ApiResources\Cotisation\Cotisation;
+use App\Service\Cotisation\CotisationCreator;
+
+/**
+ * Class CotisationDataProvider : custom provider pour assurer l'alimentation de la réponse du GET cotisation
+ * @package App\DataProvider\Cotisation
+ */
+final class CotisationDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
+{
+    public function __construct(private CotisationCreator $cotisationCreator)
+    { }
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return Cotisation::class === $resourceClass;
+    }
+
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?Cotisation
+    {
+        try {
+            return $this->cotisationCreator->getCotisation($id);
+        } catch (\Exception $e) {
+            return null;
+        }
+    }
+}

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

@@ -59,6 +59,7 @@ class Access implements UserInterface
     private bool $adminAccess = false;
 
     #[ORM\Column(nullable: true)]
+    #[Groups(['my_access:input'])]
     private ?int $activityYear = null;
 
     #[ORM\ManyToOne(cascade: ['persist'])]

+ 6 - 3
src/Entity/Core/Notification.php

@@ -52,7 +52,7 @@ class Notification
     private ?string $name = null;
 
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
-    private ?array $message = [];
+    private mixed $message = [];
 
     #[ORM\Column(nullable: true)]
     #[Assert\Choice(callback: ['\App\Enum\Core\NotificationTypeEnum', 'toArray'], message: 'invalid-type')]
@@ -99,14 +99,17 @@ class Notification
         return $this->recipientAccess;
     }
 
-    public function setMessage(?array $message): self
+    public function setMessage(mixed $message): self
     {
         $this->message = $message;
         return $this;
     }
 
-    public function getMessage(): ?array
+    public function getMessage(): mixed
     {
+        if(!is_array( $this->message)){
+            return ['about' => $this->message];
+        }
         return $this->message;
     }
 

+ 4 - 5
src/Entity/Traits/ActivityPeriodTrait.php

@@ -4,7 +4,6 @@ declare(strict_types=1);
 namespace App\Entity\Traits;
 
 use Doctrine\ORM\Mapping as ORM;
-use Symfony\Component\Validator\Constraints as Assert;
 
 trait ActivityPeriodTrait
 {
@@ -14,8 +13,8 @@ trait ActivityPeriodTrait
     #[ORM\Column(type: 'date', nullable: true)]
     private ?\DateTimeInterface $endDate = null;
 
-    public function getStartDate(): ?string {
-        return $this->startDate?->format('Y-m-d');
+    public function getStartDate(): ?\DateTimeInterface {
+        return $this->startDate;
     }
 
     public function setStartDate(?\DateTime $startDate = null): self {
@@ -24,8 +23,8 @@ trait ActivityPeriodTrait
         return $this;
     }
 
-    public function getEndDate(): ?string {
-        return $this->endDate?->format('Y-m-d');
+    public function getEndDate(): ?\DateTimeInterface {
+        return $this->endDate;
     }
 
     public function setEndDate(?\DateTime $endDate = null) :self {

+ 17 - 0
src/Enum/Cotisation/AlertStateEnum.php

@@ -0,0 +1,17 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Cotisation;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * état des alertes des cotisations disponibles.
+ */
+class AlertStateEnum extends Enum
+{
+    private const AFFILIATION ='AFFILIATION';
+    private const INVOICE ='INVOICE';
+    private const INSURANCE = 'INSURANCE';
+    private const ADVERTISINGINSURANCE = 'ADVERTISINGINSURANCE';
+}

+ 57 - 0
src/EventSubscriber/ApiResourcesValidatorSubscriber.php

@@ -0,0 +1,57 @@
+<?php
+declare(strict_types=1);
+
+namespace App\EventSubscriber;
+
+use ApiPlatform\Core\EventListener\EventPriorities;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\ViewEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
+
+/**
+ * Class ApiResourcesValidatorSubscriber : EventSubscriber qui déploit le system de validator de symfony si la resource est une instance de ApiResources
+ * @package App\EventSubscriber
+ */
+final class ApiResourcesValidatorSubscriber implements EventSubscriberInterface
+{
+    public function __construct(private  ValidatorInterface $validator)
+    {
+    }
+
+    /**
+     * ne se déclenche qu'après le post validate d'api platform
+     * @return array[]
+     */
+    public static function getSubscribedEvents()
+    {
+        return [
+            KernelEvents::VIEW => ['validate', EventPriorities::POST_VALIDATE],
+        ];
+    }
+
+    /**
+     * Si l'entité est une instance de ApiResourcesInterface, alors on active le validator
+     * @param ViewEvent $event
+     * @throws \Exception
+     */
+    public function validate(ViewEvent $event): void
+    {
+        $entity = $event->getControllerResult();
+
+        if(!$entity instanceof ApiResourcesInterface)
+            return;
+
+        $violations = $this->validator->validate($entity);
+
+        if (0 !== count($violations)) {
+            $messages = [];
+            // there are errors, now you can show them
+            foreach ($violations as $violation) {
+                $messages[] = $violation->getMessage();
+            }
+            throw new \Exception(join(',', $messages), 500);
+        }
+    }
+}

+ 87 - 0
src/Repository/Cotisation/CotisationApiResourcesRepository.php

@@ -0,0 +1,87 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Repository\Cotisation;
+
+
+use Doctrine\ORM\EntityManagerInterface;
+use Doctrine\ORM\Query\ResultSetMapping;
+
+final class CotisationApiResourcesRepository
+{
+    public function __construct(private EntityManagerInterface $adminassosEntityManager)
+    {
+    }
+
+    /**
+     * Récupère l'état de la cotisation pour une structure et une année
+     * @param int $organizationId
+     * @param int $year
+     * @return string|null
+     */
+    public function getAffiliationState(int $organizationId, int $year): string|null {
+        $rsm = new ResultSetMapping();
+        $rsm->addScalarResult('oa_miscellaneous_state_sta', 'oa_miscellaneous_state_sta');
+
+        $sql = sprintf('SELECT oa_miscellaneous_state_sta as oa_miscellaneous_state_sta '
+            . ' FROM oa_assos_state '
+            . ' WHERE pid = %s AND year_sta = %s', $organizationId, $year);
+        $query = $this->adminassosEntityManager->createNativeQuery($sql, $rsm);
+        $result = $query->getOneOrNullResult();
+
+        if (!empty($result)) {
+            return $result['oa_miscellaneous_state_sta'];
+        }
+        return null;
+    }
+
+    /**
+     * Retourne vrai si la structure n'a pas rempli son assurance pour une année
+     * @param int $organizationId
+     * @param int $year
+     * @return bool
+     */
+    public function isInsuranceNotDone(int $organizationId, int $year): bool {
+        $rsm = new ResultSetMapping();
+        $rsm->addScalarResult('done', 'done');
+
+        $sql = sprintf('SELECT done as done '
+            . ' FROM oa_contribution_fede_insurance '
+            . ' INNER JOIN oa_assos ON oa_contribution_fede_insurance.pid = oa_assos.pid '
+            . ' INNER JOIN dgv_assurance ON declare_nb_fed_aso = id_unique_dgv '
+            . ' WHERE oa_contribution_fede_insurance.pid = %s AND year_cfi = %s ', $organizationId, $year);
+
+        $query = $this->adminassosEntityManager->createNativeQuery($sql, $rsm);
+        $result = $query->getOneOrNullResult();
+
+        if (!empty($result)) {
+            return $result['done'] == 0;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Retourne vrai si la structure n'est pas un client DGV
+     * @param int $organizationId
+     * @return bool
+     */
+    public function isNotDGVCustomer(int $organizationId):bool {
+        $rsm = new ResultSetMapping();
+        $rsm->addScalarResult('total', 'total');
+
+        $sql = sprintf('SELECT COUNT(*) as total '
+            . ' FROM dgv_assurance '
+            . ' INNER JOIN oa_assos ON declare_nb_fed_aso = id_unique_dgv '
+            . ' WHERE pid = %s ', $organizationId);
+
+        $query = $this->adminassosEntityManager->createNativeQuery($sql, $rsm);
+        $result = $query->getOneOrNullResult();
+
+        if (!empty($result)) {
+            return $result['total'] == 0;
+        } else {
+            return true;
+        }
+    }
+}

+ 51 - 0
src/Security/Voter/CotisationVoter.php

@@ -0,0 +1,51 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Security\Voter;
+
+use App\ApiResources\Cotisation\Cotisation;
+use App\Entity\Access\Access;
+use App\Enum\Network\NetworkEnum;
+use App\Service\Network\Utils;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authorization\Voter\Voter;
+use Symfony\Component\Security\Core\Security;
+use Symfony\Component\Security\Core\User\UserInterface;
+
+class CotisationVoter extends Voter
+{
+    public function __construct(
+        private Security $security,
+        private Utils $networkUtils)
+    { }
+
+    protected function supports($attribute, $subject): bool
+    {
+        return in_array($attribute, ['COTISATION_CALL']) && $subject instanceof Cotisation;
+    }
+
+    /**
+     * @param string $attribute
+     * @param mixed $subject
+     * @param TokenInterface $token
+     * @return bool
+     */
+    protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
+    {
+        /** @var Access $user */
+        $user = $token->getUser();
+        // if the user is anonymous, do not grant access
+        if (!$user instanceof UserInterface) {
+            return false;
+        }
+
+        if($subject->getOrganizationId() !== $user->getOrganization()->getId()){
+            return false;
+        }
+
+        return $this->security->isGranted('ROLE_COTISATION') &&
+            $this->networkUtils->isCMFAndActiveNow($user->getOrganization());
+    }
+
+
+}

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

@@ -12,7 +12,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
 
 /**
  * Class AccessProfileCreator : Service contenant les manipulations associés à la ressource AccessProfile
- * @package App\Service\ProfileCreator
+ * @package App\Service\Access
  */
 class AccessProfileCreator
 {

+ 35 - 0
src/Service/Cotisation/CotisationCreator.php

@@ -0,0 +1,35 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Cotisation;
+
+use App\ApiResources\Cotisation\Cotisation;
+use App\Repository\Organization\OrganizationRepository;
+
+
+/**
+ * Class CotisationCreator : Service contenant les manipulations associés à la ressource Cotisation
+ * @package App\Service\Cotisation
+ */
+class CotisationCreator
+{
+    public function __construct(
+        private OrganizationRepository $organizationRepository,
+        private Utils $cotisationUtils
+    )
+    { }
+
+    public function getCotisation(int $organizationId): Cotisation{
+        $cotisation = new Cotisation();
+        $cotisation->setOrganizationId($organizationId);
+        $cotisation->setCotisationYear($this->cotisationUtils->getCurrentCotisationYear());
+
+        $organization = $this->organizationRepository->find($organizationId);
+        $cotisation->setAlertState($this->cotisationUtils->getAlertState(
+            $organization,
+            $cotisation->getCotisationYear())
+        );
+
+        return $cotisation;
+    }
+}

+ 74 - 10
src/Service/Cotisation/Utils.php

@@ -4,6 +4,8 @@ declare(strict_types=1);
 namespace App\Service\Cotisation;
 
 use App\Entity\Organization\Organization;
+use App\Enum\Cotisation\AlertStateEnum;
+use App\Repository\Cotisation\CotisationApiResourcesRepository;
 use App\Repository\Network\NetworkOrganizationRepository;
 use App\Service\Organization\Utils as OrganizationUtils;
 use App\Tests\Service\Cotisation\UtilsTest;
@@ -13,12 +15,20 @@ use App\Service\Network\Utils as NetworkUtils;
  * Class Utils : Service rassemblant des fonctions d'interrogation pour gérer des conditions dans les Cotisations
  * @package App\Service\Cotisation
  */
-class Utils {
+class Utils
+{
+    const MEMBERSHIP_WAITING = 495; // Affiliation in progress
+    const MEMBERSHIP_NOPAYMENT = 517; // Waiting paiement
+    const SUBMIT_IN_PROGRESS = 540; // Affiliation in progress
+
     function __construct(
-        private NetworkUtils $networkUtils,
-        private OrganizationUtils $organizationUtils,
-        private NetworkOrganizationRepository $networkOrganizationRepository
-    ) { }
+        private NetworkUtils                     $networkUtils,
+        private OrganizationUtils                $organizationUtils,
+        private NetworkOrganizationRepository    $networkOrganizationRepository,
+        private CotisationApiResourcesRepository $cotisationApiResourcesRepository
+    )
+    {
+    }
 
     /**
      * Test si l'organisation est un dernier parent ET appartient à la CMF.
@@ -26,7 +36,8 @@ class Utils {
      * @return bool
      * @see UtilsTest::testIsLastParentAndCMF()
      */
-    public function isLastParentAndCMF(Organization $organization): bool {
+    public function isLastParentAndCMF(Organization $organization): bool
+    {
         return $this->networkOrganizationRepository->isLastParent($organization) && $this->networkUtils->isCMF($organization);
     }
 
@@ -36,7 +47,8 @@ class Utils {
      * @return bool
      * @see UtilsTest::testIsStructureAndCMF()
      */
-    public function isStructureAndCMF(Organization $organization):bool {
+    public function isStructureAndCMF(Organization $organization): bool
+    {
         return $this->organizationUtils->isStructure($organization) && $this->networkUtils->isCMF($organization);
     }
 
@@ -46,7 +58,8 @@ class Utils {
      * @return bool
      * @see UtilsTest::testIsManagerAndCMF()
      */
-    public function isManagerAndCMF(Organization $organization): bool{
+    public function isManagerAndCMF(Organization $organization): bool
+    {
         return $this->organizationUtils->isManager($organization) && $this->networkUtils->isCMF($organization);
     }
 
@@ -56,7 +69,8 @@ class Utils {
      * @return bool
      * @see UtilsTest::testIsManagerAndLastParentAndCMF()
      */
-    public function isManagerAndLastParentAndCMF(Organization $organization): bool {
+    public function isManagerAndLastParentAndCMF(Organization $organization): bool
+    {
         return $this->organizationUtils->isManager($organization) && $this->isLastParentAndCMF($organization);
     }
 
@@ -66,7 +80,57 @@ class Utils {
      * @return bool
      * @see UtilsTest::testIsManagerAndNotLastParentAndCMF()
      */
-    public function isManagerAndNotLastParentAndCMF(Organization $organization): bool {
+    public function isManagerAndNotLastParentAndCMF(Organization $organization): bool
+    {
         return $this->organizationUtils->isManager($organization) && !$this->isLastParentAndCMF($organization);
     }
+
+
+    /**
+     * Retourne le niveau d'alerte de l'appel de cotisation pour une année.
+     * @param Organization $organization
+     * @param int $year
+     * @return string|null
+     * @see UtilsTest::testGetAlertStateAffiliation()
+     */
+    public function getAlertState(Organization $organization, int $year)
+    {
+        $state = $this->cotisationApiResourcesRepository->getAffiliationState($organization->getId(), $year);
+
+        $alertState = null;
+
+        if ($state == self::MEMBERSHIP_WAITING || $state == self::SUBMIT_IN_PROGRESS) {
+            $alertState = AlertStateEnum::AFFILIATION()->getValue();
+        } else if ($state == self::MEMBERSHIP_NOPAYMENT) {
+            $alertState = AlertStateEnum::INVOICE()->getValue();
+        } else if ($this->cotisationApiResourcesRepository->isInsuranceNotDone($organization->getId(), $year)) {
+            $alertState = AlertStateEnum::INSURANCE()->getValue();
+        } else if ($this->cotisationApiResourcesRepository->isNotDGVCustomer($organization->getId())) {
+            $alertState = AlertStateEnum::ADVERTISINGINSURANCE()->getValue();
+        }
+
+        return $alertState;
+    }
+
+    /**
+     * Retourne dans quelle année de cotisation on est aujourd'hui
+     * @return int
+     * @throws \Exception
+     * @see UtilsTest::testGetCurrentCotisationYear()
+     */
+    public function getCurrentCotisationYear(): int {
+        $today = new \DateTime('now');
+        $year = intval($today->format('Y'));
+
+        $base_date = new \DateTime($year . '-09-01');
+        $dateStart = new \DateTime($year . '-01-01');
+
+        if ($today >= $dateStart && $today <= $base_date) {
+            $cotisationYear = $year;
+        } else {
+            $cotisationYear = $year + 1;
+        }
+
+        return $cotisationYear;
+    }
 }

+ 24 - 2
src/Service/Network/Utils.php

@@ -6,6 +6,7 @@ namespace App\Service\Network;
 use App\Entity\Network\NetworkOrganization;
 use App\Entity\Organization\Organization;
 use App\Enum\Network\NetworkEnum;
+use App\Service\Utils\DatesUtils;
 use App\Tests\Service\Network\UtilsTest;
 
 /**
@@ -24,21 +25,42 @@ class Utils
         return $this->isOrganizationBelongToTheNetwork($organization, NetworkEnum::CMF());
     }
 
+    /**
+     * Test si l'organisation appartient au réseau de la CMF Actuellement
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsCmfAndActiveNow()
+     */
+    public function isCMFAndActiveNow(Organization $organization): bool {
+        return $this->isOrganizationBelongToTheNetwork($organization, NetworkEnum::CMF(), true);
+    }
+
     /**
      * Test si l'organisation appartient à un réseau
      * @param Organization $organization
      * @param NetworkEnum $network  id du réseau
+     * @param bool $activeNow  si true, on test en plus l'activité aujourd'hui
      * @return boolean
      * @see UtilsTest::testIsOrganizationBelongToTheNetwork()
      */
-    public function isOrganizationBelongToTheNetwork(Organization $organization, NetworkEnum $network): bool {
+    public function isOrganizationBelongToTheNetwork(Organization $organization, NetworkEnum $network, ?bool $activeNow = false): bool {
         $networksOrganizations = $organization->getNetworkOrganizations();
         /** @var NetworkOrganization $networksOrganization */
         foreach ($networksOrganizations as $networksOrganization) {
             if ($networksOrganization->getNetwork()->getId() === $network->getValue()) {
-                return true;
+                return $activeNow ? $this->doesNetworkOrganizationIsActiveNow($networksOrganization) : true;
             }
         }
         return false;
     }
+
+
+    /**
+     * @param NetworkOrganization $networksOrganization
+     * @return bool
+     * @throws \Exception
+     */
+    public function doesNetworkOrganizationIsActiveNow(NetworkOrganization $networksOrganization): bool{
+        return DatesUtils::isIntervalIsValidNow($networksOrganization->getStartDate(), $networksOrganization->getEndDate());
+    }
 }

+ 6 - 3
src/Service/Organization/OrganizationProfileCreator.php

@@ -6,20 +6,20 @@ namespace App\Service\Organization;
 use App\ApiResources\Profile\OrganizationProfile;
 use App\Entity\Organization\Organization;
 use App\Enum\Organization\PrincipalTypeEnum;
-use App\Enum\Organization\TypeEstablishmentDetailEnum;
 use App\Service\Network\Tree;
 use App\Service\Security\Module;
+use App\Service\Organization\Utils as organizationUtils;
 use App\Test\Service\Organization\OrganizationProfileCreatorTest;
 
 /**
  * Class OrganizationProfileCreator : Service contenant les manipulations associés à la ressource OrganizationProfile
- * @package App\Service\ProfileCreator
+ * @package App\Service\Organization
  */
 class OrganizationProfileCreator
 {
     public function __construct(
         private Module $module,
-        private Tree $tree
+        private Tree $tree,
     )
     { }
 
@@ -45,6 +45,9 @@ class OrganizationProfileCreator
             $parentProfile = $this->createLightOrganizationProfile($parent);
             $organizationProfile->addParent($parentProfile);
         }
+
+        $organizationProfile->setCurrentYear(organizationUtils::getOrganizationCurrentActivityYear($organization));
+
         return $organizationProfile;
     }
 

+ 22 - 0
src/Service/Organization/Utils.php

@@ -64,4 +64,26 @@ class Utils
     private function isOrganizationIdIs(Organization $organization, OrganizationIdsEnum $organizationIdsEnum){
         return $organization->getId() === $organizationIdsEnum->getValue();
     }
+
+    /**
+     * Retourne dans quelles année d'activité on se situe aujourd'hui
+     * @param Organization $organization
+     * @return int
+     * @throws \Exception
+     * @see UtilsTest::testGetOrganizationCurrentActivityYear()
+     */
+    public static function getOrganizationCurrentActivityYear(Organization $organization): int{
+        $musicalDate = $organization->getParameters()->getMusicalDate();
+        if(empty($musicalDate)) $musicalDate = new \DateTime('now');
+
+        $today = new \DateTime();
+        $year = intval($today->format('Y'));
+        $base_date = new \DateTime($musicalDate->format($year.'-m-d'));
+        $dateStart = new \DateTime($year . '-01-01');
+
+        if($today >= $dateStart && $today < $base_date)
+            return $year - 1;
+
+        else return $year;
+    }
 }

+ 4 - 4
src/Service/Utils/Dates.php → src/Service/Utils/DatesUtils.php

@@ -7,17 +7,17 @@ namespace App\Service\Utils;
  * Class Dates : méthodes d'aide pour la gestion de dates.
  * @package App\Service\Utils
  */
-class Dates
+class DatesUtils
 {
     /**
-     * Vérifie si la date du jour est comprise dans l'inerval passé en paramètres
+     * Vérifie si la date du jour est comprise dans l'interval passé en paramètres
      * @param \DateTime $dateStart
      * @param \DateTime $dateEnd
      * @return bool
      * @throws \Exception
-     * @see DatesTest::testIsIntervalIsValidNow()
+     * @see DatesUtilsTest::testIsIntervalIsValidNow()
      */
-    public function isIntervalIsValidNow(\DateTime $dateStart, \DateTime $dateEnd = null): bool {
+    public static function isIntervalIsValidNow(\DateTimeInterface $dateStart, \DateTimeInterface $dateEnd = null): bool {
         $now = new \DateTime('now');
         return $dateStart <= $now && (is_null($dateEnd) || $dateEnd >= $now);
     }

+ 194 - 8
tests/Service/Cotisation/UtilsTest.php

@@ -3,6 +3,8 @@
 namespace App\Tests\Service\Cotisation;
 
 use App\Entity\Organization\Organization;
+use App\Enum\Cotisation\AlertStateEnum;
+use App\Repository\Cotisation\CotisationApiResourcesRepository;
 use App\Repository\Network\NetworkOrganizationRepository;
 use App\Service\Cotisation\Utils;
 use App\Service\Organization\Utils as OrganizationUtils;
@@ -11,6 +13,10 @@ use \App\Service\Network\Utils as NetworkUtils;
 
 class UtilsTest extends TestCase
 {
+    const MEMBERSHIP_WAITING = 495; // Affiliation in progress
+    const MEMBERSHIP_NOPAYMENT = 517; // Waiting paiement
+    const SUBMIT_IN_PROGRESS = 540; // Affiliation in progress
+
     private NetworkOrganizationRepository $networkOrganizationRepositoryMock;
     private NetworkUtils $networkUtilsMock;
     private OrganizationUtils $organizationUtilsMock;
@@ -33,6 +39,11 @@ class UtilsTest extends TestCase
             $this
                 ->getMockBuilder(OrganizationUtils::class)
                 ->getMock();
+
+        $this->cotisationApiResourcesRepositoryMock =
+            $this
+                ->getMockBuilder(CotisationApiResourcesRepository::class)
+                ->getMock();
     }
 
     /**
@@ -57,7 +68,12 @@ class UtilsTest extends TestCase
                 ->with($organizationMock)
                 ->willReturn(true);
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertTrue($utils->isLastParentAndCMF($organizationMock));
     }
 
@@ -81,7 +97,12 @@ class UtilsTest extends TestCase
             ->expects($this->never())
             ->method('isCMF');
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertFalse($utils->isLastParentAndCMF($organizationMock));
     }
 
@@ -104,7 +125,12 @@ class UtilsTest extends TestCase
             ->with($organizationMock)
             ->willReturn(true);
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertTrue($utils->isStructureAndCMF($organizationMock));
     }
 
@@ -125,7 +151,12 @@ class UtilsTest extends TestCase
             ->expects($this->never())
             ->method('isCMF');
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertFalse($utils->isStructureAndCMF($organizationMock));
     }
 
@@ -148,7 +179,12 @@ class UtilsTest extends TestCase
             ->with($organizationMock)
             ->willReturn(true);
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertTrue($utils->isManagerAndCMF($organizationMock));
     }
 
@@ -169,7 +205,12 @@ class UtilsTest extends TestCase
             ->expects($this->never())
             ->method('isCMF');
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertFalse($utils->isManagerAndCMF($organizationMock));
     }
 
@@ -199,7 +240,12 @@ class UtilsTest extends TestCase
             ->expects($this->never())
             ->method('isCMF');
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertTrue($utils->isManagerAndNotLastParentAndCMF($organizationMock));
     }
 
@@ -230,7 +276,147 @@ class UtilsTest extends TestCase
             ->method('isCMF')
             ->willReturn(true);
 
-        $utils = new Utils($this->networkUtilsMock, $this->organizationUtilsMock, $this->networkOrganizationRepositoryMock);
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
         $this->assertTrue($utils->isManagerAndLastParentAndCMF($organizationMock));
     }
+
+    /**
+     * @see Utils::getAlertState()
+     */
+    public function testGetAlertStateAffiliation(): void
+    {
+        $year = 2022;
+
+        $organizationMock = $this->getMockBuilder(Organization::class)->getMock();
+        $organizationMock
+            ->method('getId')
+            ->willReturn(1);
+
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
+
+        $this->cotisationApiResourcesRepositoryMock
+            ->method('getAffiliationState')
+            ->with($organizationMock->getId(), $year)
+            ->willReturn(self::MEMBERSHIP_WAITING);
+
+        $this->assertEquals(AlertStateEnum::AFFILIATION()->getValue(), $utils->getAlertState($organizationMock, $year) );
+
+        $this->cotisationApiResourcesRepositoryMock
+            ->method('getAffiliationState')
+            ->with($organizationMock->getId(), $year)
+            ->willReturn(self::SUBMIT_IN_PROGRESS);
+
+        $this->assertEquals(AlertStateEnum::AFFILIATION()->getValue(), $utils->getAlertState($organizationMock, $year) );
+
+    }
+
+    /**
+     * @see Utils::getAlertState()
+     */
+    public function testGetAlertStateInvoice(): void
+    {
+        $year = 2022;
+
+        $organizationMock = $this->getMockBuilder(Organization::class)->getMock();
+        $organizationMock
+            ->method('getId')
+            ->willReturn(1);
+
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
+
+        $this->cotisationApiResourcesRepositoryMock
+            ->method('getAffiliationState')
+            ->with($organizationMock->getId(), $year)
+            ->willReturn(self::MEMBERSHIP_NOPAYMENT);
+
+        $this->assertEquals(AlertStateEnum::INVOICE()->getValue(), $utils->getAlertState($organizationMock, $year) );
+    }
+
+    /**
+     * @see Utils::getAlertState()
+     */
+    public function testGetAlertStateInsurance(): void
+    {
+        $year = 2022;
+
+        $organizationMock = $this->getMockBuilder(Organization::class)->getMock();
+        $organizationMock
+            ->method('getId')
+            ->willReturn(1);
+
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
+
+        $this->cotisationApiResourcesRepositoryMock
+            ->method('isInsuranceNotDone')
+            ->with($organizationMock->getId(), $year)
+            ->willReturn(true);
+
+        $this->assertEquals(AlertStateEnum::INSURANCE()->getValue(), $utils->getAlertState($organizationMock, $year) );
+    }
+
+    /**
+     * @see Utils::getAlertState()
+     */
+    public function testGetAlertStateAdvertisingInsurance(): void
+    {
+        $year = 2022;
+
+        $organizationMock = $this->getMockBuilder(Organization::class)->getMock();
+        $organizationMock
+            ->method('getId')
+            ->willReturn(1);
+
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
+
+        $this->cotisationApiResourcesRepositoryMock
+            ->method('isNotDGVCustomer')
+            ->with($organizationMock->getId(), $year)
+            ->willReturn(true);
+
+        $this->assertEquals(AlertStateEnum::ADVERTISINGINSURANCE()->getValue(), $utils->getAlertState($organizationMock, $year) );
+    }
+
+    /**
+     * @see Utils::getCurrentCotisationYear()
+     */
+    public function testGetCurrentCotisationYear(): void
+    {
+        $utils = new Utils(
+            $this->networkUtilsMock,
+            $this->organizationUtilsMock,
+            $this->networkOrganizationRepositoryMock,
+            $this->cotisationApiResourcesRepositoryMock
+        );
+        $today = new \DateTime('now');
+        if($today->format('m') <= 9)
+            $this->assertEquals($today->format('Y'), $utils->getCurrentCotisationYear());
+        else
+            $this->assertEquals(($today->format('Y') + 1), $utils->getCurrentCotisationYear());
+
+    }
 }

+ 29 - 0
tests/Service/Network/UtilsTest.php

@@ -21,6 +21,7 @@ class UtilsTest extends TestCase
         $networkCmf->setName('CMF');
         $networkOrganization = new NetworkOrganization();
         $networkOrganization->setNetwork($networkCmf);
+        $networkOrganization->setStartDate(new \DateTime('2000-09-11'));
         $this->organizationCmf = new Organization();
         $this->organizationCmf->addNetworkOrganization($networkOrganization);
 
@@ -53,6 +54,34 @@ class UtilsTest extends TestCase
         $this->assertFalse($result);
     }
 
+    /**
+     * @see Utils::isCMFAndActiveNow()
+     */
+    public function testIsCmfAndActiveNow():void
+    {
+        $result = $this->utils->isCMFAndActiveNow($this->organizationCmf);
+        $this->assertTrue($result);
+    }
+
+    /**
+     * @see Utils::isCMFAndActiveNow()
+     */
+    public function testIsCmfAndNotActiveNow():void
+    {
+        $networkCmf = new Network();
+        $networkCmf->setId(3);
+        $networkCmf->setName('CMF');
+        $networkOrganization = new NetworkOrganization();
+        $networkOrganization->setNetwork($networkCmf);
+        $networkOrganization->setStartDate(new \DateTime('2000-09-11'));
+        $networkOrganization->setEndDate(new \DateTime('2020-09-11'));
+        $organizationCmfNotActive = new Organization();
+        $organizationCmfNotActive->addNetworkOrganization($networkOrganization);
+
+        $result = $this->utils->isCMFAndActiveNow($organizationCmfNotActive);
+        $this->assertFalse($result);
+    }
+
     /**
      * @see Utils::isOrganizationBelongToTheNetwork()
      */

+ 17 - 0
tests/Service/Organization/UtilsTest.php

@@ -2,8 +2,10 @@
 namespace App\Test\Service\Organization;
 
 use App\Entity\Organization\Organization;
+use App\Entity\Organization\Parameters;
 use App\Entity\Organization\Settings;
 use App\Enum\Organization\SettingsProductEnum;
+use App\Service\Organization\Utils;
 use App\Service\Organization\Utils as OrganizationUtils;
 use PHPUnit\Framework\TestCase;
 
@@ -88,4 +90,19 @@ class UtilsTest extends TestCase
             ->willReturn(12097);
         $this->assertTrue($this->organizationUtils->isOrganizationIsCMF($organizationMock));
     }
+
+    /**
+     * @see OrganizationUtils::getOrganizationCurrentActivityYear()
+     */
+    public function testGetOrganizationCurrentActivityYear(){
+        $parameters = new Parameters();
+        $parameters->setMusicalDate(new \DateTime('2020-09-01'));
+        $this->organization->setParameters($parameters);
+
+        $today = new \DateTime('now');
+        if($today->format('m') < 9)
+            $this->assertEquals( ($today->format('Y') - 1), Utils::getOrganizationCurrentActivityYear($this->organization));
+        else
+            $this->assertEquals($today->format('Y'), Utils::getOrganizationCurrentActivityYear($this->organization));
+    }
 }

+ 0 - 27
tests/Service/Utils/DatesTest.php

@@ -1,27 +0,0 @@
-<?php
-namespace App\Tests\Service\Utils;
-
-use App\Service\Utils\Dates;
-use PHPUnit\Framework\TestCase;
-
-class DatesTest extends TestCase
-{
-    /**
-     * @see Dates::isIntervalIsValidNow()
-     */
-    public function testIsIntervalIsValidNow():void
-    {
-        $dates = new Dates();
-        $this->assertTrue($dates->isIntervalIsValidNow(new \DateTime('2020-01-02'), new \DateTime('2025-01-02')));
-        $this->assertTrue($dates->isIntervalIsValidNow(new \DateTime('2020-01-02'), null));
-    }
-
-    /**
-     * @see Dates::isIntervalIsValidNow()
-     */
-    public function testIsIntervalIsNotValidNow():void
-    {
-        $dates = new Dates();
-        $this->assertFalse($dates->isIntervalIsValidNow(new \DateTime('2019-01-02'), new \DateTime('2020-01-02')));
-    }
-}

+ 26 - 0
tests/Service/Utils/DatesUtilsTest.php

@@ -0,0 +1,26 @@
+<?php
+namespace App\Tests\Service\Utils;
+
+use App\Service\Utils\Dates;
+use App\Service\Utils\DatesUtils;
+use PHPUnit\Framework\TestCase;
+
+class DatesUtilsTest extends TestCase
+{
+    /**
+     * @see DatesUtils::isIntervalIsValidNow()
+     */
+    public function testIsIntervalIsValidNow():void
+    {
+        $this->assertTrue(DatesUtils::isIntervalIsValidNow(new \DateTime('2020-01-02'), new \DateTime('2025-01-02')));
+        $this->assertTrue(DatesUtils::isIntervalIsValidNow(new \DateTime('2020-01-02'), null));
+    }
+
+    /**
+     * @see DatesUtils::isIntervalIsValidNow()
+     */
+    public function testIsIntervalIsNotValidNow():void
+    {
+        $this->assertFalse(DatesUtils::isIntervalIsValidNow(new \DateTime('2019-01-02'), new \DateTime('2020-01-02')));
+    }
+}