authenticatedClient('admin', 'admin'); $admin = $this->getUserByUsername('admin'); $tour = $this->seedTour($admin, 'Tournée PDF'); // Une etape custom + une etape sur Tiers referentiel geolocalise. $this->seedCustomStop($tour, 0, 47.0, -1.0, 'RDV prospect'); $tier = $this->seedClient('Ferme PDF'); $address = $this->seedClientAddress($tier); $this->seedTierStop($tour, $tier, $address, 1); $response = $client->request('GET', '/api/tours/'.$tour->getId().'/roadbook.pdf'); self::assertResponseStatusCodeSame(200); self::assertResponseHeaderSame('Content-Type', 'application/pdf'); $content = $response->getContent(); self::assertStringStartsWith('%PDF', $content, 'Le corps est bien un binaire PDF.'); self::assertGreaterThan(800, strlen($content), 'Le PDF n\'est pas vide.'); } public function testRoadbookRequiresViewPermission(): void { $creds = $this->createUserWithPermission('core.users.view'); $client = $this->authenticatedClient($creds['username'], $creds['password']); $admin = $this->getUserByUsername('admin'); $tour = $this->seedTour($admin); $client->request('GET', '/api/tours/'.$tour->getId().'/roadbook.pdf'); self::assertResponseStatusCodeSame(403); } /** * RG-6.01 : une Commerciale ne peut pas exporter la tournee d'un autre. */ public function testRoadbookHidesOthersTour(): void { $credsA = $this->createUserWithPermissions(['field_sales.tours.view', 'field_sales.tours.manage']); $credsB = $this->createUserWithPermissions(['field_sales.tours.view', 'field_sales.tours.manage']); $client = $this->authenticatedClient($credsA['username'], $credsA['password']); $userB = $this->getUserByUsername($credsB['username']); $tourB = $this->seedTour($userB, 'Privée B'); $client->request('GET', '/api/tours/'.$tourB->getId().'/roadbook.pdf'); self::assertResponseStatusCodeSame(404); } private function seedCustomStop(\App\Module\FieldSales\Domain\Entity\Tour $tour, int $position, float $lat, float $lng, string $label): TourStop { $em = $this->getEm(); $stop = new TourStop(); $stop->setTour($tour); $stop->setTierType(TourStop::TIER_TYPE_CUSTOM); $stop->setCustomLabel($label); $stop->setCustomAddress('5 place du Marché, 44000 Nantes'); $stop->setCustomLatitude($lat); $stop->setCustomLongitude($lng); $stop->setPosition($position); $em->persist($stop); $em->flush(); return $stop; } private function seedTierStop(\App\Module\FieldSales\Domain\Entity\Tour $tour, \App\Module\Commercial\Domain\Entity\Client $tier, \App\Module\Commercial\Domain\Entity\ClientAddress $address, int $position): TourStop { $em = $this->getEm(); $stop = new TourStop(); $stop->setTour($tour); $stop->setTierType('client'); $stop->setTierId($tier->getId()); $stop->setAddressId($address->getId()); $stop->setPosition($position); $em->persist($stop); $em->flush(); return $stop; } }