fix(transport) : embarque le nom de la décharge dans le détail carrier (consultation/modif) (ERP-171)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 3m15s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m50s

This commit is contained in:
2026-06-17 15:34:17 +02:00
parent 7668d77c78
commit 498cef8cc0
3 changed files with 52 additions and 3 deletions
@@ -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,
@@ -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)]
@@ -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<string, mixed> $collection
*
* @return array<string, mixed>|null
* @return null|array<string, mixed>
*/
private function memberById(array $collection, int $id): ?array
{