From 87f61ae7f1aa74e6d9c031810b7a3068f16ed0f9 Mon Sep 17 00:00:00 2001 From: tristan Date: Tue, 21 Apr 2026 08:51:57 +0200 Subject: [PATCH] feat : expose IpBGetInventaire via BovinApi::getInventory --- config/services.php | 14 ++++++ src/Bovin/Api/BovinApi.php | 75 ++++++++++++++++++++++++----- src/Bovin/Api/BovinApiInterface.php | 8 +++ 3 files changed, 84 insertions(+), 13 deletions(-) diff --git a/config/services.php b/config/services.php index 91137a4..d658294 100644 --- a/config/services.php +++ b/config/services.php @@ -6,8 +6,11 @@ use Malio\EdnotifBundle\Auth\TokenProvider; use Malio\EdnotifBundle\Bovin\Api\BovinApi; use Malio\EdnotifBundle\Bovin\Api\BovinApiInterface; use Malio\EdnotifBundle\Bovin\Mapper\AnimalFileMapper; +use Malio\EdnotifBundle\Bovin\Mapper\AnimalSummaryMapper; +use Malio\EdnotifBundle\Bovin\Mapper\InventoryMapper; use Malio\EdnotifBundle\Shared\Mapper\StandardResponseMapper; use Malio\EdnotifBundle\Shared\Soap\SoapClientFactory; +use Malio\EdnotifBundle\Shared\Soap\ZipMessageDecoder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use function Symfony\Component\DependencyInjection\Loader\Configurator\service; @@ -37,6 +40,15 @@ return static function (ContainerConfigurator $container): void { $services->set(AnimalFileMapper::class)->args([service(StandardResponseMapper::class)]); + $services->set(ZipMessageDecoder::class); + $services->set(AnimalSummaryMapper::class); + $services->set(InventoryMapper::class) + ->args([ + service(AnimalSummaryMapper::class), + service(StandardResponseMapper::class), + ]) + ; + $services->set(TokenProvider::class) ->args([ service('ednotif.soap.guichet'), @@ -55,6 +67,8 @@ return static function (ContainerConfigurator $container): void { service(TokenProvider::class), service('ednotif.soap.business'), service(AnimalFileMapper::class), + service(InventoryMapper::class), + service(ZipMessageDecoder::class), '%ednotif.exploitation_country_code%', '%ednotif.exploitation_number%', ]) diff --git a/src/Bovin/Api/BovinApi.php b/src/Bovin/Api/BovinApi.php index 9b9ff67..15aa530 100644 --- a/src/Bovin/Api/BovinApi.php +++ b/src/Bovin/Api/BovinApi.php @@ -4,10 +4,14 @@ declare(strict_types=1); namespace Malio\EdnotifBundle\Bovin\Api; +use DateTimeInterface; use Malio\EdnotifBundle\Auth\TokenProvider; use Malio\EdnotifBundle\Bovin\Dto\AnimalFileDto; +use Malio\EdnotifBundle\Bovin\Dto\InventoryDto; use Malio\EdnotifBundle\Bovin\Mapper\AnimalFileMapper; +use Malio\EdnotifBundle\Bovin\Mapper\InventoryMapper; use Malio\EdnotifBundle\Shared\Exception\EdnotifException; +use Malio\EdnotifBundle\Shared\Soap\ZipMessageDecoder; use RuntimeException; use SoapClient; use SoapFault; @@ -18,6 +22,8 @@ final readonly class BovinApi implements BovinApiInterface private TokenProvider $tokenProvider, private SoapClient $businessClient, private AnimalFileMapper $bovinDossierMapper, + private InventoryMapper $inventoryMapper, + private ZipMessageDecoder $zipMessageDecoder, private string $exploitationCountryCode, private string $exploitationNumber, ) {} @@ -45,20 +51,63 @@ final readonly class BovinApi implements BovinApiInterface throw new RuntimeException('SOAP Fault on IpBGetDossierAnimal: '.$soapFault->getMessage(), 0, $soapFault); } - // Throw uniquement si Resultat=false (erreur métier) - $standardResponseNode = $soapResponse->ReponseStandard ?? null; - $isOk = is_object($standardResponseNode) && (($standardResponseNode->Resultat ?? false) === true); - - if (!$isOk) { - $anomalyNode = is_object($standardResponseNode) ? ($standardResponseNode->Anomalie ?? null) : null; - - throw new EdnotifException( - codeAnomalie: (string) ($anomalyNode->Code ?? 'UNKNOWN'), - severite: (int) ($anomalyNode->Severite ?? 1), - message: (string) ($anomalyNode->Message ?? 'EDNOTIF error') - ); - } + $this->assertSuccessfulResponse($soapResponse, 'IpBGetDossierAnimal'); return $this->bovinDossierMapper->map($soapResponse); } + + public function getInventory( + DateTimeInterface $startDate, + ?DateTimeInterface $endDate = null, + bool $includeEarTagStock = false, + ): InventoryDto { + $token = $this->tokenProvider->getToken(); + + $payload = [ + 'JetonAuthentification' => $token, + 'Exploitation' => [ + 'CodePays' => $this->exploitationCountryCode, + 'NumeroExploitation' => $this->exploitationNumber, + ], + 'DateDebut' => $startDate->format('Y-m-d'), + 'StockBoucles' => $includeEarTagStock, + ]; + if (null !== $endDate) { + $payload['DateFin'] = $endDate->format('Y-m-d'); + } + + try { + /** @var object $soapResponse */ + $soapResponse = $this->businessClient->__soapCall('IpBGetInventaire', [$payload]); + } catch (SoapFault $soapFault) { + throw new RuntimeException('SOAP Fault on IpBGetInventaire: '.$soapFault->getMessage(), 0, $soapFault); + } + + $this->assertSuccessfulResponse($soapResponse, 'IpBGetInventaire'); + + $messageZip = $soapResponse->ReponseSpecifique->MessageZip ?? null; + $unzippedMessage = is_string($messageZip) && '' !== $messageZip + ? $this->zipMessageDecoder->decode($messageZip) + : null; + + return $this->inventoryMapper->map($soapResponse, $unzippedMessage); + } + + private function assertSuccessfulResponse(object $soapResponse, string $operation): void + { + $standardResponseNode = $soapResponse->ReponseStandard ?? null; + $isOk = is_object($standardResponseNode) && (($standardResponseNode->Resultat ?? false) === true); + + if ($isOk) { + return; + } + + $anomalyNode = is_object($standardResponseNode) ? ($standardResponseNode->Anomalie ?? null) : null; + + throw new EdnotifException( + codeAnomalie: (string) ($anomalyNode->Code ?? 'UNKNOWN'), + severite: (int) ($anomalyNode->Severite ?? 1), + message: (string) ($anomalyNode->Message ?? $operation.' : EDNOTIF error') + ); + } } diff --git a/src/Bovin/Api/BovinApiInterface.php b/src/Bovin/Api/BovinApiInterface.php index f162fda..44f50b5 100644 --- a/src/Bovin/Api/BovinApiInterface.php +++ b/src/Bovin/Api/BovinApiInterface.php @@ -4,9 +4,17 @@ declare(strict_types=1); namespace Malio\EdnotifBundle\Bovin\Api; +use DateTimeInterface; use Malio\EdnotifBundle\Bovin\Dto\AnimalFileDto; +use Malio\EdnotifBundle\Bovin\Dto\InventoryDto; interface BovinApiInterface { public function getAnimalFile(string $nationalNumber, string $countryCode = 'FR'): AnimalFileDto; + + public function getInventory( + DateTimeInterface $startDate, + ?DateTimeInterface $endDate = null, + bool $includeEarTagStock = false, + ): InventoryDto; }