diff --git a/src/Module/Commercial/Domain/Entity/ClientAddress.php b/src/Module/Commercial/Domain/Entity/ClientAddress.php index 29ca240..99a998f 100644 --- a/src/Module/Commercial/Domain/Entity/ClientAddress.php +++ b/src/Module/Commercial/Domain/Entity/ClientAddress.php @@ -63,6 +63,11 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; uriVariables: [ 'clientId' => new Link(fromClass: Client::class, toProperty: 'client'), ], + // read:false : pas de stade lecture du parent. Le Link toProperty + // resoudrait l'enfant (SELECT ClientAddress ... WHERE client = :id) et + // casse en NonUniqueResult des >= 2 enfants. Le parent est rattache + // manuellement par ClientAddressProcessor::linkParent (404 si absent). + read: false, security: "is_granted('commercial.clients.manage')", normalizationContext: ['groups' => ['client_address:read']], denormalizationContext: ['groups' => ['client_address:write']], diff --git a/src/Module/Commercial/Domain/Entity/ClientContact.php b/src/Module/Commercial/Domain/Entity/ClientContact.php index b28aaa2..80247c8 100644 --- a/src/Module/Commercial/Domain/Entity/ClientContact.php +++ b/src/Module/Commercial/Domain/Entity/ClientContact.php @@ -50,6 +50,11 @@ use Symfony\Component\Validator\Constraints as Assert; uriVariables: [ 'clientId' => new Link(fromClass: Client::class, toProperty: 'client'), ], + // read:false : pas de stade lecture du parent. Le Link toProperty + // resoudrait l'enfant (SELECT ClientContact ... WHERE client = :id) et + // casse en NonUniqueResult des >= 2 enfants. Le parent est rattache + // manuellement par ClientContactProcessor::linkParent (404 si absent). + read: false, security: "is_granted('commercial.clients.manage')", normalizationContext: ['groups' => ['client_contact:read']], denormalizationContext: ['groups' => ['client_contact:write']], diff --git a/src/Module/Commercial/Domain/Entity/ClientRib.php b/src/Module/Commercial/Domain/Entity/ClientRib.php index 956ee80..c2fb408 100644 --- a/src/Module/Commercial/Domain/Entity/ClientRib.php +++ b/src/Module/Commercial/Domain/Entity/ClientRib.php @@ -54,6 +54,11 @@ use Symfony\Component\Validator\Constraints as Assert; uriVariables: [ 'clientId' => new Link(fromClass: Client::class, toProperty: 'client'), ], + // read:false : pas de stade lecture du parent. Le Link toProperty + // resoudrait l'enfant (SELECT ClientRib ... WHERE client = :id) et + // casse en NonUniqueResult des >= 2 enfants. Le parent est rattache + // manuellement par ClientRibProcessor::linkParent (404 si absent). + read: false, security: "is_granted('commercial.clients.accounting.manage')", normalizationContext: ['groups' => ['client_rib:read']], denormalizationContext: ['groups' => ['client_rib:write']], diff --git a/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientAddressProcessor.php b/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientAddressProcessor.php index 1720432..01249e9 100644 --- a/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientAddressProcessor.php +++ b/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientAddressProcessor.php @@ -12,6 +12,7 @@ use App\Module\Commercial\Domain\Entity\Client; use App\Module\Commercial\Domain\Entity\ClientAddress; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Processor d'ecriture de la sous-ressource Adresse d'un client (M1, § 4.5). @@ -75,9 +76,14 @@ final class ClientAddressProcessor implements ProcessorInterface ? $clientId : $this->em->getRepository(Client::class)->find($clientId); - if ($client instanceof Client) { - $address->setClient($client); + // read:false sur le POST : sans stade lecture, un parent introuvable n'est + // plus intercepte en amont -> 404 explicite (sinon 500 au persist sur la + // contrainte client_id NOT NULL). + if (!$client instanceof Client) { + throw new NotFoundHttpException('Client introuvable.'); } + + $address->setClient($client); } /** diff --git a/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientContactProcessor.php b/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientContactProcessor.php index 3ddffc0..4806336 100644 --- a/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientContactProcessor.php +++ b/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientContactProcessor.php @@ -14,6 +14,7 @@ use App\Module\Commercial\Domain\Entity\ClientContact; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpKernel\Exception\ConflictHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; @@ -88,9 +89,14 @@ final class ClientContactProcessor implements ProcessorInterface ? $clientId : $this->em->getRepository(Client::class)->find($clientId); - if ($client instanceof Client) { - $contact->setClient($client); + // read:false sur le POST : sans stade lecture, un parent introuvable n'est + // plus intercepte en amont -> 404 explicite (sinon 500 au persist sur la + // contrainte client_id NOT NULL). + if (!$client instanceof Client) { + throw new NotFoundHttpException('Client introuvable.'); } + + $contact->setClient($client); } /** diff --git a/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientRibProcessor.php b/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientRibProcessor.php index baf55ec..39e280c 100644 --- a/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientRibProcessor.php +++ b/src/Module/Commercial/Infrastructure/ApiPlatform/State/Processor/ClientRibProcessor.php @@ -12,6 +12,7 @@ use App\Module\Commercial\Domain\Entity\ClientRib; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpKernel\Exception\ConflictHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Processor d'ecriture de la sous-ressource RIB d'un client (M1, § 4.5). @@ -77,9 +78,14 @@ final class ClientRibProcessor implements ProcessorInterface ? $clientId : $this->em->getRepository(Client::class)->find($clientId); - if ($client instanceof Client) { - $rib->setClient($client); + // read:false sur le POST : sans stade lecture, un parent introuvable n'est + // plus intercepte en amont -> 404 explicite (sinon 500 au persist sur la + // contrainte client_id NOT NULL). + if (!$client instanceof Client) { + throw new NotFoundHttpException('Client introuvable.'); } + + $rib->setClient($client); } /**