浏览代码

Merge branch 'V8-6650_delete_from_dolibarr' into feature/V8-3988-suppression-orgas

Olivier Massot 10 月之前
父节点
当前提交
9b14d4553a

+ 23 - 5
src/Service/Dolibarr/DolibarrApiService.php

@@ -9,6 +9,7 @@ use App\Service\Rest\ApiRequestService;
 use JetBrains\PhpStorm\Pure;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Exception\HttpException;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
 
 /**
@@ -183,9 +184,6 @@ class DolibarrApiService extends ApiRequestService
 
     /**
      * Créé une société dans la DB dolibarr, et retourne l'id de celle-ci.
-     *
-     * @param Organization $organization
-     * @return mixed
      */
     public function createSociety(Organization $organization, bool $client = false): mixed
     {
@@ -194,12 +192,32 @@ class DolibarrApiService extends ApiRequestService
             'client' => $client ? 1 : 2,
             'code_client' => -1,
             'import_key' => 'crm',
-            'array_options' => ['options_2iopen_organization_id' => $organization->getId()]
+            'array_options' => ['options_2iopen_organization_id' => $organization->getId()],
         ];
 
         /** @var Response $response */
-        $response = $this->post("/thirdparties", $body);
+        $response = $this->post('/thirdparties', $body);
 
         return json_decode($response->getContent(), true);
     }
+
+    /**
+     * Delete the organization from Dolibarr.
+     *
+     * @throws \JsonException
+     * @throws TransportExceptionInterface
+     */
+    public function switchSocietyToProspect(int $organizationId): void
+    {
+        $socId = $this->getSociety($organizationId)['id'];
+
+        $res = $this->put(
+            "thirdparties/$socId",
+            ['client' => 2],
+        );
+
+        if ($res->getStatusCode() !== 200) {
+            throw new HttpException($res->getStatusCode(), 'Error while updating the society in Dolibarr');
+        }
+    }
 }

+ 116 - 146
src/Service/Organization/OrganizationFactory.php

@@ -6,10 +6,8 @@ use App\ApiResources\Organization\OrganizationCreationRequest;
 use App\ApiResources\Organization\OrganizationDeletionRequest;
 use App\ApiResources\Organization\OrganizationMemberCreationRequest;
 use App\Entity\Access\Access;
-use App\Entity\Billing\BillingSetting;
 use App\Entity\Core\AddressPostal;
 use App\Entity\Core\ContactPoint;
-use App\Entity\Education\CriteriaNotation;
 use App\Entity\Education\Cycle;
 use App\Entity\Network\NetworkOrganization;
 use App\Entity\Organization\Organization;
@@ -28,18 +26,17 @@ use App\Repository\Core\CountryRepository;
 use App\Repository\Organization\OrganizationRepository;
 use App\Repository\Person\PersonRepository;
 use App\Service\Dolibarr\DolibarrApiService;
+use App\Service\Organization\Utils as OrganizationUtils;
 use App\Service\Typo3\BindFileService;
 use App\Service\Typo3\SubdomainService;
 use App\Service\Typo3\Typo3Service;
 use App\Service\Utils\DatesUtils;
-use Doctrine\Common\Collections\Collection;
+use App\Service\Utils\SecurityUtils;
 use Doctrine\ORM\EntityManagerInterface;
 use Elastica\Param;
-use Exception;
 use libphonenumber\NumberParseException;
 use libphonenumber\PhoneNumberUtil;
 use Psr\Log\LoggerInterface;
-use SebastianBergmann\Type\RuntimeException;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\String\ByteString;
 use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
@@ -47,24 +44,23 @@ use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
 use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
 use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 use Symfony\Contracts\Service\Attribute\Required;
-use Throwable;
-use App\Service\Organization\Utils as OrganizationUtils;
 
 class OrganizationFactory
 {
     private LoggerInterface $logger;
 
     public function __construct(
-        private readonly SubdomainService       $subdomainService,
+        private readonly SubdomainService $subdomainService,
         private readonly OrganizationRepository $organizationRepository,
-        private readonly CountryRepository      $countryRepository,
-        private readonly OrganizationUtils      $organizationUtils,
-        private readonly Typo3Service           $typo3Service,
-        private readonly DolibarrApiService     $dolibarrApiService,
+        private readonly CountryRepository $countryRepository,
+        private readonly OrganizationUtils $organizationUtils,
+        private readonly Typo3Service $typo3Service,
+        private readonly DolibarrApiService $dolibarrApiService,
         private readonly EntityManagerInterface $entityManager,
-        private readonly PersonRepository       $personRepository,
-        private readonly BindFileService        $bindFileService,
-    ) {}
+        private readonly PersonRepository $personRepository,
+        private readonly BindFileService $bindFileService,
+    ) {
+    }
 
     #[Required]
     /** @see https://symfony.com/doc/current/logging/channels_handlers.html#how-to-autowire-logger-channels */
@@ -74,17 +70,15 @@ class OrganizationFactory
     }
 
     /**
-     * Créé une nouvelle organisation à partir des données contenues dans une OrganizationCreationRequest
+     * Créé une nouvelle organisation à partir des données contenues dans une OrganizationCreationRequest.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest
-     * @return Organization
      * @throws TransportExceptionInterface
-     * @throws Throwable
+     * @throws \Throwable
      */
     public function create(OrganizationCreationRequest $organizationCreationRequest): Organization
     {
         $this->logger->info(
-            "Start the creation of a new organization named '" . $organizationCreationRequest->getName() . "'"
+            "Start the creation of a new organization named '".$organizationCreationRequest->getName()."'"
         );
 
         $this->entityManager->beginTransaction();
@@ -92,16 +86,16 @@ class OrganizationFactory
         try {
             // On vérifie si cette organisation n'existe pas déjà
             if ($this->isExistingOrganization($organizationCreationRequest)) {
-                throw new \RuntimeException('An organization named ' . $organizationCreationRequest->getName() . ' already exists');
+                throw new \RuntimeException('An organization named '.$organizationCreationRequest->getName().' already exists');
             }
 
             // On vérifie la validité et la disponibilité du sous domaine
             $this->validateSubdomain($organizationCreationRequest->getSubdomain());
-            $this->logger->info("Subdomain is valid and available : '" . $organizationCreationRequest->getSubdomain() . "'");
+            $this->logger->info("Subdomain is valid and available : '".$organizationCreationRequest->getSubdomain()."'");
 
             // On construit l'organisation et ses relations
             $organization = $this->makeOrganizationWithRelations($organizationCreationRequest);
-            $this->logger->info("Organization created with all its relations");
+            $this->logger->info('Organization created with all its relations');
 
             // On persiste et on commit
             $this->entityManager->persist($organization);
@@ -112,28 +106,27 @@ class OrganizationFactory
                 $organization,
                 $organizationCreationRequest->isClient()
             );
-            $this->logger->info("New dolibarr structure created (uid : " . $dolibarrId . ")");
+            $this->logger->info('New dolibarr structure created (uid : '.$dolibarrId.')');
 
             $this->entityManager->commit();
-            $this->logger->debug(" - New entities committed in DB");
-
-            $this->logger->info("Organization persisted in the DB");
+            $this->logger->debug(' - New entities committed in DB');
 
+            $this->logger->info('Organization persisted in the DB');
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened, operation cancelled\n" . $e);
+            $this->logger->critical("An error happened, operation cancelled\n".$e);
             $this->entityManager->rollback();
             throw $e;
         }
 
         // Register the subdomain into the BindFile (takes up to 5min to take effect)
         $this->bindFileService->registerSubdomain($organizationCreationRequest->getSubdomain());
