From df3f86d33f40e70ee0fb97c14a040039b18272df Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 18 May 2026 07:12:36 +0000 Subject: [PATCH] [#FER-27] Fix export inventaire bovin (!54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Une ligne avec données absentes ou hors plage (date < 1900, n° national vide, dates incohérentes) ne fait plus tomber l'export entier en 500. Try/catch par ligne avec log warning, helper safePhpToExcel pour les dates Excel, garde birth <= arrival pour l'âge à l'entrée. | Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [ ] Pas de régression - [ ] TU/TI/TF rédigée - [ ] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: https://gitea.malio.fr/MALIO-DEV/Ferme/pulls/54 Co-authored-by: tristan Co-committed-by: tristan --- CHANGELOG.md | 1 + .../Bovin/BovineInventoryExportProvider.php | 53 +++++++++++++++---- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 095a2f3..3043e6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ Ajouter dans le fichier .env du frontend * [#FER-17] Ecran d'ajout de bovin * [#FER-18] Mise à jour du tableau d'arrivage * [#FER-26] Passeport du bovin +* [#FER-27] Fix export inventaire bovin ### Changed diff --git a/src/State/Bovin/BovineInventoryExportProvider.php b/src/State/Bovin/BovineInventoryExportProvider.php index e1d2f31..0c0e282 100644 --- a/src/State/Bovin/BovineInventoryExportProvider.php +++ b/src/State/Bovin/BovineInventoryExportProvider.php @@ -18,13 +18,15 @@ use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Style\Fill; use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; +use Throwable; /** * @implements ProviderInterface */ -final class BovineInventoryExportProvider implements ProviderInterface +final readonly class BovineInventoryExportProvider implements ProviderInterface { private const FARM_NAME = 'FERME SCEA LES NAUDS'; @@ -70,6 +72,7 @@ final class BovineInventoryExportProvider implements ProviderInterface public function __construct( private BovineRepository $bovineRepository, private RequestStack $requestStack, + private LoggerInterface $logger, ) {} public function provide(Operation $operation, array $uriVariables = [], array $context = []): Response @@ -253,7 +256,16 @@ final class BovineInventoryExportProvider implements ProviderInterface // Lignes de données $rowNumber = 5; foreach ($bovines as $bovine) { - $this->writeBovineRow($sheet, $rowNumber, $bovine); + try { + $this->writeBovineRow($sheet, $rowNumber, $bovine); + } catch (Throwable $e) { + $this->logger->warning('Export inventaire bovin : ligne ignorée suite à une erreur.', [ + 'bovineId' => $bovine->getId(), + 'nationalNumber' => $bovine->getNationalNumber(), + 'row' => $rowNumber, + 'exception' => $e, + ]); + } ++$rowNumber; } @@ -284,22 +296,25 @@ final class BovineInventoryExportProvider implements ProviderInterface ? (int) $bovine->getWorkNumber() : ($bovine->getWorkNumber() ?? '')); $sheet->setCellValue('C'.$row, $isCharo ? 'X' : ''); - $sheet->setCellValue('D'.$row, 'FR '.$bovine->getNationalNumber()); + $national = $bovine->getNationalNumber(); + $sheet->setCellValue('D'.$row, '' === $national ? '' : 'FR '.$national); $sheet->setCellValue('E'.$row, 'B1' === $code ? 'X' : ''); $sheet->setCellValue('F'.$row, 'B2' === $code ? 'X' : ''); $sheet->setCellValue('G'.$row, 'B3' === $code ? 'X' : ''); $sheet->setCellValue('H'.$row, $bovine->getBuildingCase()?->getCaseNumber() ?? ''); $sheet->setCellValue('I'.$row, $bovine->getSupplier()?->getName() ?? ''); - $birth = $bovine->getBirthDate(); - $arrival = $bovine->getArrivalDate(); - if (null !== $birth) { - $sheet->setCellValue('J'.$row, ExcelDate::PHPToExcel($birth)); + $birth = $bovine->getBirthDate(); + $arrival = $bovine->getArrivalDate(); + $birthExcel = $this->safePhpToExcel($birth); + $arrivalExcel = $this->safePhpToExcel($arrival); + if (null !== $birthExcel) { + $sheet->setCellValue('J'.$row, $birthExcel); } - if (null !== $arrival) { - $sheet->setCellValue('K'.$row, ExcelDate::PHPToExcel($arrival)); + if (null !== $arrivalExcel) { + $sheet->setCellValue('K'.$row, $arrivalExcel); } - if (null !== $birth && null !== $arrival) { + if (null !== $birth && null !== $arrival && $birth <= $arrival) { $diff = $birth->diff($arrival); $sheet->setCellValue('L'.$row, ($diff->y * 12) + $diff->m); } @@ -343,6 +358,24 @@ final class BovineInventoryExportProvider implements ProviderInterface } } + /** + * Convertit une date PHP en numéro de série Excel, ou null si la date est absente / hors plage Excel (< 1900). + */ + private function safePhpToExcel(?DateTimeImmutable $date): ?float + { + if (null === $date) { + return null; + } + + try { + $value = ExcelDate::PHPToExcel($date); + } catch (Throwable) { + return null; + } + + return is_float($value) ? $value : null; + } + /** * Sous-titre dynamique selon les tranches d'âge cochées. *