Przeglądaj źródła

implement a first version of the organization creation script

Olivier Massot 1 rok temu
rodzic
commit
4854a994d9

+ 18 - 5
src/ApiResources/Organization/OrganizationCreationRequest.php

@@ -54,7 +54,7 @@ class OrganizationCreationRequest
 
     private int $parentId;
 
-    private int $network;
+    private int $networkId;
 
     private PrincipalTypeEnum $principalType;
 
@@ -62,6 +62,8 @@ class OrganizationCreationRequest
 
     private ?OrganizationMemberCreationRequest $director = null;
 
+    private bool $createWebsite = true;
+
     public function getId(): int
     {
         return $this->id;
@@ -216,14 +218,14 @@ class OrganizationCreationRequest
         return $this;
     }
 
-    public function getNetwork(): int
+    public function getNetworkId(): int
     {
-        return $this->network;
+        return $this->networkId;
     }
 
-    public function setNetwork(int $network): self
+    public function setNetworkId(int $networkId): self
     {
-        $this->network = $network;
+        $this->networkId = $networkId;
         return $this;
     }
 
@@ -259,4 +261,15 @@ class OrganizationCreationRequest
         $this->director = $director;
         return $this;
     }
+
+    public function getCreateWebsite(): bool
+    {
+        return $this->createWebsite;
+    }
+
+    public function setCreateWebsite(bool $createWebsite): self
+    {
+        $this->createWebsite = $createWebsite;
+        return $this;
+    }
 }

+ 29 - 0
src/ApiResources/Organization/OrganizationMemberCreationRequest.php

@@ -2,10 +2,17 @@
 
 namespace App\ApiResources\Organization;
 
