Przeglądaj źródła

Merge branch 'master' of gitlab.2iopenservice.com:opentalent/ap2i

Olivier Massot 1 rok temu
rodzic
commit
df6035dc0e

+ 25 - 8
config/opentalent/modulesbyconditions.yaml

@@ -21,35 +21,35 @@ parameters:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isLastParentAndCMF
         CotisationStructure:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isStructureAndCMF
         CotisationRate:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isManagerAndLastParentAndCMF
         CotisationTransmissionState:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isManagerAndCMF
         CotisationTransmission:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isManagerAndNotLastParentAndCMF
         CotisationCMFAdministration:
             roles:
@@ -57,7 +57,7 @@ parameters:
             conditions:
                 service:
                     name: App\Service\Organization\Utils
-                    function: isOrganizationCMF
+                    function: isCMF
         Admin2IOS:
             roles:
                 - ROLE_ADMIN2IOS
@@ -68,12 +68,12 @@ parameters:
         StatisticFederation:
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isManagerAndNotLastParentAndCMF
         StatisticStructure:
             conditions:
                 service:
-                    name: App\Service\Cotisation\Utils
+                    name: App\Service\Organization\Utils
                     function: isManagerAndCMF
         Network:
             conditions:
@@ -90,3 +90,20 @@ parameters:
                 service:
                     name: App\Service\Network\Utils
                     function: isCMF
+        AccessReward:
+            conditions:
+                service:
+                    name: App\Service\Network\Utils
+                    function: isCMF
+        AccessRewardCommand:
+            conditions:
+                service:
+                    name: App\Service\Organization\Utils
+                    function: isStructureAndCMF
+        Reward:
+            roles:
+                - ROLE_REWARD
+            conditions:
+                service:
+                    name: App\Service\Organization\Utils
+                    function: isManagerAndCMF

+ 12 - 7
config/opentalent/products.yaml

@@ -76,12 +76,6 @@ parameters:
           - Course
           - Education
 
-      Medals:
-        entities:
-          - Medal
-        roles:
-          - ROLE_MEDALS
-
       Donors:
         entities:
           - Donor
@@ -272,6 +266,18 @@ parameters:
         entities:
           - DolibarrAccount
 
+      AccessReward:
+        roles:
+          - ROLE_ACCESSREWARD
+        entities:
+          - AccessReward
+
+      Reward:
+        roles:
+          - ROLE_REWARD
+        entities:
+          - Reward
+
   opentalent.products:
       artist:
         modules:
@@ -280,7 +286,6 @@ parameters:
           - Events
           - GeneralConfig
           - Equipments
-          - Medals
           - Donors
           - Commissons
           - Website

+ 1 - 0
config/packages/security.yaml

@@ -25,6 +25,7 @@ security:
             - ROLE_ONLINEREGISTRATION_ADMINISTRATION
             - ROLE_STATISTIC
             - ROLE_ADMIN_CORE
+            - ROLE_REWARD
 
         ROLE_ADMIN_CORE: *BASE_ROLE_ADMINISTRATION_CORE
 

+ 1 - 1
config/packages/security/core.yaml

@@ -3,7 +3,7 @@ security:
         ROLE_CORE-CRUD:
           - ROLE_USERS
           - ROLE_COMMISSIONS
-          - ROLE_MEDALS
+          - ROLE_ACCESSREWARD
           - ROLE_DONORS
           - ROLE_MAILS
           - ROLE_EMAILS

+ 0 - 10
config/packages/security/medals.yaml

@@ -1,10 +0,0 @@
-security:
-    role_hierarchy:
-        ROLE_MEDALS:
-          - ROLE_MEDALS_VIEW
-
-        ROLE_MEDALS_VIEW:
-          - ROLE_MEDAL_REFERENCE
-
-        ROLE_MEDAL_REFERENCE:
-          - ROLE_ACCESS_REFERENCE

+ 10 - 0
config/packages/security/rewards.yaml

@@ -0,0 +1,10 @@
+security:
+    role_hierarchy:
+        ROLE_ACCESSREWARD:
+          - ROLE_ACCESSREWARD_VIEW
+
+        ROLE_ACCESSREWARD_VIEW:
+          - ROLE_ACCESSREWARD_REFERENCE
+
+        ROLE_ACCESSREWARD_REFERENCE:
+          - ROLE_ACCESSREWARD_REFERENCE

+ 19 - 22
src/Entity/Access/Access.php

@@ -4,9 +4,9 @@ declare(strict_types=1);
 
 namespace App\Entity\Access;
 
+use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
 use ApiPlatform\Metadata\ApiFilter;
