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