Sfoglia il codice sorgente

dolibarr-mobyt: refactor requesting service and resource creations

Olivier Massot 4 anni fa
parent
commit
3b7c25edaa

+ 4 - 65
src/DataProvider/Dolibarr/DolibarrAccountDataProvider.php

@@ -6,10 +6,7 @@ namespace App\DataProvider\Dolibarr;
 use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
 use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
 use App\ApiResources\Dolibarr\DolibarrAccount;
-use App\ApiResources\Dolibarr\DolibarrBill;
-use App\ApiResources\Dolibarr\DolibarrContract;
-use App\ApiResources\Dolibarr\DolibarrContractLine;
-use App\Service\Dolibarr\DolibarrService;
+use App\Service\Dolibarr\DolibarrAccountCreator;
 
 /**
  * Custom provider pour les DolibarrAccounts récupérés via l'api dolibarr
@@ -17,21 +14,11 @@ use App\Service\Dolibarr\DolibarrService;
  */
 final class DolibarrAccountDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
-    const PRODUCT_MAPPING = [
-        1 => 'PRODUCT_ARTIST',   # OT Artist
-        2 => 'PRODUCT_ARTIST_PREMIUM',   # OT Artist Premium
-        3 => 'PRODUCT_SCHOOL',   # OT School Standard
-        4 => 'PRODUCT_SCHOOL_PREMIUM',   # OT School Premium
-        5 => 'PRODUCT_MANAGER',   # OT Manager
-    ];
-    private DolibarrService $dolibarrService;
 
     public function __construct(
-        DolibarrService $dolibarrService,
+        private DolibarrAccountCreator $dolibarrAccountCreator,
     )
-    {
-        $this->dolibarrService = $dolibarrService;
-    }
+    {}
 
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
     {
@@ -40,54 +27,6 @@ final class DolibarrAccountDataProvider implements ItemDataProviderInterface, Re
 
     public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?DolibarrAccount
     {
-        $dolibarrAccount = new DolibarrAccount();
-
-        $accountData = $this->dolibarrService->getSociety($id);
-
-        $dolibarrAccount->setOrganizationId($id);
-        $dolibarrAccount->setSocId((int)$accountData['id']);
-        $dolibarrAccount->setClientNumber($accountData['code_client']);
-        if ($accountData['array_options']['options_2iopen_software_used']) {
-            $dolibarrAccount->setProduct(
-                self::PRODUCT_MAPPING[(int)$accountData['array_options']['options_2iopen_software_used']]
-            );
-        }
-
-        // Get active contract and services
-        $contractData = $this->dolibarrService->getActiveContract($dolibarrAccount->getSocId());
-        if ($contractData !== null) {
-            $contract = new DolibarrContract();
-            $contract->setRef($contractData['ref']);
-            $contract->setSocId((int)$contractData['socid']);
-
-            foreach ($contractData['lines'] as $lineData) {
-                $line = new DolibarrContractLine();
-                $line->setId((int)$lineData['id']);
-                $line->setContractId((int)$lineData['fk_contrat']);
-                $line->setServiceRef($lineData['product_ref']);
-                $line->setServiceLabel($lineData['product_label']);
-                $line->setDateStart(new \DateTime(date('c', $lineData['date_start'])));
-                $line->setDateEnd(new \DateTime(date('c', $lineData['date_end'])));
-                $contract->addLine($line);
-            }
-
-            $dolibarrAccount->setContract($contract);
-        }
-
-        // get bills
-        $billsData = $this->dolibarrService->getBills($dolibarrAccount->getSocId());
-        foreach ($billsData as $billData) {
-            $bill = new DolibarrBill();
-            $bill->setId((int)$billData['id']);
-            $bill->setRef($billData['ref']);
-            $bill->setSocId($dolibarrAccount->getSocId());
-            $bill->setTaxExcludedAmount((float)$billData['total_ht']);
-            $bill->setTaxIncludedAmount((float)$billData['total_ttc']);
-            $bill->setDate(new \DateTime(date('c', $billData['date'])));
-            $bill->setPaid((bool)$billData['paye']);
-            $dolibarrAccount->addBill($bill);
-        }
-
-        return $dolibarrAccount;
+        return $this->dolibarrAccountCreator->getDolibarrAccount($id);
     }
 }