-use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Serializer\Filter\GroupFilter;
 use App\Entity\AccessWish\AccessWish;
 use App\Entity\Billing\AccessBilling;
@@ -37,22 +37,19 @@ use App\Entity\Message\Email;
 use App\Entity\Message\Mail;
 use App\Entity\Message\Sms;
 use App\Entity\Organization\Jury;
-use App\Entity\Organization\Organization;
 use App\Entity\Organization\OrganizationLicence;
 use App\Entity\Organization\Parameters;
 use App\Entity\Person\CommissionMember;
 use App\Entity\Person\CompanyPerson;
-use App\Entity\Person\Medal;
+use App\Entity\Product\Equipment;
+use App\Entity\Product\EquipmentLoan;
+use App\Entity\Reward\AccessReward;
+use App\Repository\Access\AccessRepository;
 use App\Entity\Person\Person;
 use App\Entity\Person\PersonActivity;
 use App\Entity\Place\PlaceRepair;
 use App\Entity\Place\RoomRepair;
-use App\Entity\Product\Equipment;
-use App\Entity\Product\EquipmentLoan;
 use App\Entity\Product\EquipmentRepair;
-use App\Filter\ApiPlatform\Person\FullNameFilter;
-use App\Filter\ApiPlatform\Utils\InFilter;
-use App\Repository\Access\AccessRepository;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
@@ -282,8 +279,8 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\OneToMany(mappedBy: 'access', targetEntity: Donor::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $donors;
 
-    #[ORM\OneToMany(mappedBy: 'access', targetEntity: Medal::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $medals;
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: AccessReward::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $accessRewards;
 
     #[ORM\OneToMany(mappedBy: 'access', targetEntity: OrganizationResponsability::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $organizationResponsabilities;
@@ -346,7 +343,7 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         $this->equipments = new ArrayCollection();
         $this->accessFictionalIntangibles = new ArrayCollection();
         $this->donors = new ArrayCollection();
-        $this->medals = new ArrayCollection();
+        $this->accessRewards = new ArrayCollection();
         $this->organizationResponsabilities = new ArrayCollection();
         $this->accessWishes = new ArrayCollection();
         $this->workByUsers = new ArrayCollection();
@@ -1832,29 +1829,29 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     }
 
     /**
-     * @return Collection<int, Medal>
+     * @return Collection<int, AccessReward>
      */
-    public function getMedals(): Collection
+    public function getAccessRewards(): Collection
     {
-        return $this->medals;
+        return $this->accessRewards;
     }
 
-    public function addMedal(Medal $medal): self
+    public function addAccessReward(AccessReward $accessRewards): self
     {
-        if (!$this->medals->contains($medal)) {
-            $this->medals[] = $medal;
-            $medal->setAccess($this);
+        if (!$this->accessRewards->contains($accessRewards)) {
+            $this->accessRewards[] = $accessRewards;
+            $accessRewards->setAccess($this);
         }
 
         return $this;
     }
 
-    public function removeMedal(Medal $medal): self
+    public function removeAccessReward(AccessReward $accessRewards): self
     {
-        if ($this->medals->removeElement($medal)) {
+        if ($this->accessRewards->removeElement($accessRewards)) {
             // set the owning side to null (unless already changed)
-            if ($medal->getAccess() === $this) {
-                $medal->setAccess(null);
+            if ($accessRewards->getAccess() === $this) {
+                $accessRewards->setAccess(null);
             }
         }
 

+ 32 - 2
src/Entity/Organization/Organization.php

@@ -41,6 +41,7 @@ use App\Enum\Organization\PrincipalTypeEnum;
 use App\Enum\Organization\SchoolCategoryEnum;
 use App\Enum\Organization\TypeEstablishmentDetailEnum;
 use App\Enum\Organization\TypeEstablishmentEnum;
+use App\Entity\Reward\Reward;
 use App\Repository\Organization\OrganizationRepository;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -310,8 +311,11 @@ class Organization
     #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Donor::class, orphanRemoval: true)]
     private Collection $donors;
 
-    //    #[ORM\OneToOne()]
-    //    private OnlineRegistrationSettings $onlineRegistrationSettings;
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Reward::class, orphanRemoval: true)]
+    private Collection $rewards;
+
+//    #[ORM\OneToOne()]
+//    private OnlineRegistrationSettings $onlineRegistrationSettings;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'organizations', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_organization')]
@@ -357,6 +361,7 @@ class Organization
         $this->intangibles = new ArrayCollection();
         $this->donors = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->rewards = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -1823,4 +1828,29 @@ class Organization
 
         return $this;
     }
+
+    public function getRewards(): Collection
+    {
+        return $this->rewards;
+    }
+
+    public function addReward(Reward $rewards): self
+    {
+        if (!$this->rewards->contains($rewards)) {
+            $this->rewards[] = $rewards;
+            $rewards->setOrganization($this);
+        }
+        return $this;
+    }
+
+    public function removeReward(Reward $rewards): self
+    {
+        if ($this->rewards->removeElement($rewards)) {
+            // set the owning side to null (unless already changed)
+            if ($rewards->getOrganization() === $this) {
+                $rewards->setOrganization(null);
+            }
+        }
+        return $this;
+    }
 }