-        $this->logger->info("Subdomain registered");
+        $this->logger->info('Subdomain registered');
 
         // Création du site typo3 (on est obligé d'attendre que l'organisation soit persistée en base)
         if ($organizationCreationRequest->getCreateWebsite()) {
             $this->createTypo3Website($organization);
         } else {
-            $this->logger->warning("Typo3 website creation was not required");
+            $this->logger->warning('Typo3 website creation was not required');
         }
 
         return $organization;
@@ -141,9 +134,6 @@ class OrganizationFactory
 
     /**
      * Une organisation du même nom existe-t-elle déjà à la même adresse ?
-     *
-     * @param OrganizationCreationRequest $organizationCreationRequest
-     * @return bool
      */
     protected function isExistingOrganization(OrganizationCreationRequest $organizationCreationRequest): bool
     {
@@ -157,24 +147,22 @@ class OrganizationFactory
     }
 
     /**
-     * Vérifie la disponibilité et la validité d'un sous domaine
+     * Vérifie la disponibilité et la validité d'un sous domaine.
      *
-     * @param string $subdomainValue
-     * @return void
      * @throws \Exception
      */
     protected function validateSubdomain(string $subdomainValue): void
     {
         if (!$this->subdomainService->isValidSubdomain($subdomainValue)) {
-            throw new \RuntimeException("Not a valid subdomain : " . $subdomainValue);
+            throw new \RuntimeException('Not a valid subdomain : '.$subdomainValue);
         }
 
         if ($this->subdomainService->isReservedSubdomain($subdomainValue)) {
-            throw new \RuntimeException("This subdomain is not available : " . $subdomainValue);
+            throw new \RuntimeException('This subdomain is not available : '.$subdomainValue);
         }
 
         if ($this->subdomainService->isRegistered($subdomainValue)) {
-            throw new \RuntimeException("This subdomain is already registered : " . $subdomainValue);
+            throw new \RuntimeException('This subdomain is already registered : '.$subdomainValue);
         }
     }
 
@@ -182,60 +170,57 @@ class OrganizationFactory
      * Créé une nouvelle instance d'organisation, et toutes les instances liées (paramètres, contact, adresses, ...),
      * selon le contenu de la requête de création.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest
-     * @return Organization
-     * @throws Throwable
+     * @throws \Throwable
      */
     protected function makeOrganizationWithRelations(
-        OrganizationCreationRequest $organizationCreationRequest
-    ): Organization
-    {
+        OrganizationCreationRequest $organizationCreationRequest,
+    ): Organization {
         // Création de l'organisation
         $organization = $this->makeOrganization($organizationCreationRequest);
-        $this->logger->debug(" - Organization created");
+        $this->logger->debug(' - Organization created');
 
         // Création des Parameters
         $parameters = $this->makeParameters($organizationCreationRequest);
         $organization->setParameters($parameters);
-        $this->logger->debug(" - Parameters created");
+        $this->logger->debug(' - Parameters created');
 
         // Création des Settings
         $settings = $this->makeSettings($organizationCreationRequest);
         $organization->setSettings($settings);
-        $this->logger->debug(" - Settings created");
+        $this->logger->debug(' - Settings created');
 
         // Création de l'adresse postale
         $organizationAddressPostal = $this->makePostalAddress($organizationCreationRequest);
         $organization->addOrganizationAddressPostal($organizationAddressPostal);
-        $this->logger->debug(" - OrganizationAddressPostal created");
+        $this->logger->debug(' - OrganizationAddressPostal created');
 
         // Création du point de contact
         $contactPoint = $this->makeContactPoint($organizationCreationRequest);
         $organization->addContactPoint($contactPoint);
-        $this->logger->debug(" - ContactPoint created");
+        $this->logger->debug(' - ContactPoint created');
 
         // Rattachement au réseau
         $networkOrganization = $this->makeNetworkOrganization($organizationCreationRequest);
         $organization->addNetworkOrganization($networkOrganization);
-        $this->logger->debug(" - NetworkOrganization created");
+        $this->logger->debug(' - NetworkOrganization created');
 
         // Créé l'admin
         $adminAccess = $this->makeAdminAccess($organizationCreationRequest);
         $organization->addAccess($adminAccess);
-        $this->logger->debug(" - Admin access created");
+        $this->logger->debug(' - Admin access created');
 
         // Création des cycles
         foreach ($this->makeCycles() as $cycle) {
             $organization->addCycle($cycle);
         }
-        $this->logger->debug(" - Cycles created");
+        $this->logger->debug(' - Cycles created');
 
         // Création du président (si renseigné)
         $presidentCreationRequest = $organizationCreationRequest->getPresident();
         if ($presidentCreationRequest !== null) {
             $presidentAccess = $this->makeAccess($presidentCreationRequest);
             $organization->addAccess($presidentAccess);
-            $this->logger->debug(" - President access created");
+            $this->logger->debug(' - President access created');
         }
 
         // Création du directeur (si renseigné)
@@ -243,7 +228,7 @@ class OrganizationFactory
         if ($directorCreationRequest !== null) {
             $directorAccess = $this->makeAccess($directorCreationRequest);
             $organization->addAccess($directorAccess);
-            $this->logger->debug(" - Director access created");
+            $this->logger->debug(' - Director access created');
         }
 
         // Création du sous-domaine
@@ -253,19 +238,16 @@ class OrganizationFactory
         // <--- Pour la rétrocompatibilité avec la v1 ; pourra être supprimé lorsque la migration sera achevée
         $parameters = $organization->getParameters();
         $parameters->setSubDomain($organizationCreationRequest->getSubdomain());
-        $parameters->setOtherWebsite('https://' . $organizationCreationRequest->getSubdomain() . '.opentalent.fr');
+        $parameters->setOtherWebsite('https://'.$organizationCreationRequest->getSubdomain().'.opentalent.fr');
         $this->entityManager->persist($parameters);
         // --->
-        $this->logger->debug(" - Subdomain created");
+        $this->logger->debug(' - Subdomain created');
 
         return $organization;
     }
 
     /**
-     * Créé une nouvelle instance d'organisation
-     *
-     * @param OrganizationCreationRequest $organizationCreationRequest
-     * @return Organization
+     * Créé une nouvelle instance d'organisation.
      */
     protected function makeOrganization(OrganizationCreationRequest $organizationCreationRequest): Organization
     {
@@ -282,40 +264,44 @@ class OrganizationFactory
     }
 
     /**
-     * Create a new Parameters object from the data in an OrganizationCreationRequest
+     * Create a new Parameters object from the data in an OrganizationCreationRequest.
      *
      * @param OrganizationCreationRequest $organizationCreationRequest The organization creation request
+     *
      * @return Parameters The created Parameters object
-     * @throws Throwable If there is an error
+     *
+     * @throws \Throwable If there is an error
      */
     protected function makeParameters(OrganizationCreationRequest $organizationCreationRequest): Parameters
     {
         $parameters = new Parameters();
         $this->entityManager->persist($parameters);
+
         return $parameters;
     }
 
     /**
      * Creates a new instance of the Settings class based on the given OrganizationCreationRequest object.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data.
+     * @param OrganizationCreationRequest $organizationCreationRequest the OrganizationCreationRequest object containing the required data
      *
-     * @return Settings The newly created instance of the Settings class.
+     * @return Settings the newly created instance of the Settings class
      */
     protected function makeSettings(OrganizationCreationRequest $organizationCreationRequest): Settings
     {
         $settings = new Settings();
         $settings->setProduct($organizationCreationRequest->getProduct());
         $this->entityManager->persist($settings);
+
         return $settings;
     }
 
     /**
      * Creates a new instance of the OrganizationAddressPostal class based on the given OrganizationCreationRequest object.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data.
+     * @param OrganizationCreationRequest $organizationCreationRequest the OrganizationCreationRequest object containing the required data
      *
-     * @return OrganizationAddressPostal The newly created instance of the OrganizationAddressPostal class.
+     * @return OrganizationAddressPostal the newly created instance of the OrganizationAddressPostal class
      */
     protected function makePostalAddress(OrganizationCreationRequest $organizationCreationRequest): OrganizationAddressPostal
     {
@@ -340,9 +326,10 @@ class OrganizationFactory
     /**
      * Creates a new instance of the ContactPoint class based on the given OrganizationCreationRequest object.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data.
+     * @param OrganizationCreationRequest $organizationCreationRequest the OrganizationCreationRequest object containing the required data
+     *
+     * @return ContactPoint the newly created instance of the ContactPoint class
      *
-     * @return ContactPoint The newly created instance of the ContactPoint class.
      * @throws NumberParseException
      */
     protected function makeContactPoint(OrganizationCreationRequest $organizationCreationRequest): ContactPoint
@@ -362,22 +349,22 @@ class OrganizationFactory
     /**
      * Creates a new instance of the NetworkOrganization class based on the given OrganizationCreationRequest object.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data.
+     * @param OrganizationCreationRequest $organizationCreationRequest the OrganizationCreationRequest object containing the required data
      *
-     * @return NetworkOrganization The newly created instance of the NetworkOrganization class.
+     * @return NetworkOrganization the newly created instance of the NetworkOrganization class
      *
-     * @throws \RuntimeException|\Exception if no parent organization is found for the given parent ID or if no network is found for the given network ID.
+     * @throws \RuntimeException|\Exception if no parent organization is found for the given parent ID or if no network is found for the given network ID
      */
     protected function makeNetworkOrganization(OrganizationCreationRequest $organizationCreationRequest): NetworkOrganization
     {
         $parent = $this->organizationRepository->find($organizationCreationRequest->getParentId());
         if (!$parent) {
-            throw new \RuntimeException('No parent organization found for id ' . $organizationCreationRequest->getParentId());
+            throw new \RuntimeException('No parent organization found for id '.$organizationCreationRequest->getParentId());
         }
 
         $networkOrganization = $this->organizationUtils->getActiveNetworkOrganization($parent);
         if (!$networkOrganization) {
-            throw new \RuntimeException('No network found for parent ' . $organizationCreationRequest->getParentId());
+            throw new \RuntimeException('No network found for parent '.$organizationCreationRequest->getParentId());
         }
 
         $network = $networkOrganization->getNetwork();
@@ -385,7 +372,7 @@ class OrganizationFactory
         // Si réseau CMF, on vérifie que le matricule est valide
         if ($network->getId() === NetworkEnum::CMF->value) {
             if (!preg_match("/FR\d{12}/", $organizationCreationRequest->getIdentifier())) {
-                throw new \RuntimeException("CMF identifier is missing or invalid.");
+                throw new \RuntimeException('CMF identifier is missing or invalid.');
             }
         }
 
@@ -401,14 +388,14 @@ class OrganizationFactory
     /**
      * Creates a new instance of the Access class with admin access based on the given OrganizationCreationRequest object.
      *
-     * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data.
+     * @param OrganizationCreationRequest $organizationCreationRequest the OrganizationCreationRequest object containing the required data
      *
-     * @return Access The newly created instance of the Access class with admin access.
+     * @return Access the newly created instance of the Access class with admin access
      */
     protected function makeAdminAccess(OrganizationCreationRequest $organizationCreationRequest): Access
     {
         $admin = new Person();
-        $admin->setUsername('admin' . strtolower($organizationCreationRequest->getSubdomain()));
+        $admin->setUsername('admin'.strtolower($organizationCreationRequest->getSubdomain()));
         $randomString = ByteString::fromRandom(32)->toString();
         $admin->setPassword($randomString);
         $this->entityManager->persist($admin);
@@ -424,7 +411,7 @@ class OrganizationFactory
     /**
      * Creates an array of Cycle objects based on a predefined set of data.
      *
-     * @return Cycle[] An array of Cycle objects.
+     * @return Cycle[] an array of Cycle objects
      */
     protected function makeCycles(): array
     {
@@ -455,16 +442,17 @@ class OrganizationFactory
     /**
      * Creates an Access object based on the given OrganizationMemberCreationRequest.
      *
-     * @param int|OrganizationMemberCreationRequest $creationRequestData The request object containing the
+     * @param int|OrganizationMemberCreationRequest $creationRequestData the request object containing the
      *                                                                   necessary data for creating a Person object,
-     *                                                                   or the id of an existing one.
-     * @return Access The created Access object.
+     *                                                                   or the id of an existing one
+     *
+     * @return Access the created Access object
+     *
      * @throws NumberParseException
      */
     protected function makeAccess(
-        int | OrganizationMemberCreationRequest $creationRequestData
-    ): Access
-    {
+        int|OrganizationMemberCreationRequest $creationRequestData,
+    ): Access {
         if (is_int($creationRequestData)) {
             $person = $this->personRepository->find($creationRequestData);
         } else {
@@ -499,10 +487,11 @@ class OrganizationFactory
     /**
      * Creates a PersonAddressPostal object based on the given OrganizationMemberCreationRequest.
      *
-     * @param OrganizationMemberCreationRequest $organizationMemberCreationRequest The request object containing the
+     * @param OrganizationMemberCreationRequest $organizationMemberCreationRequest the request object containing the
      *                                                                             necessary data for creating a
-     *                                                                             PersonAddressPostal object.
-     * @return PersonAddressPostal The created PersonAddressPostal object.
+     *                                                                             PersonAddressPostal object
+     *
+     * @return PersonAddressPostal the created PersonAddressPostal object
      */
     protected function makePersonPostalAddress(OrganizationMemberCreationRequest $organizationMemberCreationRequest): PersonAddressPostal
     {
@@ -528,9 +517,10 @@ class OrganizationFactory
     /**
      * Creates a new instance of the ContactPoint class based on the given OrganizationCreationRequest object.
      *
-     * @param OrganizationMemberCreationRequest $organizationMemberCreationRequest The OrganizationMemberCreationRequest object containing the required data.
+     * @param OrganizationMemberCreationRequest $organizationMemberCreationRequest the OrganizationMemberCreationRequest object containing the required data
+     *
+     * @return ContactPoint the newly created instance of the ContactPoint class
      *
-     * @return ContactPoint The newly created instance of the ContactPoint class.
      * @throws NumberParseException
      */
     protected function makePersonContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest): ContactPoint
@@ -549,6 +539,7 @@ class OrganizationFactory
         }
 
         $this->entityManager->persist($contactPoint);
+
         return $contactPoint;
     }
 
@@ -563,14 +554,15 @@ class OrganizationFactory
     }
 
     /**
-     * Créé le site Typo3 et retourne l'id de la page racine du site nouvellement créé, ou null en cas d'erreur
+     * Créé le site Typo3 et retourne l'id de la page racine du site nouvellement créé, ou null en cas d'erreur.
      *
      * @throws RedirectionExceptionInterface
      * @throws ClientExceptionInterface
      * @throws TransportExceptionInterface
      * @throws ServerExceptionInterface
      */
-    protected function createTypo3Website(Organization $organization): ?int {
+    protected function createTypo3Website(Organization $organization): ?int
+    {
         $response = $this->typo3Service->createSite($organization->getId());
         $rootPageUid = json_decode($response->getContent(), true);
 
@@ -590,25 +582,23 @@ class OrganizationFactory
     }
 
     /**
-     * /!\ Danger zone /!\
+     * /!\ Danger zone /!\.
      *
      * Supprime définitivement une organisation, ses données, ses fichiers, son site internet, et son profil Dolibarr.
      *
      * Pour éviter une suppression accidentelle, cette méthode ne doit pouvoir être exécutée que si la requête a été
      * envoyée depuis le localhost.
      *
-     * @param OrganizationDeletionRequest $organizationDeletionRequest
-     * @return OrganizationDeletionRequest
-     * @throws Exception
+     * @throws \Exception
      */
     public function delete(OrganizationDeletionRequest $organizationDeletionRequest): OrganizationDeletionRequest
     {
-        $this->preventIfNotLocalhost();
+        SecurityUtils::preventIfNotLocalhost();
 
         $organization = $this->organizationRepository->find($organizationDeletionRequest->getOrganizationId());
 
         $this->logger->info(
-            "Start the deletion of organization '" . $organization->getName() . "' [" . $organization->getId() . "]"
+            "Start the deletion of organization '".$organization->getName()."' [".$organization->getId().']'
         );
 
         $this->entityManager->beginTransaction();
@@ -629,7 +619,7 @@ class OrganizationFactory
             $this->entityManager->flush();
             $this->entityManager->commit();
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened, operation cancelled\n" . $e);
+            $this->logger->critical("An error happened, operation cancelled\n".$e);
             $this->entityManager->rollback();
             throw $e;
         }
@@ -637,15 +627,15 @@ class OrganizationFactory
         try {
             $this->deleteTypo3Website($organization);
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened while deleting the Typo3 website, please proceed manually.");
+            $this->logger->critical('An error happened while deleting the Typo3 website, please proceed manually.');
             $this->logger->debug($e);
             $withError = true;
         }
 
         try {
-            $this->deleteDolibarrSociety($organization);
+            $this->switchDolibarrSocietyToProspect($organization);
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened while deleting the Dolibarr society, please proceed manually.");
+            $this->logger->critical('An error happened while updating the Dolibarr society, please proceed manually.');
             $this->logger->debug($e);
             $withError = true;
         }
@@ -653,7 +643,7 @@ class OrganizationFactory
         try {
             $this->deleteLocalDirectories($organization);
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened while deleting the local directories, please proceed manually.");
+            $this->logger->critical('An error happened while deleting the local directories, please proceed manually.');
             $this->logger->debug($e);
             $withError = true;
         }
@@ -661,7 +651,7 @@ class OrganizationFactory
         try {
             $this->deleteDirectoriesV1($organization);
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened while deleting the V1 directories, please proceed manually.");
+            $this->logger->critical('An error happened while deleting the V1 directories, please proceed manually.');
             $this->logger->debug($e);
             $withError = true;
         }
@@ -669,14 +659,14 @@ class OrganizationFactory
         try {
             $this->deleteDirectories59($organization);
         } catch (\Exception $e) {
-            $this->logger->critical("An error happened while deleting the 5.9 directories, please proceed manually.");
+            $this->logger->critical('An error happened while deleting the 5.9 directories, please proceed manually.');
             $this->logger->debug($e);
             $withError = true;
         }
 
         if ($withError) {
             $organizationDeletionRequest->setStatus(OrganizationDeletionRequest::STATUS_OK_WITH_ERRORS);
-            $this->logger->warning("-- Operation ended with errors, check the logs for more information --");
+            $this->logger->warning('-- Operation ended with errors, check the logs for more information --');
         } else {
             $organizationDeletionRequest->setStatus(OrganizationDeletionRequest::STATUS_OK);
         }
@@ -684,29 +674,9 @@ class OrganizationFactory
         return $organizationDeletionRequest;
     }
 
-    /**
-     * Lève une exception si la méthode a été appelée dans le cadre d'un appel API originaire d'un hôte
-     * différent de localhost.
-     *
-     * @return void
-     */
-    protected function preventIfNotLocalhost(): void
-    {
-        if (
-            $_SERVER &&
-            $_SERVER['APP_ENV'] !== 'docker' &&
-            $_SERVER['SERVER_ADDR'] !== $_SERVER['REMOTE_ADDR']
-        ) {
-            throw new \RuntimeException("This operation is restricted to localhost");
-        }
-    }
-
     /**
      * Supprime tous les Access d'une organisation, ainsi que la Person
-     * rattachée (si celle-ci n'est pas liée à d'autres Access)
-     *
-     * @param Organization $organization
-     * @return void
+     * rattachée (si celle-ci n'est pas liée à d'autres Access).
      */
     protected function deleteOrganizationAccesses(Organization $organization): void
     {
@@ -720,36 +690,36 @@ class OrganizationFactory
     }
 
     // TODO: à revoir, c'est du many to many
-//    protected function removeTypeOfPractices(Organization $organization): void {
-//        foreach ($organization->getTypeOfPractices() as $typeOfPractice) {
-//            $organization->removeTypeOfPractice($typeOfPractice);
-//        }
-//    }
+    //    protected function removeTypeOfPractices(Organization $organization): void {
+    //        foreach ($organization->getTypeOfPractices() as $typeOfPractice) {
+    //            $organization->removeTypeOfPractice($typeOfPractice);
+    //        }
+    //    }
 
     // TODO: à revoir, c'est du many to many
-//    protected function deleteContactPoints(Organization $organization): void
-//    {
-//        foreach ($organization->getContactPoints() as $contactPoint) {
-//            $this->entityManager->remove($contactPoint);
-//        }
-//    }
+    //    protected function deleteContactPoints(Organization $organization): void
+    //    {
+    //        foreach ($organization->getContactPoints() as $contactPoint) {
+    //            $this->entityManager->remove($contactPoint);
+    //        }
+    //    }
 
     // TODO: à revoir, c'est du many to many
-//    protected function deleteBankAccounts(Organization $organization): void {
-//        foreach ($organization->getBankAccounts() as $bankAccount) {
-//            $this->entityManager->remove($bankAccount);
-//        }
-//    }
+    //    protected function deleteBankAccounts(Organization $organization): void {
+    //        foreach ($organization->getBankAccounts() as $bankAccount) {
+    //            $this->entityManager->remove($bankAccount);
+    //        }
+    //    }
 
     protected function deleteTypo3Website(Organization $organization): void
     {
         // TODO: implement
-//        $this->typo3Service->deleteSite($organization->getId());
+        //        $this->typo3Service->deleteSite($organization->getId());
     }
 
-    protected function deleteDolibarrSociety(Organization $organization): void
+    protected function switchDolibarrSocietyToProspect(Organization $organization): void
     {
-        // TODO: implement
+        $this->dolibarrApiService->switchSocietyToProspect($organization->getId());
     }
 
     protected function deleteLocalDirectories(Organization $organization): void

+ 23 - 0
src/Service/Utils/SecurityUtils.php

@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Service\Utils;
+
+class SecurityUtils
+{
+    /**
+     * Lève une exception si la méthode a été appelée dans le cadre d'un appel API originaire d'un hôte
+     * différent de localhost.
+     */
+    public static function preventIfNotLocalhost(): void
+    {
+        if (
+            $_SERVER
+            && $_SERVER['APP_ENV'] !== 'docker'
+            && $_SERVER['SERVER_ADDR'] !== $_SERVER['REMOTE_ADDR']
+        ) {
+            throw new \RuntimeException('This operation is restricted to localhost');
+        }
+    }
+}

+ 55 - 4
tests/Unit/Service/Dolibarr/DolibarrApiServiceTest.php

@@ -461,7 +461,7 @@ class DolibarrApiServiceTest extends TestCase
             'client' => 2,
             'code_client' => -1,
             'import_key' => 'crm',
-            'array_options' => ['options_2iopen_organization_id' => 123]
+            'array_options' => ['options_2iopen_organization_id' => 123],
         ];
 
         $response = $this->getMockBuilder(ResponseInterface::class)->getMock();
@@ -470,7 +470,7 @@ class DolibarrApiServiceTest extends TestCase
         $dolibarrApiService
             ->expects(self::once())
             ->method('post')
-            ->with("/thirdparties", $expectedPostBody)
+            ->with('/thirdparties', $expectedPostBody)
             ->willReturn($response);
 
         $result = $dolibarrApiService->createSociety($organization);
@@ -497,7 +497,7 @@ class DolibarrApiServiceTest extends TestCase
             'client' => 1,
             'code_client' => -1,
             'import_key' => 'crm',
-            'array_options' => ['options_2iopen_organization_id' => 123]
+            'array_options' => ['options_2iopen_organization_id' => 123],
         ];
 
         $response = $this->getMockBuilder(ResponseInterface::class)->getMock();
@@ -506,11 +506,62 @@ class DolibarrApiServiceTest extends TestCase
         $dolibarrApiService
             ->expects(self::once())
             ->method('post')
-            ->with("/thirdparties", $expectedPostBody)
+            ->with('/thirdparties', $expectedPostBody)
             ->willReturn($response);
 
         $result = $dolibarrApiService->createSociety($organization, true);
 
         $this->assertEquals(456, $result);
     }