+ 5 - 29
src/DataProvider/Mobyt/MobytUserStatusDataProvider.php

@@ -6,8 +6,7 @@ namespace App\DataProvider\Mobyt;
 use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
 use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
 use App\ApiResources\Mobyt\MobytUserStatus;
-use App\Repository\Organization\OrganizationRepository;
-use App\Service\Mobyt\MobytService;
+use App\Service\Mobyt\MobytUserStatusCreator;
 
 /**
  * Custom provider pour les MobytUserStatus récupérés via l'api Mobyt
@@ -16,9 +15,9 @@ use App\Service\Mobyt\MobytService;
 final class MobytUserStatusDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
     public function __construct(
-        private MobytService $mobytService,
-        private OrganizationRepository $organizationRepository,
-    ) {}
+        private MobytUserStatusCreator $mobytUserStatusCreator,
+    )
+    {}
 
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
     {
@@ -27,29 +26,6 @@ final class MobytUserStatusDataProvider implements ItemDataProviderInterface, Re
 
     public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?MobytUserStatus
     {
-        $userStatus = new MobytUserStatus();
-        $userStatus->setOrganizationId($id);
-
-        $organization = $this->organizationRepository->find($id);
-        $parameters = $organization->getParameters();
-        $mobytLogin = $parameters->getUsernameSMS();
-        $mobytPassword = $parameters->getPasswordSMS();
-        if (!$mobytLogin) {
-            return $userStatus;
-        }
-
-        $userStatusData = $this->mobytService->getUserStatus($id, $mobytLogin, $mobytPassword);
-        $userStatus->setActive(true);
-        $userStatus->setMoney($userStatusData['money']);
-
-        $topQualitySmsAmount = null;
-        foreach ($userStatusData['sms'] as $_ => $smsTypeData) {
-            // we only retrieve the 'top quality sms', which are identified by the letter L in the mobyt api
-            if ($smsTypeData['type'] === 'L') {
-                $topQualitySmsAmount = $smsTypeData['quantity'];
-            }
-        }
-        $userStatus->setAmount($topQualitySmsAmount);
-        return $userStatus;
+        return $this->mobytUserStatusCreator->getUserStatus($id);
     }
 }

+ 89 - 0
src/Service/ApiRequestService.php

@@ -0,0 +1,89 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service;
+
+use App\Service\Utils\UrlBuilder;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
+use Symfony\Contracts\HttpClient\ResponseInterface;
+
+/**
+ * Base class for services sending requests to an external API
+ */
+class ApiRequestService
+{
+    function __construct(
+        protected HttpClientInterface $client
+    ) {}
+
+    /**
+     * Sends a GET request and returns the response's body decoded as json
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return array
+     */
+    public function getJsonContent(string $path, array $parameters = [], array $options = []): array {
+        return json_decode($this->getContent($path, $parameters, $options), true);
+    }
+
+    /**
+     * Sends a GET request and returns the response's body
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return string
+     */
+    public function getContent(string $path, array $parameters = [], array $options = []): string {
+        try {
+            return $this->get($path, $parameters, $options)->getContent();
+        } catch (ClientExceptionInterface | TransportExceptionInterface | RedirectionExceptionInterface | ServerExceptionInterface $e) {
+            throw new NotFoundHttpException('data not found', $e, 404);
+        }
+    }
+
+    /**
+     * Sends a GET request and returns the response
+     *
+     * @param string $path
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     */
+    protected function get(string $path, array $parameters = [], array $options = []): ResponseInterface {
+        return $this->request('GET', $path, $parameters, $options);
+    }
+
+    /**
+     * Send an HTTP request to the Dolibarr API,
+     * and return the decoded content of the response's body
+     *
+     * @param string $method
+     * @param string $url
+     * @param array $parameters
+     * @param array $options
+     * @return ResponseInterface
+     */
+    protected function request(
+        string $method,
+        string $url,
+        array $parameters = [],
+        array $options = []
+    ): ResponseInterface
+    {
+        $url = ltrim($url, '/');
+        $url = UrlBuilder::concatParameters($url, $parameters);
+        try {
+            return $this->client->request($method, $url, $options);
+        } catch (HttpExceptionInterface | TransportExceptionInterface $e) {
+            throw new NotFoundHttpException('fetch error', $e, 500);
+        }
+    }
+}

