feat(transport) : adresse unique par transporteur (OneToOne back + un seul bloc front) (ERP-172)

This commit is contained in:
2026-06-17 17:32:29 +02:00
parent 498cef8cc0
commit e76bd1dd63
14 changed files with 219 additions and 225 deletions
@@ -58,14 +58,13 @@ use Symfony\Component\Validator\Constraints as Assert;
normalizationContext: ['groups' => ['carrier:item:read', 'default:read']],
),
new Post(
uriTemplate: '/carriers/{carrierId}/addresses',
uriTemplate: '/carriers/{carrierId}/address',
uriVariables: [
'carrierId' => new Link(fromClass: Carrier::class, toProperty: 'carrier'),
],
// read:false : pas de stade lecture du parent. Le Link toProperty
// resoudrait l'enfant (SELECT CarrierAddress ... WHERE carrier = :id)
// et casse en NonUniqueResult des >= 2 enfants. Le parent est rattache
// manuellement par CarrierAddressProcessor::linkParent (404 si absent).
// read:false : pas de stade lecture du parent. Le parent est rattache
// manuellement par CarrierAddressProcessor::linkParent (404 si absent),
// qui refuse aussi une 2e adresse (RG metier : adresse UNIQUE — 409).
read: false,
security: "is_granted('transport.carriers.manage')",
normalizationContext: ['groups' => ['carrier:item:read', 'default:read']],
@@ -86,7 +85,9 @@ use Symfony\Component\Validator\Constraints as Assert;
)]
#[ORM\Entity]
#[ORM\Table(name: 'carrier_address')]
#[ORM\Index(name: 'idx_carrier_address_carrier', columns: ['carrier_id'])]
// Adresse UNIQUE par transporteur (OneToOne owning side) : contrainte d'unicite
// sur carrier_id (decision metier ERP-172).
#[ORM\UniqueConstraint(name: 'uniq_carrier_address_carrier', columns: ['carrier_id'])]
#[ORM\Index(name: 'idx_carrier_address_created_by', columns: ['created_by'])]
#[ORM\Index(name: 'idx_carrier_address_updated_by', columns: ['updated_by'])]
#[Auditable]
@@ -100,7 +101,7 @@ class CarrierAddress implements TimestampableInterface, BlamableInterface
#[Groups(['carrier:item:read'])]
private ?int $id = null;
#[ORM\ManyToOne(targetEntity: Carrier::class, inversedBy: 'addresses')]
#[ORM\OneToOne(targetEntity: Carrier::class, inversedBy: 'address')]
#[ORM\JoinColumn(name: 'carrier_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
private ?Carrier $carrier = null;