fix(commercial) : billingEmail vide rejete en 422 et non en 500 (RG-1.11)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m55s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m18s

Le callback validateBillingEmailPresence testait null === billingEmail. Une
chaine vide "" (champ vide envoye par le client) passait donc les validators ;
le ClientAddressProcessor la normalisait ensuite en null APRES la validation,
puis la persistance d'une adresse is_billing=true avec billing_email=null
violait le CHECK chk_client_address_billing_email -> 500 DBAL au lieu du 422
attendu. Symetriquement, "" sur une adresse non facturable etait rejete a tort
en 422 alors qu'un champ vide equivaut a une absence d'email.

Le callback raisonne desormais sur la presence effective (null OU chaine vide
apres trim = absent), coheremment avec la normalisation du processor. Deux cas
de test ajoutes : adresse facturable + "" -> 422, adresse non facturable +
"" -> 201.
This commit is contained in:
Matthieu
2026-06-02 00:10:43 +02:00
parent 039d4c6391
commit e6188535fd
2 changed files with 66 additions and 2 deletions
@@ -106,6 +106,33 @@ final class ClientAddressTest extends AbstractCommercialApiTestCase
self::assertResponseStatusCodeSame(422);
}
/**
* RG-1.11 (cas chaine vide) : une adresse de facturation avec un billingEmail
* vide ("") doit etre rejetee en 422, et NON passer la validation pour finir
* en 500 sur le CHECK BDD. Le ClientAddressProcessor normalise "" -> null
* APRES la validation : le callback doit donc traiter "" comme « absent ».
*/
public function testBillingAddressRejectsEmptyBillingEmail(): void
{
$this->skipIfSitesModuleDisabled();
$client = $this->createAdminClient();
$seed = $this->seedClient('Billing Empty Email');
$client->request('POST', '/api/clients/'.$seed->getId().'/addresses', [
'headers' => ['Content-Type' => self::LD],
'json' => [
'isBilling' => true,
'billingEmail' => '',
'postalCode' => '86100',
'city' => 'Châtellerault',
'street' => '1 rue du Test',
'sites' => [$this->firstSiteIri()],
],
]);
self::assertResponseStatusCodeSame(422);
}
/**
* RG-1.11 (sens inverse) : une adresse NON facturable ne peut pas porter un
* billingEmail -> 422.
@@ -131,6 +158,33 @@ final class ClientAddressTest extends AbstractCommercialApiTestCase
self::assertResponseStatusCodeSame(422);
}
/**
* RG-1.11 (sens inverse, cas chaine vide) : une adresse NON facturable avec
* un billingEmail vide ("") est ACCEPTEE (201). Le "" equivaut a « pas
* d'email » : il ne doit pas declencher la violation « email interdit hors
* facturation » (sinon un champ simplement vide serait refuse a tort).
*/
public function testNonBillingAddressAcceptsEmptyBillingEmail(): void
{
$this->skipIfSitesModuleDisabled();
$client = $this->createAdminClient();
$seed = $this->seedClient('Non Billing Empty Email');
$client->request('POST', '/api/clients/'.$seed->getId().'/addresses', [
'headers' => ['Content-Type' => self::LD],
'json' => [
'isBilling' => false,
'billingEmail' => '',
'postalCode' => '86100',
'city' => 'Châtellerault',
'street' => '1 rue du Test',
'sites' => [$this->firstSiteIri()],
],
]);
self::assertResponseStatusCodeSame(201);
}
/**
* RG-1.29 : poster une categorie de type DISTRIBUTEUR sur une adresse -> 422
* avec violation sur le champ `categories`.