+
+use App\Enum\Person\GenderEnum;
+
 class OrganizationMemberCreationRequest
 {
+    private GenderEnum $gender;
+
     private string $name;
 
+    private string $givenName;
+
     private string $streetAddress1;
 
     private string $streetAddress2;
@@ -24,6 +31,17 @@ class OrganizationMemberCreationRequest
 
     private string $email;
 
+    public function getGender(): GenderEnum
+    {
+        return $this->gender;
+    }
+
+    public function setGender(GenderEnum $gender): self
+    {
+        $this->gender = $gender;
+        return $this;
+    }
+
     public function getName(): string
     {
         return $this->name;
@@ -35,6 +53,17 @@ class OrganizationMemberCreationRequest
         return $this;
     }
 
+    public function getGivenName(): string
+    {
+        return $this->givenName;
+    }
+
+    public function setGivenName(string $givenName): self
+    {
+        $this->givenName = $givenName;
+        return $this;
+    }
+
     public function getStreetAddress1(): string
     {
         return $this->streetAddress1;

+ 5 - 0
src/Entity/Organization/Organization.php

@@ -499,6 +499,11 @@ class Organization
 
     public function setParameters(Parameters $parameters): self
     {
+        // set the owning side of the relation if necessary
+        if ($parameters->getOrganization() !== $this) {
+            $parameters->setOrganization($this);
+        }
+
         $this->parameters = $parameters;
 
         return $this;

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

@@ -225,6 +225,11 @@ class Parameters
 
     public function setOrganization(Organization $organization): self
     {
+        // set the owning side of the relation if necessary
+        if ($organization->getParameters() !== $this) {
+            $organization->setParameters($this);
+        }
+
         $this->organization = $organization;
 
         return $this;

+ 5 - 0
src/Entity/Organization/Settings.php

@@ -53,6 +53,11 @@ class Settings
 
     public function setOrganization(Organization $organization): self
     {
+        // set the owning side of the relation if necessary
+        if ($organization->getSettings() !== $this) {
+            $organization->setSettings($this);
+        }
+
         $this->organization = $organization;
 
         return $this;

+ 47 - 0
src/Service/Dolibarr/DolibarrApiService.php

@@ -4,9 +4,13 @@ declare(strict_types=1);
 
 namespace App\Service\Dolibarr;
 
+use App\Entity\Organization\Organization;
 use App\Service\Rest\ApiRequestService;
 use JetBrains\PhpStorm\Pure;
+use Symfony\Component\HttpClient\Exception\ClientException;
+use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Exception\HttpException;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
 
 /**
@@ -178,4 +182,47 @@ class DolibarrApiService extends ApiRequestService
             throw $e;
         }
     }
+
+    /**
+     * @param Organization $organization
+     * @throws TransportExceptionInterface
+     */
+    public function createSociety(Organization $organization): void
+    {
+        try {
+            $body = json_encode([
+                'name' => $organization->getName(),
+                'client' => 2,
+                'code_client' => -1,
+                'import_key' => 'crm',
+                'array_options' => ['options_2iopen_organization_id' => $organization->getId()]
+            ]);
+
+            $options = [
+                'headers' => [
+                    'Accept'=> 'application/json',
+                    'DOLAPIKEY' => "Bocc4zC0J186v8J6QCqu7DnoIw4I7mCJ"
+                ],
+                'body' => $body
+            ];
+
+            /** @var Response $response */
+            $response = $this->client->request('POST',
+                "api/index.php/thirdparties",
+                $options
+            );
+
+            // $content = json_decode($response->getBody()->getContents(), true);
+
+        } catch (ClientException $exception) {
+            switch ($exception->getResponse()->getStatusCode()) {
+                case Response::HTTP_BAD_REQUEST:
+                    //throw new \Exception('errors', self::HTTP_ERROR);
+                    break;
+                case Response::HTTP_NOT_FOUND:
+                    //throw new \Exception('credentials_incorrects', self::HTTP_UNAUTHORIZED);
+                    break;
+            }
+        }
+    }
 }

+ 186 - 1
src/Service/Organization/OrganizationFactory.php

@@ -3,12 +3,197 @@
 namespace App\Service\Organization;
 
 use App\ApiResources\Organization\OrganizationCreationRequest;
+use App\Entity\Access\Access;
+use App\Entity\Core\AddressPostal;
+use App\Entity\Core\ContactPoint;
+use App\Entity\Education\Cycle;
+use App\Entity\Network\NetworkOrganization;
 use App\Entity\Organization\Organization;
+use App\Entity\Organization\OrganizationAddressPostal;
+use App\Entity\Organization\Parameters;
+use App\Entity\Organization\Settings;
+use App\Entity\Person\Person;
+use App\Enum\Core\ContactPointTypeEnum;
+use App\Enum\Education\CycleEnum;
+use App\Enum\Organization\AddressPostalOrganizationTypeEnum;
+use App\Repository\Core\CountryRepository;
+use App\Repository\Network\NetworkRepository;
+use App\Repository\Organization\OrganizationRepository;
+use App\Service\Dolibarr\DolibarrApiService;
+use App\Service\Typo3\BindFileService;
+use App\Service\Typo3\SubdomainService;
+use App\Service\Typo3\Typo3Service;
+use App\Service\Utils\DatesUtils;
+use libphonenumber\PhoneNumber;
+use Symfony\Component\String\ByteString;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
+use Throwable;
 
 class OrganizationFactory
 {
-    public function create(OrganizationCreationRequest $organizationCreationRequest)
+    public function __construct(
+        private readonly SubdomainService $subdomainService,
+        private readonly OrganizationRepository $organizationRepository,
+        private readonly CountryRepository $countryRepository,
+        private readonly NetworkRepository $networkRepository,
+        private readonly Typo3Service $typo3Service,
+        private readonly DolibarrApiService $dolibarrApiService,
+        private readonly BindFileService $bindFileService
+    ) {}
+
+    /**
+     * Créé une nouvelle organisation à partir des données contenues dans une OrganizationCreationRequest
+     *
+     * @param OrganizationCreationRequest $organizationCreationRequest
+     * @return Organization
+     * @throws TransportExceptionInterface
+     * @throws Throwable
+     */
+    public function create(OrganizationCreationRequest $organizationCreationRequest): Organization
     {
+        // Création de l'organisation
+        $organization = new Organization();
+        $organization->setName($organizationCreationRequest->getName());
+        $organization->setLegalStatus($organizationCreationRequest->getLegalStatus());
+
+        // Création des Parameters
+        $parameters = new Parameters();
+        $organization->setParameters($parameters);
+
+        // Création des Settings
+        $settings = new Settings();
+        $settings->setProduct($organizationCreationRequest->getProduct());
+        $organization->setSettings($settings);
+
+        // Création de l'adresse postale
+        $addressPostal = new AddressPostal();
+        $addressPostal->setStreetAddress($organizationCreationRequest->getStreetAddress1());
+        $addressPostal->setStreetAddressSecond($organizationCreationRequest->getStreetAddress2());
+        $addressPostal->setStreetAddressThird($organizationCreationRequest->getStreetAddress3());
+        $addressPostal->setPostalCode($organizationCreationRequest->getPostalCode());
+        $addressPostal->setAddressCity($organizationCreationRequest->getCity());
+
+        $country = $this->countryRepository->find($organizationCreationRequest->getCountryId());
+        $addressPostal->setAddressCountry($country);
+
+        $organizationAddressPostal = new OrganizationAddressPostal();
+        $organizationAddressPostal->setAddressPostal($addressPostal);
+        $organizationAddressPostal->setType(AddressPostalOrganizationTypeEnum::ADDRESS_HEAD_OFFICE);
+        $organization->addOrganizationAddressPostal($organizationAddressPostal);
+
+        // Création du point de contact
+        $phoneNumber = new PhoneNumber();
+        $phoneNumber->unserialize($organizationCreationRequest->getPhoneNumber());
+
+        $contactPoint = new ContactPoint();
+        $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL);
+        $contactPoint->setEmail($organizationCreationRequest->getEmail());
+        $contactPoint->setTelphone($phoneNumber);
+        $organization->addContactPoint($contactPoint);
+
+        // Rattachement au réseau
+        $parent = $this->organizationRepository->find($organizationCreationRequest->getParentId());
+        if (!$parent) {
+            throw new \RuntimeException('No parent organization found for id ' . $organizationCreationRequest->getParentId());
+        }
+
+        $network = $this->networkRepository->find($organizationCreationRequest->getNetworkId());
+        if (!$network) {
+            throw new \RuntimeException('No network found for id ' . $organizationCreationRequest->getNetworkId());
+        }
+
+        $networkOrganization = new NetworkOrganization();
+        $networkOrganization->setParent($parent);
+        $networkOrganization->setNetwork($network);
+        $networkOrganization->setStartDate(DatesUtils::new());
+        $organization->addNetworkOrganization($networkOrganization);
+
+        // Créé l'admin
+        $admin = new Person();
+        $admin->setUsername('admin' . strtolower($organizationCreationRequest->getSubdomain()));
+        $randomString = ByteString::fromRandom(32)->toString();
+        $admin->setPassword($randomString);
+
+        $adminAccess = new Access();
+        $adminAccess->setAdminAccess(true);
+        $adminAccess->setPerson($admin);
+        $adminAccess->setOrganization($organization);
+
+        // Création des cycles
+        $cyclesData = [
+            ['Cycle initiation', 10, CycleEnum::INITIATION_CYCLE],
+            ['Cycle 1', 20, CycleEnum::CYCLE_1],
+            ['Cycle 2', 30, CycleEnum::CYCLE_2],
+            ['Cycle 3', 40, CycleEnum::CYCLE_3],
+            ['Cycle 4', 50, CycleEnum::CYCLE_4],
+            ['Hors cycle', 60, CycleEnum::OUT_CYCLE],
+        ];
+
+        foreach ($cyclesData as $cycleData) {
+            $cycle = new Cycle();
+            $cycle->setLabel($cycleData[0]);
+            $cycle->setOrder($cycleData[1]);
+            $cycle->setCycleEnum($cycleData[2]);
+            $cycle->setIsSystem(false);
+            $cycle->setOrganization($organization);
+            $organization->addCycle($cycle);
+        }
+
+        // Création du sous domaine
+        $this->subdomainService->addNewSubdomain(
+            $organization,
+            $organizationCreationRequest->getSubdomain(),
+            true
+        );
+
+        // Création du président (si renseigné)
+        $presidentCreationRequest = $organizationCreationRequest->getPresident();
+        if ($presidentCreationRequest !== null) {
+            $president = new Person();
+
+            $president->setUsername(
+                strtolower(str_replace(' ', '-', $presidentCreationRequest->getName()))
+            );
+            $president->setPassword(ByteString::fromRandom(32)->toString());
+
+            $president->setGender($presidentCreationRequest->getGender());
+            $president->setName($presidentCreationRequest->getName());
+            $president->setGivenName($presidentCreationRequest->getGivenName());
+
+            $presidentAccess = new Access();
+            $presidentAccess->setPerson($president);
+            $organization->addAccess($presidentAccess);
+        }
+
+        // Création du directeur (si renseigné)
+        if ($organizationCreationRequest->getDirector() !== null) {
+            $director = new Person();
+
+            $director->setUsername(
+                strtolower(str_replace(' ', '-', $presidentCreationRequest->getName()))
+            );
+            $director->setPassword(ByteString::fromRandom(32)->toString());
+
+            $director->setGender($presidentCreationRequest->getGender());
+            $director->setName($presidentCreationRequest->getName());
+            $director->setGivenName($presidentCreationRequest->getGivenName());
+
+            $directorAccess = new Access();
+            $directorAccess->setPerson($director);
+            $organization->addAccess($directorAccess);
+        }
+
+        // Création du site typo3
+        if ($organizationCreationRequest->getCreateWebsite()) {
+            $this->typo3Service->createSite($organization->getId());
+        }
+
+        // Création de la société Dolibarr
+        $this->dolibarrApiService->createSociety($organization);
+
+        // Mise à jour du fichier Bind
+        $this->bindFileService->registerSubdomain($organizationCreationRequest->getSubdomain());
 
+        return $organization;
     }
 }