= 1 site) sont DEJA couverts par * ClientSubResourceApiTest (ERP-57) et ne sont pas reduplique ici. Ce fichier * cible les contraintes CHECK BDD non encore testees : * - RG-1.06 / RG-1.07 / RG-1.08 : `chk_client_address_prospect_exclusive` * (is_prospect exclusif de is_delivery / is_billing) ; * - RG-1.11 : `chk_client_address_billing_email` (billing_email obligatoire * ssi is_billing). * * Note : ces regles sont portees par des CHECK Postgres (pas d'Assert ni de * regle Processor au M1). On verifie donc que la combinaison invalide est * REJETEE par le serveur (statut >= 400), sans coupler le test au code exact : * une violation CHECK non mappee remonte aujourd'hui en erreur serveur ; un * mapping fin vers 422 serait une amelioration ulterieure (hors perimetre * ERP-60, test-only). * * RG-1.29 (filtrage du type de categorie SECTEUR/AUTRE sur une adresse) n'est * PAS testee : la validation d'ecriture correspondante n'est pas implementee * cote back au M1 (et ne figure pas dans la liste § 8.1). Documentee comme gap * dans le cahier de test #478. * * @internal */ final class ClientAddressTest extends AbstractCommercialApiTestCase { private const string LD = 'application/ld+json'; /** * RG-1.06 / RG-1.07 : une adresse de prospection ne peut pas etre une * adresse de livraison (CHECK chk_client_address_prospect_exclusive). */ public function testProspectAddressCannotBeDelivery(): void { $this->skipIfSitesModuleDisabled(); $client = $this->createAdminClient(); $seed = $this->seedClient('Prospect Delivery'); $response = $client->request('POST', '/api/clients/'.$seed->getId().'/addresses', [ 'headers' => ['Content-Type' => self::LD], 'json' => [ 'isProspect' => true, 'isDelivery' => true, 'postalCode' => '86100', 'city' => 'Châtellerault', 'street' => '1 rue du Test', 'sites' => [$this->firstSiteIri()], ], ]); self::assertGreaterThanOrEqual(400, $response->getStatusCode()); } /** * RG-1.06 / RG-1.08 : une adresse de prospection ne peut pas etre une * adresse de facturation (meme CHECK). On fournit billingEmail pour que la * seule violation possible soit l'exclusivite prospect/billing. */ public function testProspectAddressCannotBeBilling(): void { $this->skipIfSitesModuleDisabled(); $client = $this->createAdminClient(); $seed = $this->seedClient('Prospect Billing'); $response = $client->request('POST', '/api/clients/'.$seed->getId().'/addresses', [ 'headers' => ['Content-Type' => self::LD], 'json' => [ 'isProspect' => true, 'isBilling' => true, 'billingEmail' => 'facturation@test.fr', 'postalCode' => '86100', 'city' => 'Châtellerault', 'street' => '1 rue du Test', 'sites' => [$this->firstSiteIri()], ], ]); self::assertGreaterThanOrEqual(400, $response->getStatusCode()); } /** * RG-1.11 : une adresse de facturation exige un billingEmail * (CHECK chk_client_address_billing_email). */ public function testBillingAddressRequiresBillingEmail(): void { $this->skipIfSitesModuleDisabled(); $client = $this->createAdminClient(); $seed = $this->seedClient('Billing No Email'); $response = $client->request('POST', '/api/clients/'.$seed->getId().'/addresses', [ 'headers' => ['Content-Type' => self::LD], 'json' => [ 'isBilling' => true, 'postalCode' => '86100', 'city' => 'Châtellerault', 'street' => '1 rue du Test', 'sites' => [$this->firstSiteIri()], ], ]); self::assertGreaterThanOrEqual(400, $response->getStatusCode()); } /** * RG-1.11 (sens inverse) : une adresse NON facturable ne peut pas porter un * billingEmail (meme CHECK). */ public function testNonBillingAddressRejectsBillingEmail(): void { $this->skipIfSitesModuleDisabled(); $client = $this->createAdminClient(); $seed = $this->seedClient('Non Billing With Email'); $response = $client->request('POST', '/api/clients/'.$seed->getId().'/addresses', [ 'headers' => ['Content-Type' => self::LD], 'json' => [ 'isBilling' => false, 'billingEmail' => 'parasite@test.fr', 'postalCode' => '86100', 'city' => 'Châtellerault', 'street' => '1 rue du Test', 'sites' => [$this->firstSiteIri()], ], ]); self::assertGreaterThanOrEqual(400, $response->getStatusCode()); } /** * Retourne l'IRI du premier site seede (fixtures Sites). */ private function firstSiteIri(): string { $site = $this->getEm()->getRepository(Site::class)->findOneBy([]); self::assertNotNull($site, 'Aucun site seede : impossible de tester les adresses.'); return '/api/sites/'.$site->getId(); } }