feat : DTOs et mapper pour IpBGetInventaire
This commit is contained in:
12
src/Bovin/Dto/EarTagSeriesDto.php
Normal file
12
src/Bovin/Dto/EarTagSeriesDto.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Malio\EdnotifBundle\Bovin\Dto;
|
||||
|
||||
final readonly class EarTagSeriesDto
|
||||
{
|
||||
public function __construct(
|
||||
public object $rawNode,
|
||||
) {}
|
||||
}
|
||||
26
src/Bovin/Dto/InventoryDto.php
Normal file
26
src/Bovin/Dto/InventoryDto.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Malio\EdnotifBundle\Bovin\Dto;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Malio\EdnotifBundle\Shared\Dto\StandardResponseDto;
|
||||
|
||||
final readonly class InventoryDto
|
||||
{
|
||||
/**
|
||||
* @param list<AnimalSummaryDto> $animals
|
||||
* @param list<EarTagSeriesDto> $earTagSeries
|
||||
*/
|
||||
public function __construct(
|
||||
public StandardResponseDto $standardResponse,
|
||||
public int $nbBovins,
|
||||
public ?DateTimeImmutable $startDate,
|
||||
public ?DateTimeImmutable $endDate,
|
||||
public bool $includesEarTagStock,
|
||||
public array $animals,
|
||||
public array $earTagSeries,
|
||||
public ?object $rawSoapResponse,
|
||||
) {}
|
||||
}
|
||||
85
src/Bovin/Mapper/InventoryMapper.php
Normal file
85
src/Bovin/Mapper/InventoryMapper.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Malio\EdnotifBundle\Bovin\Mapper;
|
||||
|
||||
use Malio\EdnotifBundle\Bovin\Dto\EarTagSeriesDto;
|
||||
use Malio\EdnotifBundle\Bovin\Dto\InventoryDto;
|
||||
use Malio\EdnotifBundle\Shared\Dto\AnomalyDto;
|
||||
use Malio\EdnotifBundle\Shared\Dto\StandardResponseDto;
|
||||
|
||||
final class InventoryMapper
|
||||
{
|
||||
use BovinNodeMappingTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly AnimalSummaryMapper $animalSummaryMapper,
|
||||
) {}
|
||||
|
||||
public function map(object $soapResponse, ?object $unzippedMessage): InventoryDto
|
||||
{
|
||||
$standardResponse = $this->mapStandardResponse($soapResponse->ReponseStandard ?? null);
|
||||
|
||||
$nbBovins = $this->toNullableInt($soapResponse->ReponseSpecifique->NbBovins ?? null) ?? 0;
|
||||
|
||||
$startDate = null;
|
||||
$endDate = null;
|
||||
$includesEarTagStock = false;
|
||||
$animals = [];
|
||||
$earTagSeries = [];
|
||||
|
||||
if (is_object($unzippedMessage)) {
|
||||
$infoNode = $unzippedMessage->InformationsMessage ?? null;
|
||||
if (is_object($infoNode)) {
|
||||
$startDate = $this->toNullableDate($infoNode->DateDebut ?? null);
|
||||
$endDate = $this->toNullableDate($infoNode->DateFin ?? null);
|
||||
$includesEarTagStock = (bool) $this->toNullableBool($infoNode->StockBoucles ?? null);
|
||||
}
|
||||
|
||||
$bovinsNode = $unzippedMessage->Bovins->Bovin ?? null;
|
||||
foreach ($this->normalizeToList($bovinsNode) as $bovinNode) {
|
||||
if (!is_object($bovinNode)) {
|
||||
continue;
|
||||
}
|
||||
$animals[] = $this->animalSummaryMapper->map($bovinNode);
|
||||
}
|
||||
|
||||
$seriesNode = $unzippedMessage->Boucles->SerieBoucles ?? null;
|
||||
foreach ($this->normalizeToList($seriesNode) as $serieNode) {
|
||||
if (!is_object($serieNode)) {
|
||||
continue;
|
||||
}
|
||||
$earTagSeries[] = new EarTagSeriesDto(rawNode: $serieNode);
|
||||
}
|
||||
}
|
||||
|
||||
return new InventoryDto(
|
||||
standardResponse: $standardResponse,
|
||||
nbBovins: $nbBovins,
|
||||
startDate: $startDate,
|
||||
endDate: $endDate,
|
||||
includesEarTagStock: $includesEarTagStock,
|
||||
animals: $animals,
|
||||
earTagSeries: $earTagSeries,
|
||||
rawSoapResponse: $soapResponse,
|
||||
);
|
||||
}
|
||||
|
||||
private function mapStandardResponse(mixed $standardResponseNode): StandardResponseDto
|
||||
{
|
||||
$result = (bool) ($standardResponseNode->Resultat ?? false);
|
||||
$anomalyNode = $standardResponseNode->Anomalie ?? null;
|
||||
$anomaly = null;
|
||||
|
||||
if (is_object($anomalyNode)) {
|
||||
$anomaly = new AnomalyDto(
|
||||
code: $this->toNullableString($anomalyNode->Code ?? null),
|
||||
severity: $this->toNullableInt($anomalyNode->Severite ?? null),
|
||||
message: $this->toNullableString($anomalyNode->Message ?? null),
|
||||
);
|
||||
}
|
||||
|
||||
return new StandardResponseDto($result, $anomaly);
|
||||
}
|
||||
}
|
||||
99
tests/Unit/Bovin/Mapper/InventoryMapperTest.php
Normal file
99
tests/Unit/Bovin/Mapper/InventoryMapperTest.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Malio\EdnotifBundle\Tests\Unit\Bovin\Mapper;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Malio\EdnotifBundle\Bovin\Dto\InventoryDto;
|
||||
use Malio\EdnotifBundle\Bovin\Mapper\AnimalSummaryMapper;
|
||||
use Malio\EdnotifBundle\Bovin\Mapper\InventoryMapper;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
#[CoversClass(InventoryMapper::class)]
|
||||
final class InventoryMapperTest extends TestCase
|
||||
{
|
||||
public function testMapFullInventory(): void
|
||||
{
|
||||
$mapper = new InventoryMapper(new AnimalSummaryMapper());
|
||||
|
||||
$inventory = $mapper->map($this->makeSoapResponse(), $this->makeUnzippedMessage());
|
||||
|
||||
self::assertInstanceOf(InventoryDto::class, $inventory);
|
||||
self::assertTrue($inventory->standardResponse->result);
|
||||
self::assertSame(2, $inventory->nbBovins);
|
||||
self::assertEquals(new DateTimeImmutable('2026-01-01'), $inventory->startDate);
|
||||
self::assertEquals(new DateTimeImmutable('2026-01-31'), $inventory->endDate);
|
||||
self::assertTrue($inventory->includesEarTagStock);
|
||||
self::assertCount(2, $inventory->animals);
|
||||
self::assertCount(1, $inventory->earTagSeries);
|
||||
self::assertSame('FR123', $inventory->animals[0]->identification?->bovin?->nationalNumber);
|
||||
}
|
||||
|
||||
public function testMapInventoryWithoutMessageZipReturnsEmptyLists(): void
|
||||
{
|
||||
$mapper = new InventoryMapper(new AnimalSummaryMapper());
|
||||
|
||||
$soapResponse = new stdClass();
|
||||
$soapResponse->ReponseStandard = new stdClass();
|
||||
$soapResponse->ReponseStandard->Resultat = true;
|
||||
$soapResponse->ReponseSpecifique = new stdClass();
|
||||
$soapResponse->ReponseSpecifique->NbBovins = 0;
|
||||
|
||||
$inventory = $mapper->map($soapResponse, null);
|
||||
|
||||
self::assertSame(0, $inventory->nbBovins);
|
||||
self::assertSame([], $inventory->animals);
|
||||
self::assertSame([], $inventory->earTagSeries);
|
||||
self::assertNull($inventory->startDate);
|
||||
}
|
||||
|
||||
private function makeSoapResponse(): object
|
||||
{
|
||||
$response = new stdClass();
|
||||
$response->ReponseStandard = new stdClass();
|
||||
$response->ReponseStandard->Resultat = true;
|
||||
$response->ReponseSpecifique = new stdClass();
|
||||
$response->ReponseSpecifique->NbBovins = 2;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function makeUnzippedMessage(): object
|
||||
{
|
||||
$message = new stdClass();
|
||||
$message->InformationsMessage = new stdClass();
|
||||
$message->InformationsMessage->DateDebut = '2026-01-01';
|
||||
$message->InformationsMessage->DateFin = '2026-01-31';
|
||||
$message->InformationsMessage->StockBoucles = '1';
|
||||
$message->Bovins = new stdClass();
|
||||
$message->Bovins->Bovin = [
|
||||
$this->makeAnimalNode('FR123'),
|
||||
$this->makeAnimalNode('FR456'),
|
||||
];
|
||||
$message->Boucles = new stdClass();
|
||||
$message->Boucles->SerieBoucles = new stdClass();
|
||||
$message->Boucles->SerieBoucles->NumeroSerieDebut = 'A0001';
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
private function makeAnimalNode(string $nationalNumber): object
|
||||
{
|
||||
$node = new stdClass();
|
||||
$node->IdentiteBovin = new stdClass();
|
||||
$node->IdentiteBovin->Bovin = new stdClass();
|
||||
$node->IdentiteBovin->Bovin->NumeroNational = $nationalNumber;
|
||||
$node->PeriodesPresences = new stdClass();
|
||||
$node->PeriodesPresences->PeriodePresence = new stdClass();
|
||||
$node->PeriodesPresences->PeriodePresence->Entree = new stdClass();
|
||||
$node->PeriodesPresences->PeriodePresence->Entree->DateEntree = '2025-05-01';
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user