+ 3 - 3
src/Entity/Person/Medal.php → src/Entity/Reward/AccessReward.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Entity\Person;
+namespace App\Entity\Reward;
 
 use App\Entity\Access\Access;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
@@ -13,14 +13,14 @@ use Doctrine\ORM\Mapping as ORM;
  */
 // #[Auditable]
 #[ORM\Entity]
-class Medal
+class AccessReward
 {
     #[ORM\Id]
     #[ORM\Column]
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
-    #[ORM\ManyToOne(inversedBy: 'medals')]
+    #[ORM\ManyToOne(inversedBy: 'accessRewards')]
     #[ORM\JoinColumn(nullable: false)]
     private Access $access;
 

+ 42 - 0
src/Entity/Reward/Reward.php

@@ -0,0 +1,42 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Reward;
+
+//use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Organization\Organization;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Classe qui gère les disctinctions de la CMF
+ */
+//#[Auditable]
+#[ORM\Entity]
+class Reward
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'rewards')]
+    #[ORM\JoinColumn(nullable: false)]
+    private Organization $organization;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getOrganization(): ?Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(?Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+}

+ 0 - 0
src/Filter/ApiPlatform/Person/FullNameFilter.php~2.4.1 → src/Filter/ApiPlatform/Person/FullNameFilter.php


+ 0 - 53
src/Filter/ApiPlatform/Person/FullNameFilter.php~HEAD

@@ -1,53 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Filter\ApiPlatform\Person;
-
-use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
-use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
-use ApiPlatform\Metadata\Operation;
-use Doctrine\ORM\QueryBuilder;
-
-class FullNameFilter extends AbstractFilter
-{
-    /**
-     * @param mixed[] $context
-     */
-    protected function filterProperty(string $property,
-        mixed $value,
-        QueryBuilder $queryBuilder,
-        QueryNameGeneratorInterface $queryNameGenerator,
-        string $resourceClass,
-        ?Operation $operation = null,
-        array $context = []): void
-    {
-        if ('fullname' !== $property) {
-            return;
-        }
-        $alias = $queryBuilder->getRootAliases()[0];
-        $queryBuilder
-            ->innerJoin(sprintf('%s.person', $alias), 'person')
-            ->andWhere('person.name LIKE :search OR person.givenName LIKE :search')
-            ->setParameter('search', '%'.$value.'%');
-    }
-
-    /**
-     * API docs.
-     *
-     * @return array<string, mixed[]>
-     */
-    public function getDescription(string $resourceClass): array
-    {
-        return [
-            'fullname' => [
-                'property' => null,
-                'type' => 'string',
-                'required' => false,
-                'openapi' => [
-                    'description' => 'Rechercher parmi les champs name et givenName',
-                ],
-            ],
-        ];
-    }
-}

+ 75 - 6
src/Service/Organization/Utils.php

@@ -7,9 +7,10 @@ namespace App\Service\Organization;
 use App\Entity\Organization\Organization;
 use App\Enum\Organization\OrganizationIdsEnum;
 use App\Enum\Organization\SettingsProductEnum;
+use App\Repository\Network\NetworkOrganizationRepository;
 use App\Service\Utils\DatesUtils;
 use App\Service\Utils\UrlBuilder;
-use App\Test\Service\Organization\UtilsTest;
+use App\Service\Network\Utils as NetworkUtils;
 
 /**
  * Service rassemblant des fonctions d'aide pour les questions se rapportant à l'organisation.
@@ -19,6 +20,12 @@ class Utils
     public const START_DATE_KEY = 'dateStart';
     public const END_DATE_KEY = 'dateEnd';
 
+    public function __construct(
+        private NetworkOrganizationRepository $networkOrganizationRepository,
+        private NetworkUtils $networkUtils
+    )
+    {}
+
     /**
      * Teste si l'organisation est considérée comme une structure == n'a pas un produit manager.
      *
@@ -74,18 +81,80 @@ class Utils
 
     /**
      * Test si l'organisation est la structure CMF.
-     *
-     * @see UtilsTest::testIsOrganizationIsCMF()
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsCMF()
      */