+
+    public function testSwitchSocietyToProspect(): void
+    {
+        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
+            ->setConstructorArgs([$this->client])
+            ->setMethodsExcept(['switchSocietyToProspect'])
+            ->getMock();
+
+        $response = $this->getMockBuilder(ResponseInterface::class)->getMock();
+        $response->method('getStatusCode')->willReturn(200);
+
+        $dolibarrApiService
+            ->method('getSociety')
+            ->with(123)
+            ->willReturn(['id' => 456]);
+
+        $dolibarrApiService
+            ->expects(self::once())
+            ->method('put')
+            ->with('thirdparties/456', ['client' => 2])
+            ->willReturn($response);
+
+        $dolibarrApiService->switchSocietyToProspect(123);
+    }
+
+    public function testSwitchSocietyToProspectWithError(): void
+    {
+        $dolibarrApiService = $this->getMockBuilder(DolibarrApiService::class)
+            ->setConstructorArgs([$this->client])
+            ->setMethodsExcept(['switchSocietyToProspect'])
+            ->getMock();
+
+        $response = $this->getMockBuilder(ResponseInterface::class)->getMock();
+        $response->method('getStatusCode')->willReturn(500);
+
+        $dolibarrApiService
+            ->method('getSociety')
+            ->with(123)
+            ->willReturn(['id' => 456]);
+
+        $dolibarrApiService
+            ->expects(self::once())
+            ->method('put')
+            ->with('thirdparties/456', ['client' => 2])
+            ->willReturn($response);
+
+        $this->expectException(HttpException::class);
+        $this->expectExceptionMessage('Error while updating the society in Dolibarr');
+
+        $dolibarrApiService->switchSocietyToProspect(123);
+    }
 }

