[ERP-76 + ERP-68] Validations d'adresse client (RG → 422) + fixtures démo Catalog/Commercial #41
@@ -202,18 +202,28 @@ class ClientAddress implements TimestampableInterface, BlamableInterface
|
|||||||
* RG-1.11 : l'email de facturation est obligatoire si l'adresse est de
|
* RG-1.11 : l'email de facturation est obligatoire si l'adresse est de
|
||||||
* facturation, et interdit sinon. Mirror applicatif (422) du CHECK
|
* facturation, et interdit sinon. Mirror applicatif (422) du CHECK
|
||||||
* chk_client_address_billing_email.
|
* chk_client_address_billing_email.
|
||||||
|
*
|
||||||
|
* On raisonne sur la PRESENCE effective de l'email : null ET chaine vide
|
||||||
|
* sont traites comme « absent », car le ClientAddressProcessor normalise une
|
||||||
|
* chaine vide en null APRES la validation (RG-1.21). Sans ce traitement,
|
||||||
|
* billingEmail="" passerait les callbacks (null === "" est faux) puis serait
|
||||||
|
* persiste en null avec is_billing=true -> violation du CHECK -> 500 au lieu
|
||||||
|
* du 422 attendu (et symetriquement, "" sur une adresse non facturable
|
||||||
|
* serait rejete a tort).
|
||||||
*/
|
*/
|
||||||
#[Assert\Callback]
|
#[Assert\Callback]
|
||||||
public function validateBillingEmailPresence(ExecutionContextInterface $context): void
|
public function validateBillingEmailPresence(ExecutionContextInterface $context): void
|
||||||
{
|
{
|
||||||
if ($this->isBilling && null === $this->billingEmail) {
|
$hasBillingEmail = null !== $this->billingEmail && '' !== trim($this->billingEmail);
|
||||||
|
|
||||||
|
if ($this->isBilling && !$hasBillingEmail) {
|
||||||
$context->buildViolation('L\'email de facturation est obligatoire pour une adresse de facturation.')
|
$context->buildViolation('L\'email de facturation est obligatoire pour une adresse de facturation.')
|
||||||
->atPath('billingEmail')
|
->atPath('billingEmail')
|
||||||
->addViolation()
|
->addViolation()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->isBilling && null !== $this->billingEmail) {
|
if (!$this->isBilling && $hasBillingEmail) {
|
||||||
$context->buildViolation('L\'email de facturation n\'est autorisé que sur une adresse de facturation.')
|
$context->buildViolation('L\'email de facturation n\'est autorisé que sur une adresse de facturation.')
|
||||||
->atPath('billingEmail')
|
->atPath('billingEmail')
|
||||||
->addViolation()
|
->addViolation()
|
||||||
|
|||||||
@@ -106,6 +106,33 @@ final class ClientAddressTest extends AbstractCommercialApiTestCase
|
|||||||
self::assertResponseStatusCodeSame(422);
|
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
|
* RG-1.11 (sens inverse) : une adresse NON facturable ne peut pas porter un
|
||||||
* billingEmail -> 422.
|
* billingEmail -> 422.
|
||||||
@@ -131,6 +158,33 @@ final class ClientAddressTest extends AbstractCommercialApiTestCase
|
|||||||
self::assertResponseStatusCodeSame(422);
|
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
|
* RG-1.29 : poster une categorie de type DISTRIBUTEUR sur une adresse -> 422
|
||||||
* avec violation sur le champ `categories`.
|
* avec violation sur le champ `categories`.
|
||||||
|
|||||||
Reference in New Issue
Block a user