-    public function isOrganizationCMF(Organization $organization): bool
+    public function isCMF(Organization $organization): bool
     {
         return $this->isOrganizationIdEqualTo($organization, OrganizationIdsEnum::CMF);
     }
 
     /**
-     * Test si l'id de l'organisation est celui passé en paramètre (doit faire partit des OrganizationIdsEnum).
+     * Test si l'organisation est un dernier parent ET appartient à la CMF.
+     *
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsLastParentAndCMF()
+     */
+    public function isLastParentAndCMF(Organization $organization): bool
+    {
+        return $this->networkOrganizationRepository->isLastParent($organization) && $this->networkUtils->isCMF($organization);
+    }
+
+    /**
+     * Test si l'organisation est une structure (non manager) ET appartient à la CMF
+     *
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsStructureAndCMF()
+     */
+    public function isStructureAndCMF(Organization $organization): bool
+    {
+        return $this->isStructure($organization) && $this->networkUtils->isCMF($organization);
+    }
+
+    /**
+     * Test si la structure est un manager ET qu'elle appartient à la CMF
+     *
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsManagerAndCMF()
+     */
+    public function isManagerAndCMF(Organization $organization): bool
+    {
+        return $this->isManager($organization) && $this->networkUtils->isCMF($organization);
+    }
+
+    /**
+     * Test si l'organisation est un manager ET un dernier parent ET appartient à la CMF
+     *
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsManagerAndLastParentAndCMF()
+     */
+    public function isManagerAndLastParentAndCMF(Organization $organization): bool
+    {
+        return $this->isManager($organization) && $this->isLastParentAndCMF($organization);
+    }
+
+    /**
+     * Test si l'organisation est un manager ET n'est pas un dernier parent ET appartient à la CMF
+     *
+     * @param Organization $organization
+     * @return bool
+     * @see UtilsTest::testIsManagerAndNotLastParentAndCMF()
+     */
+    public function isManagerAndNotLastParentAndCMF(Organization $organization): bool
+    {
+        return $this->isManager($organization) && !$this->networkOrganizationRepository->isLastParent($organization) && $this->networkUtils->isCMF($organization);
+    }
+
+
+    /**
+     * Test si l'id de l'organisation est celui passé en paramètre (doit faire partie des OrganizationIdsEnum).
      */
-    protected function isOrganizationIdEqualTo(Organization $organization, OrganizationIdsEnum $organizationIds): bool
+    public function isOrganizationIdEqualTo(Organization $organization, OrganizationIdsEnum $organizationIds): bool
     {
         return $organization->getId() === $organizationIds->value;
     }

+ 0 - 1
src/Service/Rest/Operation/CreateOperation.php

@@ -18,7 +18,6 @@ class CreateOperation extends BaseRestOperation
      * @param array<mixed> $parameters
      * @param array<mixed> $options
      */