+ 95 - 0
src/Service/Dolibarr/DolibarrAccountCreator.php

@@ -0,0 +1,95 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Dolibarr;
+
+use App\ApiResources\Dolibarr\DolibarrAccount;
+use App\ApiResources\Dolibarr\DolibarrBill;
+use App\ApiResources\Dolibarr\DolibarrContract;
+use App\ApiResources\Dolibarr\DolibarrContractLine;
+
+class DolibarrAccountCreator
+{
+    const PRODUCT_MAPPING = [
+        1 => 'PRODUCT_ARTIST',   # OT Artist
+        2 => 'PRODUCT_ARTIST_PREMIUM',   # OT Artist Premium
+        3 => 'PRODUCT_SCHOOL',   # OT School Standard
+        4 => 'PRODUCT_SCHOOL_PREMIUM',   # OT School Premium
+        5 => 'PRODUCT_MANAGER',   # OT Manager
+    ];
+
+    public function __construct(
+        private DolibarrService $dolibarrService,
+    )
+    {}
+
+    public function getDolibarrAccount(int $id): DolibarrAccount {
+
+        // Get dolibarr account (society)
+        $accountData = $this->dolibarrService->getSociety($id);
+        $dolibarrAccount = $this->createDolibarrAccount($id, $accountData);
+
+        // Get active contract and services
+        $contractData = $this->dolibarrService->getActiveContract($dolibarrAccount->getSocId());
+        if ($contractData !== null) {
+            $contract = $this->createDolibarrContract($contractData);
+            $dolibarrAccount->setContract($contract);
+        }
+
+        // get bills
+        $billsData = $this->dolibarrService->getBills($dolibarrAccount->getSocId());
+        foreach ($billsData as $billData) {
+            $bill = $this->createDolibarrBill($billData);
+            $dolibarrAccount->addBill($bill);
+        }
+
+        return $dolibarrAccount;
+    }
+
+    public function createDolibarrAccount(int $organizationId, array $accountData): DolibarrAccount {
+        $dolibarrAccount = new DolibarrAccount();
+        $dolibarrAccount->setOrganizationId($organizationId)
+                        ->setSocId((int)$accountData['id'])
+                        ->setClientNumber($accountData['code_client']);
+
+        if ($accountData['array_options']['options_2iopen_software_used']) {
+            $dolibarrAccount->setProduct(
+                self::PRODUCT_MAPPING[(int)$accountData['array_options']['options_2iopen_software_used']]
+            );
+        }
+        return $dolibarrAccount;
+    }
+
+    public function createDolibarrContract(array $contractData): DolibarrContract {
+        $contract = new DolibarrContract();
+        $contract->setRef($contractData['ref'])
+                 ->setSocId((int)$contractData['socid']);
+
+        foreach ($contractData['lines'] as $lineData) {
+            $line = $this->createDolibarrContractLine($lineData);
+            $contract->addLine($line);
+        }
+
+        return $contract;
+    }
+
+    public function createDolibarrContractLine(array $lineData): DolibarrContractLine {
+        $line = new DolibarrContractLine();
+        return $line->setId((int)$lineData['id'])
+                    ->setContractId((int)$lineData['fk_contrat'])
+                    ->setServiceRef($lineData['product_ref'])
+                    ->setServiceLabel($lineData['product_label'])
+                    ->setDateStart(new \DateTime(date('c', $lineData['date_start'])))
+                    ->setDateEnd(new \DateTime(date('c', $lineData['date_end'])));
+    }
+
+    public function createDolibarrBill(array $billData): DolibarrBill {
+        $bill = new DolibarrBill();
+        return $bill->setId((int)$billData['id'])
+                    ->setRef($billData['ref'])
+                    ->setTaxExcludedAmount((float)$billData['total_ht'])
+                    ->setTaxIncludedAmount((float)$billData['total_ttc'])
+                    ->setDate(new \DateTime(date('c', $billData['date'])))
+                    ->setPaid((bool)$billData['paye']);
+    }
+}

