diff --git a/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue b/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue
index 98fc7ec..d42b2bd 100644
--- a/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue
+++ b/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue
@@ -161,14 +161,14 @@
chaque
+ * 422 est mappee inline sous le champ via useFormErrors (ERP-101).
+ */
+ #[Assert\Callback]
+ public function validateManualEntryDigits(ExecutionContextInterface $context): void
+ {
+ $this->assertManualDigitCap($context, $this->emptyMode, $this->emptyWeight, 'emptyWeight', 'Le poids saisi ne peut pas dépasser 5 chiffres (99999 kg maximum).');
+ $this->assertManualDigitCap($context, $this->emptyMode, $this->emptyDsd, 'emptyDsd', 'Le DSD saisi ne peut pas dépasser 5 chiffres (99999 maximum).');
+ $this->assertManualDigitCap($context, $this->fullMode, $this->fullWeight, 'fullWeight', 'Le poids saisi ne peut pas dépasser 5 chiffres (99999 kg maximum).');
+ $this->assertManualDigitCap($context, $this->fullMode, $this->fullDsd, 'fullDsd', 'Le DSD saisi ne peut pas dépasser 5 chiffres (99999 maximum).');
+ }
+
/**
* Date du ticket affichee en LISTE (§ 4.0) : date de la pesee a plein si
* disponible, sinon date de la pesee a vide. Getter calcule (jamais
@@ -646,4 +668,14 @@ class WeighingTicket implements TimestampableInterface, BlamableInterface
return $this;
}
+
+ private function assertManualDigitCap(ExecutionContextInterface $context, ?string $mode, ?int $value, string $path, string $message): void
+ {
+ if ('MANUAL' === $mode && null !== $value && $value > self::MANUAL_VALUE_MAX) {
+ $context->buildViolation($message)
+ ->atPath($path)
+ ->addViolation()
+ ;
+ }
+ }
}
diff --git a/src/Module/Logistique/Infrastructure/ApiPlatform/Resource/WeighbridgeReadingResource.php b/src/Module/Logistique/Infrastructure/ApiPlatform/Resource/WeighbridgeReadingResource.php
index 8840f0b..f7f2bcf 100644
--- a/src/Module/Logistique/Infrastructure/ApiPlatform/Resource/WeighbridgeReadingResource.php
+++ b/src/Module/Logistique/Infrastructure/ApiPlatform/Resource/WeighbridgeReadingResource.php
@@ -6,6 +6,7 @@ namespace App\Module\Logistique\Infrastructure\ApiPlatform\Resource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Post;
+use App\Module\Logistique\Domain\Entity\WeighingTicket;
use App\Module\Logistique\Infrastructure\ApiPlatform\State\Processor\WeighbridgeReadingProcessor;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Validator\Constraints as Assert;
@@ -59,6 +60,7 @@ final class WeighbridgeReadingResource
* fournit le poids). En sortie : poids effectif de la pesee.
*/
#[Assert\Positive(message: 'Le poids doit être un entier positif (kg).')]
+ #[Assert\LessThanOrEqual(value: WeighingTicket::MANUAL_VALUE_MAX, message: 'Le poids saisi ne peut pas dépasser 5 chiffres (99999 kg maximum).')]
#[Groups(['weighbridge_reading:write', 'weighbridge_reading:read'])]
public ?int $weight = null;
@@ -68,6 +70,7 @@ final class WeighbridgeReadingResource
* (l'obligation en MANUAL est portee par le Callback ci-dessous).
*/
#[Assert\Positive(message: 'Le DSD doit être un entier positif.')]
+ #[Assert\LessThanOrEqual(value: WeighingTicket::MANUAL_VALUE_MAX, message: 'Le DSD saisi ne peut pas dépasser 5 chiffres (99999 maximum).')]
#[Groups(['weighbridge_reading:write', 'weighbridge_reading:read'])]
public ?int $dsd = null;
diff --git a/tests/Module/Logistique/Api/WeighbridgeReadingApiTest.php b/tests/Module/Logistique/Api/WeighbridgeReadingApiTest.php
index b6b34d7..dd871a4 100644
--- a/tests/Module/Logistique/Api/WeighbridgeReadingApiTest.php
+++ b/tests/Module/Logistique/Api/WeighbridgeReadingApiTest.php
@@ -133,6 +133,49 @@ final class WeighbridgeReadingApiTest extends AbstractApiTestCase
self::assertViolationOnPath($response, 'dsd');
}
+ public function testManualWeighingRejectsWeightOverFiveDigits(): void
+ {
+ $client = $this->manageClientWithCurrentSite();
+
+ $response = $client->request('POST', '/api/weighbridge_readings', [
+ 'headers' => ['Content-Type' => 'application/ld+json'],
+ // 100000 = 6 chiffres → au-dela du plafond 5 chiffres (99999).
+ 'json' => ['mode' => 'MANUAL', 'weight' => 100000, 'dsd' => 16619],
+ ]);
+
+ self::assertResponseStatusCodeSame(422);
+ self::assertViolationOnPath($response, 'weight');
+ }
+
+ public function testManualWeighingRejectsDsdOverFiveDigits(): void
+ {
+ $client = $this->manageClientWithCurrentSite();
+
+ $response = $client->request('POST', '/api/weighbridge_readings', [
+ 'headers' => ['Content-Type' => 'application/ld+json'],
+ 'json' => ['mode' => 'MANUAL', 'weight' => 23187, 'dsd' => 100000],
+ ]);
+
+ self::assertResponseStatusCodeSame(422);
+ self::assertViolationOnPath($response, 'dsd');
+ }
+
+ public function testManualWeighingAcceptsFiveDigitBoundary(): void
+ {
+ $client = $this->manageClientWithCurrentSite();
+
+ $response = $client->request('POST', '/api/weighbridge_readings', [
+ 'headers' => ['Content-Type' => 'application/ld+json'],
+ // 99999 = exactement 5 chiffres → derniere valeur acceptee.
+ 'json' => ['mode' => 'MANUAL', 'weight' => 99999, 'dsd' => 99999],
+ ]);
+
+ self::assertResponseStatusCodeSame(200);
+ $data = $response->toArray();
+ self::assertSame(99999, $data['weight']);
+ self::assertSame(99999, $data['dsd']);
+ }
+
/**
* Garde-fou ERP-101 (miroir AbstractWeighingTicketApiTestCase) : une 422 doit
* porter une violation sur le `propertyPath` attendu, consommable inline par