-    #[Pure]
     public function __construct(
         protected string $label,
         protected string $entityName,

+ 8 - 228
tests/Unit/Service/Cotisation/UtilsTest.php

@@ -5,10 +5,7 @@ namespace App\Tests\Unit\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 as CotisationUtils;
-use App\Service\Network\Utils as NetworkUtils;
-use App\Service\Organization\Utils as OrganizationUtils;
 use App\Service\Utils\DatesUtils;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
@@ -26,221 +23,16 @@ class UtilsTest extends TestCase
 
     public function setUp(): void
     {
-        $this->networkOrganizationRepository = $this->getMockBuilder(NetworkOrganizationRepository::class)
-                ->disableOriginalConstructor()
-                ->getMock();
-
-        $this->networkUtils = $this->getMockBuilder(NetworkUtils::class)->disableOriginalConstructor()->getMock();
-        $this->organizationUtils = $this->getMockBuilder(OrganizationUtils::class)->getMock();
-
         $this->cotisationApiResourcesRepository = $this->getMockBuilder(CotisationApiResourcesRepository::class)
             ->disableOriginalConstructor()
             ->getMock();
     }
 
-    /**
-     * @see Utils::isLastParentAndCMF()
-     */
-    public function testIsLastParentAndCMF(): void
-    {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['isLastParentAndCMF'])
-            ->getMock();
-
-        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
-
-        $this->networkOrganizationRepository
-                ->method('isLastParent')
-                ->willReturnMap([
-                    [$organization1, true],
-                    [$organization2, true],
-                    [$organization3, false],
-                    [$organization4, false],
-                ]);
-
-        $this->networkUtils
-                ->method('isCMF')
-                ->willReturnMap([
-                    [$organization1, true],
-                    [$organization2, false],
-                    [$organization3, true],
-                    [$organization4, false],
-                ]);
-
-        $this->assertTrue($cotisationUtils->isLastParentAndCMF($organization1));
-        $this->assertFalse($cotisationUtils->isLastParentAndCMF($organization2));
-        $this->assertFalse($cotisationUtils->isLastParentAndCMF($organization3));
-        $this->assertFalse($cotisationUtils->isLastParentAndCMF($organization4));
-    }
-
-    /**
-     * @see Utils::isStructureAndCMF()
-     */
-    public function testIsStructureAndCMF(): void
-    {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['isStructureAndCMF'])
-            ->getMock();
-
-        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
-
-        $this->organizationUtils
-            ->method('isStructure')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, true],
-                [$organization4, false],
-            ]);
-
-        $this->networkUtils
-            ->method('isCMF')
-            ->with($organization1)
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, false],
-                [$organization4, true],
-            ]);
-
-        $this->assertTrue($cotisationUtils->isStructureAndCMF($organization1));
-        $this->assertFalse($cotisationUtils->isStructureAndCMF($organization2));
-        $this->assertFalse($cotisationUtils->isStructureAndCMF($organization3));
-        $this->assertFalse($cotisationUtils->isStructureAndCMF($organization4));
-    }
-
-    /**
-     * @see Utils::isManagerAndCMF()
-     */
-    public function testIsManagerAndCMF(): void
-    {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['isManagerAndCMF'])
-            ->getMock();
-
-        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
-
-        $this->organizationUtils
-            ->method('isManager')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, true],
-                [$organization4, false],
-            ]);
-
-        $this->networkUtils
-            ->method('isCMF')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, false],
-                [$organization4, true],
-            ]);
-
-        $this->assertTrue($cotisationUtils->isManagerAndCMF($organization1));
-        $this->assertFalse($cotisationUtils->isManagerAndCMF($organization2));
-        $this->assertFalse($cotisationUtils->isManagerAndCMF($organization3));
-        $this->assertFalse($cotisationUtils->isManagerAndCMF($organization4));
-    }
-
-    /**
-     * @see Utils::isManagerAndNotLastParentAndCMF()
-     */
-    public function testIsManagerAndLastParentAndCMF(): void
-    {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['isManagerAndLastParentAndCMF'])
+    public function getCotisationUtilsMockFor(string $methodName) {
+        return $this->getMockBuilder(CotisationUtils::class)
+            ->setConstructorArgs([$this->cotisationApiResourcesRepository])
+            ->setMethodsExcept([$methodName])
             ->getMock();
-
-        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
-
-        $this->organizationUtils
-            ->method('isManager')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, true],
-                [$organization4, false],
-            ]);
-
-        $cotisationUtils
-            ->method('isLastParentAndCMF')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, false],
-                [$organization4, true],
-            ]);
-
-        $this->assertTrue($cotisationUtils->isManagerAndLastParentAndCMF($organization1));
-        $this->assertFalse($cotisationUtils->isManagerAndLastParentAndCMF($organization2));
-        $this->assertFalse($cotisationUtils->isManagerAndLastParentAndCMF($organization3));
-        $this->assertFalse($cotisationUtils->isManagerAndLastParentAndCMF($organization4));
-    }
-
-    /**
-     * @see Utils::isManagerAndNotLastParentAndCMF()
-     */
-    public function testIsManagerAndNotLastParentAndCMF(): void
-    {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['isManagerAndNotLastParentAndCMF'])
-            ->getMock();
-
-        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
-        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
-
-        $this->organizationUtils
-            ->method('isManager')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, false],
-                [$organization3, true],
-                [$organization4, true],
-            ]);
-
-        $this->networkOrganizationRepository
-            ->method('isLastParent')
-            ->willReturnMap([
-                [$organization1, false],
-                [$organization2, false],
-                [$organization3, true],
-                [$organization4, false],
-            ]);
-
-        $this->networkUtils
-            ->method('isCMF')
-            ->willReturnMap([
-                [$organization1, true],
-                [$organization2, true],
-                [$organization3, true],
-                [$organization4, false],
-            ]);
-
-        $this->assertTrue($cotisationUtils->isManagerAndNotLastParentAndCMF($organization1));
-        $this->assertFalse($cotisationUtils->isManagerAndNotLastParentAndCMF($organization2));
-        $this->assertFalse($cotisationUtils->isManagerAndNotLastParentAndCMF($organization3));
-        $this->assertFalse($cotisationUtils->isManagerAndNotLastParentAndCMF($organization4));
     }
 
     /**
@@ -248,10 +40,7 @@ class UtilsTest extends TestCase
      */
     public function testGetAlertState(): void
     {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['getAlertState'])