+ 123 - 73
tests/Unit/Service/Organization/OrganizationFactoryTest.php

@@ -1,4 +1,5 @@
 <?php
+
 declare(strict_types=1);
 
 namespace App\Tests\Unit\Service\Organization;
@@ -41,14 +42,14 @@ use App\Service\Typo3\Typo3Service;
 use App\Service\Utils\DatesUtils;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\ORM\EntityManagerInterface;
-use Elastica\Param;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Contracts\HttpClient\ResponseInterface;
 
-class TestableOrganizationFactory extends OrganizationFactory {
+class TestableOrganizationFactory extends OrganizationFactory
+{
     public function isExistingOrganization(OrganizationCreationRequest $organizationCreationRequest): bool
     {
         return parent::isExistingOrganization($organizationCreationRequest);
@@ -60,60 +61,73 @@ class TestableOrganizationFactory extends OrganizationFactory {
     }
 
     public function makeOrganizationWithRelations(
-        OrganizationCreationRequest $organizationCreationRequest
+        OrganizationCreationRequest $organizationCreationRequest,
     ): Organization {
         return parent::makeOrganizationWithRelations($organizationCreationRequest);
     }
 
-    public function makeOrganization(OrganizationCreationRequest $organizationCreationRequest): Organization {
+    public function makeOrganization(OrganizationCreationRequest $organizationCreationRequest): Organization
+    {
         return parent::makeOrganization($organizationCreationRequest);
     }
 
-    public function makeParameters(OrganizationCreationRequest $organizationCreationRequest): Parameters {
+    public function makeParameters(OrganizationCreationRequest $organizationCreationRequest): Parameters
+    {
         return parent::makeParameters($organizationCreationRequest);
     }
 
-    public function makeSettings(OrganizationCreationRequest $organizationCreationRequest): Settings {
+    public function makeSettings(OrganizationCreationRequest $organizationCreationRequest): Settings
+    {
         return parent::makeSettings($organizationCreationRequest);
     }
 
-    public function makePostalAddress(OrganizationCreationRequest $organizationCreationRequest): OrganizationAddressPostal {
+    public function makePostalAddress(OrganizationCreationRequest $organizationCreationRequest): OrganizationAddressPostal
+    {
         return parent::makePostalAddress($organizationCreationRequest);
     }
 
-    public function makeContactPoint(OrganizationCreationRequest $organizationCreationRequest): ContactPoint {
+    public function makeContactPoint(OrganizationCreationRequest $organizationCreationRequest): ContactPoint
+    {
         return parent::makeContactPoint($organizationCreationRequest);
     }
 
-    public function makeNetworkOrganization(OrganizationCreationRequest $organizationCreationRequest): NetworkOrganization {
+    public function makeNetworkOrganization(OrganizationCreationRequest $organizationCreationRequest): NetworkOrganization
+    {
         return parent::makeNetworkOrganization($organizationCreationRequest);
     }
 
-    public function makeAdminAccess(OrganizationCreationRequest $organizationCreationRequest): Access {
+    public function makeAdminAccess(OrganizationCreationRequest $organizationCreationRequest): Access
+    {
         return parent::makeAdminAccess($organizationCreationRequest);
     }
 
-    public function makeCycles(): array {
+    public function makeCycles(): array
+    {
         return parent::makeCycles();
     }
 
-    public function makeAccess(int|OrganizationMemberCreationRequest $creationRequestData): Access {
+    public function makeAccess(int|OrganizationMemberCreationRequest $creationRequestData): Access
+    {
         return parent::makeAccess($creationRequestData);
     }
 
-    public function makePersonPostalAddress(OrganizationMemberCreationRequest $organizationMemberCreationRequest): PersonAddressPostal {
+    public function makePersonPostalAddress(OrganizationMemberCreationRequest $organizationMemberCreationRequest): PersonAddressPostal
+    {
         return parent::makePersonPostalAddress($organizationMemberCreationRequest);
     }
 
-    public function makePersonContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest): ContactPoint {
+    public function makePersonContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest): ContactPoint
+    {
         return parent::makePersonContactPoint($organizationMemberCreationRequest);
     }
 
-    public function makeSubdomain(OrganizationCreationRequest $organizationCreationRequest): Subdomain {
+    public function makeSubdomain(OrganizationCreationRequest $organizationCreationRequest): Subdomain
+    {
         return parent::makeSubdomain($organizationCreationRequest);
     }
 
-    public function createTypo3Website(Organization $organization): ?int {
+    public function createTypo3Website(Organization $organization): ?int
+    {
         return parent::createTypo3Website($organization);
     }
 
@@ -127,9 +141,9 @@ class TestableOrganizationFactory extends OrganizationFactory {
         parent::deleteTypo3Website($organization);
     }
 
-    public function deleteDolibarrSociety(Organization $organization): void
+    public function switchDolibarrSocietyToProspect(Organization $organization): void
     {
-        parent::deleteDolibarrSociety($organization);
+        parent::switchDolibarrSocietyToProspect($organization);
     }
 
     public function deleteLocalDirectories(Organization $organization): void
@@ -150,16 +164,16 @@ class TestableOrganizationFactory extends OrganizationFactory {
 
 class OrganizationFactoryTest extends TestCase
 {
-    private readonly MockObject | SubdomainService       $subdomainService;
-    private readonly MockObject | OrganizationRepository $organizationRepository;
-    private readonly MockObject | CountryRepository      $countryRepository;
-    private readonly MockObject | OrganizationUtils      $organizationUtils;
-    private readonly MockObject | Typo3Service           $typo3Service;
-    private readonly MockObject | DolibarrApiService     $dolibarrApiService;
-    private readonly MockObject | EntityManagerInterface $entityManager;
-    private readonly MockObject | PersonRepository       $personRepository;
-    private readonly MockObject | BindFileService        $bindFileService;
-    private readonly MockObject | LoggerInterface        $logger;
+    private readonly MockObject|SubdomainService $subdomainService;
+    private readonly MockObject|OrganizationRepository $organizationRepository;
+    private readonly MockObject|CountryRepository $countryRepository;
+    private readonly MockObject|OrganizationUtils $organizationUtils;
+    private readonly MockObject|Typo3Service $typo3Service;
+    private readonly MockObject|DolibarrApiService $dolibarrApiService;
+    private readonly MockObject|EntityManagerInterface $entityManager;
+    private readonly MockObject|PersonRepository $personRepository;
+    private readonly MockObject|BindFileService $bindFileService;
+    private readonly MockObject|LoggerInterface $logger;
 
     public function setUp(): void
     {
@@ -180,7 +194,7 @@ class OrganizationFactoryTest extends TestCase
         DatesUtils::clearFakeDatetime();
     }
 
-    private function getOrganizationFactoryMockFor(string $methodName): TestableOrganizationFactory | MockObject
+    private function getOrganizationFactoryMockFor(string $methodName): TestableOrganizationFactory|MockObject
     {
         $organizationFactory = $this
             ->getMockBuilder(TestableOrganizationFactory::class)
@@ -194,7 +208,7 @@ class OrganizationFactoryTest extends TestCase
                     $this->dolibarrApiService,
                     $this->entityManager,
                     $this->personRepository,
-                    $this->bindFileService
+                    $this->bindFileService,
                 ])
             ->setMethodsExcept(['setLoggerInterface', $methodName])
             ->getMock();
@@ -204,7 +218,8 @@ class OrganizationFactoryTest extends TestCase
         return $organizationFactory;
     }
 
-    public function testCreate(): void {
+    public function testCreate(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('create');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -250,10 +265,10 @@ class OrganizationFactoryTest extends TestCase
             ->withConsecutive(
                 ["Start the creation of a new organization named 'foo'"],
                 ["Subdomain is valid and available : 'subdomain'"],
-                ["Organization created with all its relations"],
-                ["New dolibarr structure created (uid : 456)"],
-                ["Organization persisted in the DB"],
-                ["Subdomain registered"],
+                ['Organization created with all its relations'],
+                ['New dolibarr structure created (uid : 456)'],
+                ['Organization persisted in the DB'],
+                ['Subdomain registered'],
             );
 
         $result = $organizationFactory->create($organizationCreationRequest);
@@ -264,7 +279,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testCreateWithRollback(): void {
+    public function testCreateWithRollback(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('create');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -306,7 +322,7 @@ class OrganizationFactoryTest extends TestCase
             ->withConsecutive(
                 ["Start the creation of a new organization named 'foo'"],
                 ["Subdomain is valid and available : 'subdomain'"],
-                ["Organization created with all its relations"]
+                ['Organization created with all its relations']
             );
 
         $this->logger
@@ -320,7 +336,8 @@ class OrganizationFactoryTest extends TestCase
         $result = $organizationFactory->create($organizationCreationRequest);
     }
 
-    public function testCreateWithExistingOrganization(): void {
+    public function testCreateWithExistingOrganization(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('create');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -365,12 +382,13 @@ class OrganizationFactoryTest extends TestCase
             );
 
         $this->expectException(\RuntimeException::class);
-        $this->expectExceptionMessage("An organization named foo already exists");
+        $this->expectExceptionMessage('An organization named foo already exists');
 
         $result = $organizationFactory->create($organizationCreationRequest);
     }
 
-    public function testCreateNoWebsiteAndIsClient(): void {
+    public function testCreateNoWebsiteAndIsClient(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('create');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -400,7 +418,7 @@ class OrganizationFactoryTest extends TestCase
         $this->logger
             ->expects(self::once())
             ->method('warning')
-            ->with("Typo3 website creation was not required");
+            ->with('Typo3 website creation was not required');
 
         $result = $organizationFactory->create($organizationCreationRequest);
 
@@ -429,7 +447,8 @@ class OrganizationFactoryTest extends TestCase
         $this->assertFalse($organizationFactory->isExistingOrganization($organizationCreationRequest2));
     }
 
-    public function testValidateSubdomain(): void {
+    public function testValidateSubdomain(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain');
 
         $this->subdomainService->expects(self::once())->method('isValidSubdomain')->willReturn(true);
@@ -439,7 +458,8 @@ class OrganizationFactoryTest extends TestCase
         $organizationFactory->validateSubdomain('foo');
     }
 
-    public function testValidateSubdomainIsNotValid(): void {
+    public function testValidateSubdomainIsNotValid(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain');
 
         $this->subdomainService->method('isValidSubdomain')->willReturn(false);
@@ -447,12 +467,13 @@ class OrganizationFactoryTest extends TestCase
         $this->subdomainService->method('isRegistered')->willReturn(false);
 
         $this->expectException(\RuntimeException::class);
-        $this->expectExceptionMessage("Not a valid subdomain : foo");
+        $this->expectExceptionMessage('Not a valid subdomain : foo');
 
         $organizationFactory->validateSubdomain('foo');
     }
 
-    public function testValidateSubdomainIsReserved(): void {
+    public function testValidateSubdomainIsReserved(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain');
 
         $this->subdomainService->method('isValidSubdomain')->willReturn(true);
@@ -460,12 +481,13 @@ class OrganizationFactoryTest extends TestCase
         $this->subdomainService->method('isRegistered')->willReturn(false);
 
         $this->expectException(\RuntimeException::class);
-        $this->expectExceptionMessage("This subdomain is not available : foo");
+        $this->expectExceptionMessage('This subdomain is not available : foo');
 
         $organizationFactory->validateSubdomain('foo');
     }
 
-    public function testValidateSubdomainIsRegistered(): void {
+    public function testValidateSubdomainIsRegistered(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('validateSubdomain');
 
         $this->subdomainService->method('isValidSubdomain')->willReturn(true);
@@ -473,7 +495,7 @@ class OrganizationFactoryTest extends TestCase
         $this->subdomainService->method('isRegistered')->willReturn(true);
 
         $this->expectException(\RuntimeException::class);
-        $this->expectExceptionMessage("This subdomain is already registered : foo");
+        $this->expectExceptionMessage('This subdomain is already registered : foo');
 
         $organizationFactory->validateSubdomain('foo');
     }
@@ -578,9 +600,9 @@ class OrganizationFactoryTest extends TestCase
             ->expects(self::exactly(2))
             ->method('makeAccess')
             ->willReturnMap([
-                    [$organizationMemberCreationRequest1, $access1],
-                    [$organizationMemberCreationRequest2, $access2]
-                ]);
+                [$organizationMemberCreationRequest1, $access1],
+                [$organizationMemberCreationRequest2, $access2],
+            ]);
 
         $organization
             ->expects(self::exactly(3))
@@ -613,7 +635,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testMakeOrganizationWithRelationsNoPresidentNoDirector() {
+    public function testMakeOrganizationWithRelationsNoPresidentNoDirector()
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeOrganizationWithRelations');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -792,7 +815,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testMakeNetworkOrganization(): void {
+    public function testMakeNetworkOrganization(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
 
         DatesUtils::setFakeDatetime('2024-01-01');
@@ -832,7 +856,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testMakeNetworkOrganizationMissingParent(): void {
+    public function testMakeNetworkOrganizationMissingParent(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -846,7 +871,8 @@ class OrganizationFactoryTest extends TestCase
         $organizationFactory->makeNetworkOrganization($organizationCreationRequest);
     }
 
-    public function testMakeNetworkOrganizationMissingNetwork(): void {
+    public function testMakeNetworkOrganizationMissingNetwork(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -869,7 +895,8 @@ class OrganizationFactoryTest extends TestCase
         $organizationFactory->makeNetworkOrganization($organizationCreationRequest);
     }
 
-    public function testMakeNetworkOrganizationIsCMFInvalidIdentifier(): void {
+    public function testMakeNetworkOrganizationIsCMFInvalidIdentifier(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -891,12 +918,13 @@ class OrganizationFactoryTest extends TestCase
             ->willReturn($networkOrganization);
 
         $this->expectException(\RuntimeException::class);
-        $this->expectExceptionMessage("CMF identifier is missing or invalid.");
+        $this->expectExceptionMessage('CMF identifier is missing or invalid.');
 
         $organizationFactory->makeNetworkOrganization($organizationCreationRequest);
     }
 
-    public function testMakeNetworkOrganizationIsNotCMFInvalidIdentifier(): void {
+    public function testMakeNetworkOrganizationIsNotCMFInvalidIdentifier(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeNetworkOrganization');
 
         $organizationCreationRequest = $this->getMockBuilder(OrganizationCreationRequest::class)->getMock();
@@ -991,7 +1019,7 @@ class OrganizationFactoryTest extends TestCase
             $this->assertFalse(
                 $cycle->getIsSystem()
             );
-            $i++;
+            ++$i;
         }
     }
 
@@ -1172,7 +1200,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testMakePersonContactPointNoMobile(): void {
+    public function testMakePersonContactPointNoMobile(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint');
 
         $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock();
@@ -1213,7 +1242,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testCreateTypo3Website(): void {
+    public function testCreateTypo3Website(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('createTypo3Website');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
@@ -1237,7 +1267,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testCreateTypo3WebsiteWithError(): void {
+    public function testCreateTypo3WebsiteWithError(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('createTypo3Website');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
@@ -1259,7 +1290,8 @@ class OrganizationFactoryTest extends TestCase
         $this->assertNull($result);
     }
 
-    public function testCreateTypo3WebsiteWithInvalidResponse(): void {
+    public function testCreateTypo3WebsiteWithInvalidResponse(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('createTypo3Website');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
@@ -1291,6 +1323,7 @@ class OrganizationFactoryTest extends TestCase
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organization->method('getId')->willReturn(123);
         $organization->method('getParameters')->willReturn($parameters);
 
         $this->organizationRepository
@@ -1312,7 +1345,7 @@ class OrganizationFactoryTest extends TestCase
         );
 
         $organizationFactory->expects(self::once())->method('deleteTypo3Website')->with($organization);
-        $organizationFactory->expects(self::once())->method('deleteDolibarrSociety')->with($organization);
+        $organizationFactory->expects(self::once())->method('switchDolibarrSocietyToProspect')->with($organization);
         $organizationFactory->expects(self::once())->method('deleteLocalDirectories')->with($organization);
         $organizationFactory->expects(self::once())->method('deleteDirectoriesV1')->with($organization);
         $organizationFactory->expects(self::once())->method('deleteDirectories59')->with($organization);
@@ -1358,7 +1391,7 @@ class OrganizationFactoryTest extends TestCase
         $this->entityManager->method('remove')->willThrowException(new \Exception('some error'));
 
         $organizationFactory->expects(self::never())->method('deleteTypo3Website');
-        $organizationFactory->expects(self::never())->method('deleteDolibarrSociety');
+        $organizationFactory->expects(self::never())->method('switchDolibarrSocietyToProspect');
         $organizationFactory->expects(self::never())->method('deleteLocalDirectories');
         $organizationFactory->expects(self::never())->method('deleteDirectoriesV1');
         $organizationFactory->expects(self::never())->method('deleteDirectories59');
@@ -1370,7 +1403,7 @@ class OrganizationFactoryTest extends TestCase
         $this->logger
             ->expects(self::once())
             ->method('critical')
-            ->with($this->callback(function($arg) {
+            ->with($this->callback(function ($arg) {
                 return is_string($arg) && str_contains($arg, 'An error happened, operation cancelled') && str_contains($arg, 'some error');
             }));
 
@@ -1389,6 +1422,7 @@ class OrganizationFactoryTest extends TestCase
 
         $parameters = $this->getMockBuilder(Parameters::class)->getMock();
         $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organization->method('getId')->willReturn(123);
         $organization->method('getParameters')->willReturn($parameters);
 
         $this->organizationRepository
@@ -1410,7 +1444,7 @@ class OrganizationFactoryTest extends TestCase
         );
 
         $organizationFactory->expects(self::once())->method('deleteTypo3Website')->willThrowException(new \Exception('some error'));
-        $organizationFactory->expects(self::once())->method('deleteDolibarrSociety')->willThrowException(new \Exception('some error'));
+        $organizationFactory->expects(self::once())->method('switchDolibarrSocietyToProspect')->willThrowException(new \Exception('some error'));
         $organizationFactory->expects(self::once())->method('deleteLocalDirectories')->willThrowException(new \Exception('some error'));
         $organizationFactory->expects(self::once())->method('deleteDirectoriesV1')->willThrowException(new \Exception('some error'));
         $organizationFactory->expects(self::once())->method('deleteDirectories59')->willThrowException(new \Exception('some error'));
@@ -1424,11 +1458,11 @@ class OrganizationFactoryTest extends TestCase
             ->expects(self::exactly(5))
             ->method('critical')
         ->withConsecutive(
-            ["An error happened while deleting the Typo3 website, please proceed manually."],
-            ["An error happened while deleting the Dolibarr society, please proceed manually."],
-            ["An error happened while deleting the local directories, please proceed manually."],
-            ["An error happened while deleting the V1 directories, please proceed manually."],
-            ["An error happened while deleting the 5.9 directories, please proceed manually."],
+            ['An error happened while deleting the Typo3 website, please proceed manually.'],
+            ['An error happened while updating the Dolibarr society, please proceed manually.'],
+            ['An error happened while deleting the local directories, please proceed manually.'],
+            ['An error happened while deleting the V1 directories, please proceed manually.'],
+            ['An error happened while deleting the 5.9 directories, please proceed manually.'],
         );
 
         $result = $organizationFactory->delete($organizationDeletionRequest);
@@ -1439,7 +1473,8 @@ class OrganizationFactoryTest extends TestCase
         );
     }
 
-    public function testDeleteOrganizationAccesses(): void {
+    public function testDeleteOrganizationAccesses(): void
+    {
         $organizationFactory = $this->getOrganizationFactoryMockFor('deleteOrganizationAccesses');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
@@ -1469,4 +1504,19 @@ class OrganizationFactoryTest extends TestCase
 
         $organizationFactory->deleteOrganizationAccesses($organization);
     }
+
+    public function testSwitchDolibarrSocietyToProspect(): void
+    {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('switchDolibarrSocietyToProspect');
+
+        $organization = $this->getMockBuilder(Organization::class)->getMock();
+        $organization->method('getId')->willReturn(123);
+
+        $this->dolibarrApiService
+            ->expects(self::once())
+            ->method('switchSocietyToProspect')
+            ->with(123);
+
+        $organizationFactory->switchDolibarrSocietyToProspect($organization);
+    }
 }