diff --git a/src/Module/Transport/Domain/Entity/Carrier.php b/src/Module/Transport/Domain/Entity/Carrier.php index de39955..dc35ee7 100644 --- a/src/Module/Transport/Domain/Entity/Carrier.php +++ b/src/Module/Transport/Domain/Entity/Carrier.php @@ -81,6 +81,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; 'supplier:read', 'supplier_address:read', 'site:read', + // Embarque le nom de fichier de la decharge (RG-4.02) au lieu d'un + // IRI nu, pour l'affichage en consultation / modification (ERP-171). + 'uploaded_document:reference', 'default:read', ]], provider: CarrierProvider::class, diff --git a/src/Shared/Domain/Entity/UploadedDocument.php b/src/Shared/Domain/Entity/UploadedDocument.php index e1151cd..0ae76ac 100644 --- a/src/Shared/Domain/Entity/UploadedDocument.php +++ b/src/Shared/Domain/Entity/UploadedDocument.php @@ -75,8 +75,12 @@ class UploadedDocument #[Groups(['uploaded_document:read'])] private ?int $id = null; + // `uploaded_document:reference` : groupe minimal d'EMBARQUEMENT (nom de fichier + // seul, sans `storedPath`/`checksum`) pour qu'une entite parente (ex: Carrier) + // affiche le libelle du document au lieu d'un simple IRI. La parente l'ajoute a + // son `normalizationContext`. #[ORM\Column(name: 'original_filename', length: 255)] - #[Groups(['uploaded_document:read'])] + #[Groups(['uploaded_document:read', 'uploaded_document:reference'])] private string $originalFilename; #[ORM\Column(name: 'stored_path', length: 512)] diff --git a/tests/Module/Transport/Api/CarrierSerializationContractTest.php b/tests/Module/Transport/Api/CarrierSerializationContractTest.php index ba5650e..e66e9f2 100644 --- a/tests/Module/Transport/Api/CarrierSerializationContractTest.php +++ b/tests/Module/Transport/Api/CarrierSerializationContractTest.php @@ -4,9 +4,14 @@ declare(strict_types=1); namespace App\Tests\Module\Transport\Api; +use App\Module\Transport\Domain\Entity\Carrier; +use App\Shared\Domain\Entity\UploadedDocument; +use App\Tests\Module\Commercial\Api\SupplierSerializationContractTest; +use DateTimeImmutable; + /** * Tests du CONTRAT DE SERIALISATION du repertoire transporteurs (M4, spec-back - * § 4.0 / § 4.0.bis). Jumeau de {@see \App\Tests\Module\Commercial\Api\SupplierSerializationContractTest}. + * § 4.0 / § 4.0.bis). Jumeau de {@see SupplierSerializationContractTest}. * Reverifie sur le JSON REEL les pieges silencieux du M1 transposes au M4 : * - #1/#2 : relations embarquees en OBJET (pas IRI nu) — qualimatCarrier, et au * detail prices[].client / .supplier / .departureSite / .deliverySite. @@ -133,6 +138,43 @@ final class CarrierSerializationContractTest extends AbstractCarrierApiTestCase self::assertIsArray($supplierPrice['deliverySite']); } + // === Decharge (RG-4.02) embarquee en OBJET avec son nom de fichier (ERP-171) === + + public function testDetailEmbedsDischargeDocumentFilename(): void + { + $em = $this->getEm(); + + // Decharge (UploadedDocument) rattachee a un transporteur certifie AUTRE. + $document = new UploadedDocument( + originalFilename: 'decharge-test.pdf', + storedPath: '2026/06/'.bin2hex(random_bytes(8)).'.pdf', + mimeType: 'application/pdf', + sizeBytes: 1234, + checksum: hash('sha256', 'contenu'), + createdAt: new DateTimeImmutable(), + ); + $em->persist($document); + + $carrier = new Carrier(); + $carrier->setName('AUTRE DISCHARGE CO'); + $carrier->setCertificationType('AUTRE'); + $carrier->setDischargeDocument($document); + $em->persist($carrier); + $em->flush(); + + $http = $this->createAdminClient(); + $data = $http->request('GET', '/api/carriers/'.$carrier->getId(), ['headers' => ['Accept' => self::LD]])->toArray(); + + // dischargeDocument embarque en OBJET (uploaded_document:reference) avec son + // nom de fichier — sinon le front n'a qu'un IRI nu et affiche un champ vide. + self::assertArrayHasKey('dischargeDocument', $data); + self::assertIsArray($data['dischargeDocument'], 'dischargeDocument doit etre un objet embarque, pas un IRI nu.'); + self::assertSame('decharge-test.pdf', $data['dischargeDocument']['originalFilename']); + // Le groupe minimal n'expose PAS les metadonnees internes (storedPath / checksum). + self::assertArrayNotHasKey('storedPath', $data['dischargeDocument']); + self::assertArrayNotHasKey('checksum', $data['dischargeDocument']); + } + // === RBAC : 403 sans la permission view === public function testForbiddenWithoutViewPermission(): void @@ -183,7 +225,7 @@ final class CarrierSerializationContractTest extends AbstractCarrierApiTestCase * * @param array $collection * - * @return array|null + * @return null|array */ private function memberById(array $collection, int $id): ?array {