-            ->getMock();
+        $cotisationUtils = $this->getCotisationUtilsMockFor('getAlertState');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
         $organization->method('getId')->willReturn(1);
@@ -275,10 +64,7 @@ class UtilsTest extends TestCase
      */
     public function testGetAlertStateInsurance(): void
     {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['getAlertState'])
-            ->getMock();
+        $cotisationUtils = $this->getCotisationUtilsMockFor('getAlertState');
 
         $year = 2022;
 
@@ -303,10 +89,7 @@ class UtilsTest extends TestCase
      */
     public function testGetAlertStateAdvertisingInsurance(): void
     {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['getAlertState'])
-            ->getMock();
+        $cotisationUtils = $this->getCotisationUtilsMockFor('getAlertState');
 
         $year = 2022;
 
@@ -331,10 +114,7 @@ class UtilsTest extends TestCase
      */
     public function testGetCurrentCotisationYear(): void
     {
-        $cotisationUtils = $this->getMockBuilder(CotisationUtils::class)
-            ->setConstructorArgs([$this->networkUtils, $this->organizationUtils, $this->networkOrganizationRepository, $this->cotisationApiResourcesRepository])
-            ->setMethodsExcept(['getCurrentCotisationYear'])
-            ->getMock();
+        $cotisationUtils = $this->getCotisationUtilsMockFor('getCurrentCotisationYear');
 
         DatesUtils::setFakeDatetime('2022-03-01');
 

+ 232 - 30
tests/Unit/Service/Organization/UtilsTest.php

@@ -10,27 +10,41 @@ use App\Entity\Organization\Settings;
 use App\Entity\Organization\Subdomain;
 use App\Enum\Organization\OrganizationIdsEnum;
 use App\Enum\Organization\SettingsProductEnum;
+use App\Repository\Network\NetworkOrganizationRepository;
+use App\Service\Network\Utils as NetworkUtils;
 use App\Service\Organization\Utils as OrganizationUtils;
 use App\Service\Utils\DatesUtils;
 use Doctrine\Common\Collections\ArrayCollection;
+use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 
-class TestableOrganizationUtils extends OrganizationUtils
+class UtilsTest extends TestCase
 {
-    public function isOrganizationIdEqualTo(Organization $organization, OrganizationIdsEnum $organizationIdsEnum): bool
+    private MockObject | NetworkOrganizationRepository $networkOrganizationRepository;
+    private MockObject | NetworkUtils $networkUtils;
+
+    public function setUp(): void
     {
-        return parent::isOrganizationIdEqualTo($organization, $organizationIdsEnum);
+        $this->networkOrganizationRepository = $this->getMockBuilder(NetworkOrganizationRepository::class)
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->networkUtils = $this->getMockBuilder(NetworkUtils::class)->disableOriginalConstructor()->getMock();
+    }
+
+    public function getOrganizationUtilsMockFor(string $methodName) {
+        return $this->getMockBuilder(OrganizationUtils::class)
+            ->setConstructorArgs([$this->networkOrganizationRepository, $this->networkUtils])
+            ->setMethodsExcept([$methodName])
+            ->getMock();
     }
-}
 
-class UtilsTest extends TestCase
-{
     /**
      * @see OrganizationUtils::isStructure()
      */
     public function testIsStructure(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['isStructure'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isStructure');
 
         $organization = $this->createOrganizationWithProductMock(SettingsProductEnum::ARTIST);
         $this->assertTrue($organizationUtils->isStructure($organization));
@@ -56,7 +70,7 @@ class UtilsTest extends TestCase
      */
     public function testIsManager(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['isManager'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isManager');
 
         $organization = $this->createOrganizationWithProductMock(SettingsProductEnum::ARTIST);
         $this->assertFalse($organizationUtils->isManager($organization));
@@ -82,7 +96,7 @@ class UtilsTest extends TestCase
      */
     public function testIsOrganizationIs2ios(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['is2iosOrganization'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('is2iosOrganization');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
 
@@ -92,17 +106,17 @@ class UtilsTest extends TestCase
     }
 
     /**
-     * @see OrganizationUtils::isOrganizationCMF()
+     * @see OrganizationUtils::isCMF()
      */
-    public function testIsOrganizationIsCMF(): void
+    public function testIsCMF(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['isOrganizationCMF'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isCMF');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
 
         $organizationUtils->expects(self::once())->method('isOrganizationIdEqualTo')->with($organization, OrganizationIdsEnum::CMF);
 
-        $organizationUtils->isOrganizationCMF($organization);
+        $organizationUtils->isCMF($organization);
     }
 
     /**
@@ -110,7 +124,7 @@ class UtilsTest extends TestCase
      */
     public function testIsOrganizationIdEqualTo(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['isOrganizationIdEqualTo'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isOrganizationIdEqualTo');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
         $organization->method('getId')->willReturnOnConsecutiveCalls(123, OrganizationIdsEnum::_2IOS->value);
@@ -124,7 +138,7 @@ class UtilsTest extends TestCase
      */
     public function testGetOrganizationCurrentActivityYear(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationCurrentActivityYear'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationCurrentActivityYear');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getMusicalDate')->willReturnOnConsecutiveCalls(
@@ -155,7 +169,7 @@ class UtilsTest extends TestCase
      */
     public function testGetActivityPeriodsSwitchYear(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getActivityPeriodsSwitchYear'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getActivityPeriodsSwitchYear');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getMusicalDate')->willReturn(new \DateTime('2020-09-05'));
@@ -174,7 +188,7 @@ class UtilsTest extends TestCase
      */
     public function testGetActivityPeriodsSwitchYearNoMusicalDate(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getActivityPeriodsSwitchYear'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getActivityPeriodsSwitchYear');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getMusicalDate')->willReturn(null);
@@ -193,7 +207,7 @@ class UtilsTest extends TestCase
      */
     public function testGetActivityYearSwitchDate(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getActivityYearSwitchDate'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getActivityYearSwitchDate');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getMusicalDate')->willReturn(new \DateTime('2020-09-05'));
@@ -210,7 +224,7 @@ class UtilsTest extends TestCase
      */
     public function testGetActivityYearSwitchDateNoMusicalDate(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getActivityYearSwitchDate'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getActivityYearSwitchDate');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getMusicalDate')->willReturn(null);
@@ -225,9 +239,8 @@ class UtilsTest extends TestCase
     /**
      * @see OrganizationUtils::getOrganizationActiveSubdomain()
      */
-    public function testGetOrganizationActiveSubdomain(): void
-    {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationActiveSubdomain'])->getMock();
+    public function testGetOrganizationActiveSubdomain(): void {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationActiveSubdomain');
 
         $subdomain1 = $this->getMockBuilder(Subdomain::class)->getMock();
         $subdomain1->method('isActive')->willReturn(false);
@@ -248,9 +261,8 @@ class UtilsTest extends TestCase
     /**
      * @see OrganizationUtils::getOrganizationActiveSubdomain()
      */
-    public function testGetOrganizationActiveSubdomainNone(): void
-    {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationActiveSubdomain'])->getMock();
+    public function testGetOrganizationActiveSubdomainNone(): void {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationActiveSubdomain');
 
         $subdomain1 = $this->getMockBuilder(Subdomain::class)->getMock();
         $subdomain1->method('isActive')->willReturn(false);
@@ -266,7 +278,7 @@ class UtilsTest extends TestCase
      */
     public function testOrganizationWebsite(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationWebsite'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationWebsite');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getDesactivateOpentalentSiteWeb')->willReturn(false);
@@ -285,7 +297,7 @@ class UtilsTest extends TestCase
      */
     public function testOrganizationWebsiteDeactivatedWithOther(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationWebsite'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationWebsite');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getDesactivateOpentalentSiteWeb')->willReturn(true);
@@ -302,7 +314,7 @@ class UtilsTest extends TestCase
      */
     public function testOrganizationWebsiteDeactivatedNoOther(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationWebsite'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationWebsite');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getDesactivateOpentalentSiteWeb')->willReturn(true);
@@ -319,7 +331,7 @@ class UtilsTest extends TestCase
      */
     public function testOrganizationWebsiteWithCustom(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationWebsite'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationWebsite');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getDesactivateOpentalentSiteWeb')->willReturn(false);
@@ -336,7 +348,7 @@ class UtilsTest extends TestCase
      */
     public function testOrganizationWebsiteNoSubdomains(): void
     {
-        $organizationUtils = $this->getMockBuilder(TestableOrganizationUtils::class)->setMethodsExcept(['getOrganizationWebsite'])->getMock();
+        $organizationUtils = $this->getOrganizationUtilsMockFor('getOrganizationWebsite');
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $parameters->method('getDesactivateOpentalentSiteWeb')->willReturn(false);
@@ -350,6 +362,196 @@ class UtilsTest extends TestCase
         $this->assertEquals(null, $organizationUtils->getOrganizationWebsite($organization));
     }
 
+    /**
+     * @see Utils::isLastParentAndCMF()
+     */
+    public function testIsLastParentAndCMF(): void
+    {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isLastParentAndCMF');
+
+        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
+
+        $this->networkOrganizationRepository
+            ->method('isLastParent')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, true],
+                [$organization3, false],
+                [$organization4, false],
+            ]);
+
+        $this->networkUtils
+            ->method('isCMF')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, true],
+                [$organization4, false],
+            ]);
+
+        $this->assertTrue($organizationUtils->isLastParentAndCMF($organization1));
+        $this->assertFalse($organizationUtils->isLastParentAndCMF($organization2));
+        $this->assertFalse($organizationUtils->isLastParentAndCMF($organization3));
+        $this->assertFalse($organizationUtils->isLastParentAndCMF($organization4));
+    }
+
+    /**
+     * @see Utils::isStructureAndCMF()
+     */
+    public function testIsStructureAndCMF(): void
+    {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isStructureAndCMF');
+
+        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
+
+        $organizationUtils
+            ->method('isStructure')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, true],
+                [$organization4, false],
+            ]);
+
+        $this->networkUtils
+            ->method('isCMF')
+            ->with($organization1)
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, false],
+                [$organization4, true],
+            ]);
+
+        $this->assertTrue($organizationUtils->isStructureAndCMF($organization1));
+        $this->assertFalse($organizationUtils->isStructureAndCMF($organization2));
+        $this->assertFalse($organizationUtils->isStructureAndCMF($organization3));
+        $this->assertFalse($organizationUtils->isStructureAndCMF($organization4));
+    }
+
+    /**
+     * @see Utils::isManagerAndCMF()
+     */
+    public function testIsManagerAndCMF(): void
+    {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isManagerAndCMF');
+
+        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
+
+        $organizationUtils
+            ->method('isManager')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, true],
+                [$organization4, false],
+            ]);
+
+        $this->networkUtils
+            ->method('isCMF')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, false],
+                [$organization4, true],
+            ]);
+
+        $this->assertTrue($organizationUtils->isManagerAndCMF($organization1));
+        $this->assertFalse($organizationUtils->isManagerAndCMF($organization2));
+        $this->assertFalse($organizationUtils->isManagerAndCMF($organization3));
+        $this->assertFalse($organizationUtils->isManagerAndCMF($organization4));
+    }
+
+    /**
+     * @see Utils::isManagerAndNotLastParentAndCMF()
+     */
+    public function testIsManagerAndLastParentAndCMF(): void
+    {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isManagerAndLastParentAndCMF');
+
+        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
+
+        $organizationUtils
+            ->method('isManager')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, true],
+                [$organization4, false],
+            ]);
+
+        $organizationUtils
+            ->method('isLastParentAndCMF')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, false],
+                [$organization4, true],
+            ]);
+
+        $this->assertTrue($organizationUtils->isManagerAndLastParentAndCMF($organization1));
+        $this->assertFalse($organizationUtils->isManagerAndLastParentAndCMF($organization2));
+        $this->assertFalse($organizationUtils->isManagerAndLastParentAndCMF($organization3));
+        $this->assertFalse($organizationUtils->isManagerAndLastParentAndCMF($organization4));
+    }
+
+    /**
+     * @see Utils::isManagerAndNotLastParentAndCMF()
+     */
+    public function testIsManagerAndNotLastParentAndCMF(): void
+    {
+        $organizationUtils = $this->getOrganizationUtilsMockFor('isManagerAndNotLastParentAndCMF');
+
+        $organization1 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization2 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization3 = $this->getMockBuilder(Organization::class)->getMock();
+        $organization4 = $this->getMockBuilder(Organization::class)->getMock();
+
+        $organizationUtils
+            ->method('isManager')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, false],
+                [$organization3, true],
+                [$organization4, true],
+            ]);
+
+        $this->networkOrganizationRepository
+            ->method('isLastParent')
+            ->willReturnMap([
+                [$organization1, false],
+                [$organization2, false],
+                [$organization3, true],
+                [$organization4, false],
+            ]);
+
+        $this->networkUtils
+            ->method('isCMF')
+            ->willReturnMap([
+                [$organization1, true],
+                [$organization2, true],
+                [$organization3, true],
+                [$organization4, false],
+            ]);
+
+        $this->assertTrue($organizationUtils->isManagerAndNotLastParentAndCMF($organization1));
+        $this->assertFalse($organizationUtils->isManagerAndNotLastParentAndCMF($organization2));
+        $this->assertFalse($organizationUtils->isManagerAndNotLastParentAndCMF($organization3));
+        $this->assertFalse($organizationUtils->isManagerAndNotLastParentAndCMF($organization4));
+    }
+
     /**
      * @see OrganizationUtils::isSchool()
      */