Explorar el Código

Merge branch 'hotfix/no_ref_bill'

Olivier Massot hace 3 años
padre
commit
1cf99b7e04

+ 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('ApiRequestService->getContent: an error occurred', $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);
+        }
+    }
+}

+ 14 - 19
src/Service/Dolibarr/DolibarrAccountCreator.php

@@ -10,7 +10,7 @@ use App\ApiResources\Dolibarr\DolibarrContractLine;
 
 class DolibarrAccountCreator
 {
-    const PRODUCT_MAPPING = [
+    public const PRODUCT_MAPPING = [
         1 => 'PRODUCT_ARTIST',   # OT Artist
         2 => 'PRODUCT_ARTIST_PREMIUM',   # OT Artist Premium
         3 => 'PRODUCT_SCHOOL',   # OT School Standard
@@ -19,25 +19,26 @@ class DolibarrAccountCreator
     ];
 
     public function __construct(
-        private DolibarrApiService $dolibarrApiService,
+        private DolibarrService $dolibarrService,
     )
     {}
 
     public function getDolibarrAccount(int $id): DolibarrAccount {
 
         // Get dolibarr account (society)
-        $accountData = $this->dolibarrApiService->getSociety($id);
+        $accountData = $this->dolibarrService->getSociety($id);
         $dolibarrAccount = $this->createDolibarrAccount($id, $accountData);
 
         // Get active contract and services
-        $contractData = $this->dolibarrApiService->getActiveContract($dolibarrAccount->getSocId());
+        $contractData = $this->dolibarrService->getActiveContract($dolibarrAccount->getSocId());
+
         if ($contractData !== null) {
             $contract = $this->createDolibarrContract($contractData);
             $dolibarrAccount->setContract($contract);
         }
 
         // get bills
-        $billsData = $this->dolibarrApiService->getBills($dolibarrAccount->getSocId());
+        $billsData = $this->dolibarrService->getBills($dolibarrAccount->getSocId());
         foreach ($billsData as $billData) {
             $bill = $this->createDolibarrBill($billData);
             $dolibarrAccount->addBill($bill);
@@ -52,7 +53,7 @@ class DolibarrAccountCreator
                         ->setSocId((int)$accountData['id'])
                         ->setClientNumber($accountData['code_client']);
 
-        if ($accountData['array_options']['options_2iopen_software_used']) {
+        if (!empty($accountData['array_options']['options_2iopen_software_used'])) {
             $dolibarrAccount->setProduct(
                 self::PRODUCT_MAPPING[(int)$accountData['array_options']['options_2iopen_software_used']]
             );
@@ -62,7 +63,7 @@ class DolibarrAccountCreator
 
     public function createDolibarrContract(array $contractData): DolibarrContract {
         $contract = new DolibarrContract();
-        $contract->setRef($contractData['ref'])
+        $contract->setRef($contractData['ref'] ?? '')
                  ->setSocId((int)$contractData['socid']);
 
         foreach ($contractData['lines'] as $lineData) {
@@ -75,18 +76,12 @@ class DolibarrAccountCreator
 
     public function createDolibarrContractLine(array $lineData): DolibarrContractLine {
         $line = new DolibarrContractLine();
-        $line->setId((int)$lineData['id'])
-            ->setContractId((int)$lineData['fk_contrat'])
-            ->setServiceRef($lineData['product_ref'])
-            ->setServiceLabel($lineData['product_label']);
-
-        if(!empty($lineData['date_start'])){
-            $line->setDateStart(new \DateTime(date('c', $lineData['date_start'])));
-        }
-        if(!empty($lineData['date_end'])){
-            $line->setDateEnd(new \DateTime(date('c', $lineData['date_end'])));
-        }
-        return $line;
+        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 {

+ 84 - 0
src/Service/Dolibarr/DolibarrService.php

@@ -0,0 +1,84 @@
+<?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\HttpClientInterface;
+
+/**
+ * Service d'appel à l'API dolibarr
+ *
+ * @see https://prod-erp.2iopenservice.com/api/index.php/explorer/
+ */
+class DolibarrService extends ApiRequestService
+{
+    #[Pure]
+    function __construct(HttpClientInterface $dolibarr_client)
+    {
+        parent::__construct($dolibarr_client);
+    }
+
+    /**
+     * Get a dolibarr society by its opentalent organization id
+     *
+     * @param int $organizationId
+     * @return array
+     */
+    public function getSociety(int $organizationId): array {
+        // impossible to retrieve a society by its extrafield 2iopen_organization_id (thanks dolibarr), so
+        // we need to store the organization id in two fields: 2iopen_organization_id and ref_int :(
+        return $this->getJsonContent("thirdparties" , ["limit" => "1", "sqlfilters" => "ref_int=" . $organizationId])[0];
+    }
+
+    /**
+     * Get the first active contract for the given dolibarr society
+     *
+     * @param int $socId
+     * @return array|null
+     */
+    public function getActiveContract(int $socId): ?array {
+        try {
+            return $this->getJsonContent(
+                "contracts",
+                ["limit" => "1", "sqlfilters" => "statut=1", "thirdparty_ids=" . $socId => null]
+            )[0];
+        } catch (NotFoundHttpException) {
+            return null;
+        }
+    }
+
+    /**
+     * Get a society bills by their society id
+     *
+     * @param int $socId
+     * @return array
+     */
+    public function getBills(int $socId): array {
+        try {
+            return $this->getJsonContent(
+                "invoices",
+                ["sortfield" => "datef", "sortorder" => "DESC", "limit" => 5, "sqlfilters" => "fk_soc=" . $socId]);
+        } catch (NotFoundHttpException) {
+            return [];
+        }
+    }
+
+    /**
+     *
+     * @param $organization
+     * @return void
+     */
+    public function createSociety($organization): void
+    {
+        $body = sprintf(
+            '{"name":"%s","client":"2","code_client":"-1","ref_int":"%s","import_key":"crm"}',
+            $organization->getName(),
+            $organization->getId()
+        );
+
+        $this->request('POST', "api/index.php/thirdparties", [], ['body' => $body]);
+    }
+}