From 5da0003c4d8d80e4a48c53f2aa6a45202260d4da Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 18 May 2026 07:40:10 +0000 Subject: [PATCH] [#FER-25] Ajout un cron pour la synchro de l'inventaire bovin (!55) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit | Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [x] Pas de régression - [ ] TU/TI/TF rédigée - [x] TU/TI/TF OK - [x] CHANGELOG modifié Reviewed-on: https://gitea.malio.fr/MALIO-DEV/Ferme/pulls/55 Co-authored-by: tristan Co-committed-by: tristan --- CHANGELOG.md | 1 + src/Command/SyncBovineInventoryCommand.php | 49 +++++++ src/Service/BovineInventorySyncer.php | 138 ++++++++++++++++++ .../Bovin/BovineSyncInventoryProcessor.php | 126 +--------------- 4 files changed, 192 insertions(+), 122 deletions(-) create mode 100644 src/Command/SyncBovineInventoryCommand.php create mode 100644 src/Service/BovineInventorySyncer.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3043e6d..27c8444 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ Ajouter dans le fichier .env du frontend * [#FER-18] Mise à jour du tableau d'arrivage * [#FER-26] Passeport du bovin * [#FER-27] Fix export inventaire bovin +* [#FER-25] Ajout un cron pour la synchro de l'inventaire bovin ### Changed diff --git a/src/Command/SyncBovineInventoryCommand.php b/src/Command/SyncBovineInventoryCommand.php new file mode 100644 index 0000000..6775944 --- /dev/null +++ b/src/Command/SyncBovineInventoryCommand.php @@ -0,0 +1,49 @@ +syncer->sync(); + } catch (Throwable $e) { + $io->error(sprintf('Échec de la synchronisation : %s', $e->getMessage())); + + return Command::FAILURE; + } + + $io->success(sprintf( + 'Inventaire synchronisé · Créés : %d · Mis à jour : %d · Sortis : %d · Total EDNOTIF : %d', + $result->created, + $result->updated, + $result->exited, + $result->total, + )); + + return Command::SUCCESS; + } +} diff --git a/src/Service/BovineInventorySyncer.php b/src/Service/BovineInventorySyncer.php new file mode 100644 index 0000000..5bf780c --- /dev/null +++ b/src/Service/BovineInventorySyncer.php @@ -0,0 +1,138 @@ + + */ + private array $bovineTypeCache = []; + + public function __construct( + private readonly BovinApiInterface $bovinApi, + private readonly EntityManagerInterface $em, + ) {} + + public function sync(): BovineSyncInventoryResult + { + $inventory = $this->bovinApi->getInventory(new DateTimeImmutable('today')); + + $result = new BovineSyncInventoryResult(); + $result->total = count($inventory->animals); + + $this->bovineTypeCache = []; + foreach ($this->em->getRepository(BovineType::class)->findAll() as $bovineType) { + if (null !== $bovineType->getCode()) { + $this->bovineTypeCache[$bovineType->getCode()] = $bovineType; + } + } + + $existingByNationalNumber = []; + foreach ($this->em->getRepository(Bovine::class)->findAll() as $bovine) { + $existingByNationalNumber[$bovine->getNationalNumber()] = $bovine; + } + + $seen = []; + foreach ($inventory->animals as $animal) { + $nationalNumber = $animal->identification?->bovin?->nationalNumber; + if (null === $nationalNumber || '' === $nationalNumber) { + continue; + } + $seen[$nationalNumber] = true; + + if (isset($existingByNationalNumber[$nationalNumber])) { + $bovine = $existingByNationalNumber[$nationalNumber]; + ++$result->updated; + } else { + $bovine = new Bovine(); + $bovine->setNationalNumber($nationalNumber); + $this->em->persist($bovine); + ++$result->created; + } + + $this->applyEdnotifData($bovine, $animal); + $bovine->setExitedAt(null); + } + + $now = new DateTimeImmutable(); + foreach ($existingByNationalNumber as $nationalNumber => $bovine) { + if (isset($seen[$nationalNumber])) { + continue; + } + if (null !== $bovine->getExitedAt()) { + continue; + } + $bovine->setExitedAt($now); + ++$result->exited; + } + + $this->em->flush(); + + return $result; + } + + private function applyEdnotifData(Bovine $bovine, AnimalSummaryDto $animal): void + { + $identification = $animal->identification; + if (null !== $identification) { + $bovine->setSex($identification->sex); + $bovine->setBovineType($this->resolveBovineType($identification->breedType)); + $bovine->setWorkNumber($identification->workNumber); + $bovine->setBirthDate($identification->birthDate?->date); + + $bovine->setMotherNationalNumber($identification->motherCarrier?->bovin?->nationalNumber); + $bovine->setMotherBovineType($this->resolveBovineType($identification->motherCarrier?->breedType)); + $bovine->setFatherNationalNumber($identification->fatherIpg?->bovin?->nationalNumber); + $bovine->setFatherBovineType($this->resolveBovineType($identification->fatherIpg?->breedType)); + } + + $latestEntry = null; + $latestExit = null; + foreach ($animal->presencePeriods as $period) { + if (null !== $period->entry?->date && (null === $latestEntry || $period->entry->date > $latestEntry)) { + $latestEntry = $period->entry->date; + } + if (null !== $period->exit?->date && (null === $latestExit || $period->exit->date > $latestExit)) { + $latestExit = $period->exit->date; + } + } + $bovine->setArrivalDate($latestEntry); + $bovine->setExitDate($latestExit); + $bovine->refreshAgeMonths(); + } + + /** + * Trouve un BovineType existant par code, sinon en crée un placeholder + * que l'admin pourra renommer dans /admin/bovin/bovin-list. + */ + private function resolveBovineType(?string $code): ?BovineType + { + if (null === $code || '' === $code) { + return null; + } + + if (isset($this->bovineTypeCache[$code])) { + return $this->bovineTypeCache[$code]; + } + + $bovineType = new BovineType(); + $bovineType->setCode($code); + $bovineType->setLabel(sprintf('À renommer (%s)', $code)); + $this->em->persist($bovineType); + + $this->bovineTypeCache[$code] = $bovineType; + + return $bovineType; + } +} diff --git a/src/State/Bovin/BovineSyncInventoryProcessor.php b/src/State/Bovin/BovineSyncInventoryProcessor.php index 176e6e6..5db0f19 100644 --- a/src/State/Bovin/BovineSyncInventoryProcessor.php +++ b/src/State/Bovin/BovineSyncInventoryProcessor.php @@ -7,26 +7,15 @@ namespace App\State\Bovin; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\ApiResource\BovineSyncInventoryResult; -use App\Entity\Bovine; -use App\Entity\BovineType; -use DateTimeImmutable; -use Doctrine\ORM\EntityManagerInterface; -use Malio\EdnotifBundle\Bovin\Api\BovinApiInterface; -use Malio\EdnotifBundle\Bovin\Dto\AnimalSummaryDto; +use App\Service\BovineInventorySyncer; /** * @implements ProcessorInterface */ -final class BovineSyncInventoryProcessor implements ProcessorInterface +final readonly class BovineSyncInventoryProcessor implements ProcessorInterface { - /** - * @var array - */ - private array $bovineTypeCache = []; - public function __construct( - private BovinApiInterface $bovinApi, - private EntityManagerInterface $em, + private BovineInventorySyncer $syncer, ) {} public function process( @@ -35,113 +24,6 @@ final class BovineSyncInventoryProcessor implements ProcessorInterface array $uriVariables = [], array $context = [], ): BovineSyncInventoryResult { - $inventory = $this->bovinApi->getInventory(new DateTimeImmutable('today')); - - $result = new BovineSyncInventoryResult(); - $result->total = count($inventory->animals); - - $this->bovineTypeCache = []; - foreach ($this->em->getRepository(BovineType::class)->findAll() as $bovineType) { - if (null !== $bovineType->getCode()) { - $this->bovineTypeCache[$bovineType->getCode()] = $bovineType; - } - } - - $existingByNationalNumber = []; - foreach ($this->em->getRepository(Bovine::class)->findAll() as $bovine) { - $existingByNationalNumber[$bovine->getNationalNumber()] = $bovine; - } - - $seen = []; - foreach ($inventory->animals as $animal) { - $nationalNumber = $animal->identification?->bovin?->nationalNumber; - if (null === $nationalNumber || '' === $nationalNumber) { - continue; - } - $seen[$nationalNumber] = true; - - if (isset($existingByNationalNumber[$nationalNumber])) { - $bovine = $existingByNationalNumber[$nationalNumber]; - ++$result->updated; - } else { - $bovine = new Bovine(); - $bovine->setNationalNumber($nationalNumber); - $this->em->persist($bovine); - ++$result->created; - } - - $this->applyEdnotifData($bovine, $animal); - $bovine->setExitedAt(null); - } - - $now = new DateTimeImmutable(); - foreach ($existingByNationalNumber as $nationalNumber => $bovine) { - if (isset($seen[$nationalNumber])) { - continue; - } - if (null !== $bovine->getExitedAt()) { - continue; - } - $bovine->setExitedAt($now); - ++$result->exited; - } - - $this->em->flush(); - - return $result; - } - - private function applyEdnotifData(Bovine $bovine, AnimalSummaryDto $animal): void - { - $identification = $animal->identification; - if (null !== $identification) { - $bovine->setSex($identification->sex); - $bovine->setBovineType($this->resolveBovineType($identification->breedType)); - $bovine->setWorkNumber($identification->workNumber); - $bovine->setBirthDate($identification->birthDate?->date); - - $bovine->setMotherNationalNumber($identification->motherCarrier?->bovin?->nationalNumber); - $bovine->setMotherBovineType($this->resolveBovineType($identification->motherCarrier?->breedType)); - $bovine->setFatherNationalNumber($identification->fatherIpg?->bovin?->nationalNumber); - $bovine->setFatherBovineType($this->resolveBovineType($identification->fatherIpg?->breedType)); - } - - $latestEntry = null; - $latestExit = null; - foreach ($animal->presencePeriods as $period) { - if (null !== $period->entry?->date && (null === $latestEntry || $period->entry->date > $latestEntry)) { - $latestEntry = $period->entry->date; - } - if (null !== $period->exit?->date && (null === $latestExit || $period->exit->date > $latestExit)) { - $latestExit = $period->exit->date; - } - } - $bovine->setArrivalDate($latestEntry); - $bovine->setExitDate($latestExit); - $bovine->refreshAgeMonths(); - } - - /** - * Trouve un BovineType existant par code, sinon en crée un placeholder - * que l'admin pourra renommer dans /admin/bovin/bovin-list. - */ - private function resolveBovineType(?string $code): ?BovineType - { - if (null === $code || '' === $code) { - return null; - } - - if (isset($this->bovineTypeCache[$code])) { - return $this->bovineTypeCache[$code]; - } - - $bovineType = new BovineType(); - $bovineType->setCode($code); - $bovineType->setLabel(sprintf('À renommer (%s)', $code)); - $this->em->persist($bovineType); - - $this->bovineTypeCache[$code] = $bovineType; - - return $bovineType; + return $this->syncer->sync(); } }