+ 17 - 33
src/Service/Dolibarr/DolibarrService.php

@@ -1,10 +1,11 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Service\Dolibarr;
 
+use App\Service\ApiRequestService;
+use JetBrains\PhpStorm\Pure;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
-use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
 
 /**
@@ -12,13 +13,12 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
  *
  * @see https://prod-erp.2iopenservice.com/api/index.php/explorer/
  */
-class DolibarrService
+class DolibarrService extends ApiRequestService
 {
-    private HttpClientInterface $client;
-
+    #[Pure]
     function __construct(HttpClientInterface $dolibarr_client)
     {
-        $this->client = $dolibarr_client;
+        parent::__construct($dolibarr_client);
     }
 
     /**
@@ -28,7 +28,7 @@ class DolibarrService
      * @return array
      */
     public function getSociety(int $organizationId): array {
-        return $this->request("thirdparties?sqlfilters=" . urlencode("ref_int=" . $organizationId))[0];
+        return $this->getJsonContent("thirdparties" , [ "sqlfilters" => "ref_int=" . $organizationId])[0];
     }
 
     /**
@@ -39,7 +39,10 @@ class DolibarrService
      */
     public function getActiveContract(int $socId): ?array {
         try {
-            return $this->request("contracts?limit=1&sqlfilters=statut%3D1&thirdparty_ids%3D" . $socId)[0];
+            return $this->getJsonContent(
+                "contracts",
+                ["limit" => "1", "sqlfilters" => "statut=1", "thirdparty_ids=" . $socId => null]
+            )[0];
         } catch (NotFoundHttpException) {
             return null;
         }
@@ -53,7 +56,9 @@ class DolibarrService
      */
     public function getBills(int $socId): array {
         try {
-            return $this->request("invoices?sortfield=datef&sortorder=DESC&limit=5&sqlfilters=fk_soc%3D" . $socId);
+            return $this->getJsonContent(
+                "invoices",
+                ["sortfield" => "datef", "sortorder" => "DESC", "limit" => 5, "sqlfilters" => "fk_soc=" . $socId]);
         } catch (NotFoundHttpException) {
             return [];
         }
@@ -62,9 +67,9 @@ class DolibarrService
     /**
      *
      * @param $organization
-     * @return array
+     * @return void
      */
-    public function createSociety($organization): array
+    public function createSociety($organization): void
     {
         $body = sprintf(
             '{"name":"%s","client":"2","code_client":"-1","ref_int":"%s","import_key":"crm"}',
@@ -72,27 +77,6 @@ class DolibarrService
             $organization->getId()
         );
 
-        return $this->request("api/index.php/thirdparties",'POST', ['body' => $body]);
-    }
-
-    /**
-     * Send an HTTP request to the Dolibarr API,
-     * and return the decoded content of the response's body
-     *
-     * @param string $path
-     * @param string $method
-     * @param array $options
-     * @return array
-     * @throws NotFoundHttpException
-     */
-    private function request(string $path, string $method = 'GET', array $options = []): array
-    {
-        try {
-            $uri = ltrim($path, '/');
-            $response = $this->client->request($method, $uri, $options);
-            return json_decode($response->getContent(), true);
-        } catch (HttpExceptionInterface | TransportExceptionInterface $e) {
-            throw new NotFoundHttpException('data_not_found', $e, 404);
-        }
+        $this->request('POST', "api/index.php/thirdparties", [], ['body' => $body]);
     }
 }

+ 25 - 35
src/Service/Mobyt/MobytService.php

@@ -1,67 +1,57 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Service\Mobyt;
 
-use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
-use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
+use App\Service\ApiRequestService;
+use JetBrains\PhpStorm\Pure;
 use Symfony\Contracts\HttpClient\HttpClientInterface;
 
 /**
  * Service d'appel à l'API Mobyt
  */
-class MobytService
+class MobytService extends ApiRequestService
 {
-    private HttpClientInterface $client;
     private string $userId;
     private string $sessionKey;
 
+    #[Pure]
     function __construct(
         HttpClientInterface $mobyt_client
     )
     {
-        $this->client = $mobyt_client;
+        parent::__construct($mobyt_client);
     }
 
-    private function connect(string $login, string $password){
-        $response = $this->client->request('GET', sprintf('login?username=%s&password=%s', $login, $password));
-        list($this->userId, $this->sessionKey) = explode(';', $response->getContent());
-        return true;
+    /**
+     * Send a connexion request to mobyt and get the user id and session key from the response
+     *
+     * @param string $login
+     * @param string $password
+     * @return void
+     */
+    private function connect(string $login, string $password): void
+    {
+        $responseContent = $this->getContent('login', ['username' => $login, 'password' => $password]);
+        list($this->userId, $this->sessionKey) = explode(';', $responseContent);
     }
 
     /**
      * Get a dolibarr society by its opentalent organization id
      *
      * @param int $organizationId
+     * @param string $login
+     * @param string $password
      * @return array
      */
     public function getUserStatus(int $organizationId, string $login, string $password): array {
         $this->connect($login, $password);
-        return $this->request(
-            'status?getMoney=true&typeAliases=true',
-            'GET',
-            ['headers' => [ 'user_key' => $this->userId, 'Session_key' => $this->sessionKey ]]
+        return $this->getJsonContent(
+            'status',
+            ['getMoney' => 'true', 'typeAliases' => 'true'],
+            [
+                'headers' => [ 'user_key' => $this->userId, 'Session_key' => $this->sessionKey ]
+            ]
         );
     }
-
-    /**
-     * Send an HTTP request to the Dolibarr API,
-     * and return the decoded content of the response's body
-     *
-     * @param string $path
-     * @param string $method
-     * @param array $options
-     * @return array
-     * @throws NotFoundHttpException
-     */
-    private function request(string $path, string $method = 'GET', array $options = []): array
-    {
-        try {
-            $uri = ltrim($path, '/');
-            $response = $this->client->request($method, $uri, $options);
-            return json_decode($response->getContent(), true);
-        } catch (HttpExceptionInterface | TransportExceptionInterface $e) {
-            throw new NotFoundHttpException('data_not_found', $e, 404);
-        }
-    }
 }

+ 41 - 0
src/Service/Mobyt/MobytUserStatusCreator.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Service\Mobyt;
+
+use App\ApiResources\Mobyt\MobytUserStatus;
+use App\Repository\Organization\OrganizationRepository;
+
+class MobytUserStatusCreator
+{
+    public function __construct(
+        private MobytService $mobytService,
+        private OrganizationRepository $organizationRepository,
+    ) {}
+
+    public function getUserStatus(int $organizationId): MobytUserStatus {
+        $userStatus = new MobytUserStatus();
+        $userStatus->setOrganizationId($organizationId);
+
+        $organization = $this->organizationRepository->find($organizationId);
+        $parameters = $organization->getParameters();
+        $mobytLogin = $parameters->getUsernameSMS();
+        $mobytPassword = $parameters->getPasswordSMS();
+        if (!$mobytLogin) {
+            return $userStatus;
+        }
+
+        $userStatusData = $this->mobytService->getUserStatus($organizationId, $mobytLogin, $mobytPassword);
+        $userStatus->setActive(true);
+        $userStatus->setMoney($userStatusData['money']);
+
+        $topQualitySmsAmount = null;
+        foreach ($userStatusData['sms'] as $_ => $smsTypeData) {
+            // we only retrieve the 'top quality sms', which are identified by the letter L in the mobyt api
+            if ($smsTypeData['type'] === 'L') {
+                $topQualitySmsAmount = $smsTypeData['quantity'];
+            }
+        }
+        $userStatus->setAmount($topQualitySmsAmount);
+        return $userStatus;
+    }
+}