feat : Reception.validatedAt + statut entrées + mode consultation

- Backend : champ Reception.validatedAt (timestamp) avec PreUpdate + helpers
  isFullyConfirmed/tryValidate ; sync EDNOTIF déclenche tryValidate sur
  les receptions impactées ; expose Supplier.name dans le groupe bovine:read.
- Migration : ajout colonne validated_at sans backfill (les receptions
  remontent en attente jusqu'au prochain sync).
- Front /entry-exit : remplace Historique par 'Entrées validées' (filtre
  exists[validatedAt]=true), ajoute filtres et colonne Statut sur les
  deux tableaux, retire Fournisseur, layout 2x2 (entrées + sorties).
- Front /entry-exit/entry/{id} : mode consultation quand entryCompleted=true
  (formulaire + actions masqués, colonne EDNOTIF par bovin) ; ajoute
  colonnes Vendeur et Cause dans le récap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-30 16:31:16 +02:00
parent 476502c91c
commit 8f88abab46
9 changed files with 400 additions and 240 deletions

View File

@@ -52,7 +52,8 @@ final class BovineSyncInventoryProcessor implements ProcessorInterface
$existingByNationalNumber[$bovine->getNationalNumber()] = $bovine;
}
$seen = [];
$seen = [];
$impactedReceptions = [];
foreach ($inventory->animals as $animal) {
$nationalNumber = $animal->identification?->bovin?->nationalNumber;
if (null === $nationalNumber || '' === $nationalNumber) {
@@ -77,9 +78,17 @@ final class BovineSyncInventoryProcessor implements ProcessorInterface
// voit ce bovin remonter dans l'inventaire.
if (null === $bovine->getEdnotifConfirmedAt()) {
$bovine->setEdnotifConfirmedAt(new DateTimeImmutable());
$reception = $bovine->getReception();
if (null !== $reception) {
$impactedReceptions[$reception->getId()] = $reception;
}
}
}
foreach ($impactedReceptions as $reception) {
$reception->tryValidate();
}
$now = new DateTimeImmutable();
foreach ($existingByNationalNumber as $nationalNumber => $bovine) {
if (isset($seen[$nationalNumber])) {