d9313dbec8
Schéma BDD du répertoire transporteurs (M4) + entités + contrat de lecture (liste + détail), socle du front. - Migration Version20260615150000 : tables carrier / carrier_address / carrier_contact / carrier_price (FK cross-module, CHECK enum, index partiel uq_carrier_name_active, COMMENT ON COLUMN). uploaded_document et qualimat_carrier réutilisées (non recréées). - Entités Carrier* (#[Auditable], Timestampable/Blamable) + ApiResource LECTURE seule (GetCollection + Get via CarrierProvider, anti-N+1, exclusion archivés + ?includeArchived). Écriture (POST/PATCH + Processor) reportée WT4+. - QualimatCarrier : mapping ORM lecture seule sur la table référentielle existante (sortie du schema_filter, mapping aligné DDL ERP-39, schema:update no-op) + endpoint de recherche read-only (§ 4.7). - Relations cross-module des prix (Client/Supplier/adresses) via contrats Shared (ClientInterface, SupplierInterface, ClientAddressInterface, SupplierAddressInterface) + resolve_target_entities — sans import inter-module (règle n°1). Ajout du groupe supplier_address:read aux champs de SupplierAddress pour l'embed. - Garde-fous : ColumnCommentsCatalog (carrier* + qualimat_carrier), makefile test-db-setup (index partiel carrier), i18n audit (transport_carrier*), EntitiesAreTimestampableBlamableTest (QualimatCarrier whitelisté). - CarrierSerializationContractTest : contrat JSON liste + détail vérifié (embeds objet, booléens, enveloppe Hydra) ; JSON réel capturé dans spec-back § 4.0.bis. make db-reset OK, make test vert (731), make nuxt-test vert (480), php-cs-fixer OK.
170 lines
4.2 KiB
PHP
170 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Transport\Domain\Entity;
|
|
|
|
use App\Shared\Domain\Attribute\Auditable;
|
|
use App\Shared\Domain\Contract\BlamableInterface;
|
|
use App\Shared\Domain\Contract\TimestampableInterface;
|
|
use App\Shared\Domain\Trait\TimestampableBlamableTrait;
|
|
use Doctrine\ORM\Mapping as ORM;
|
|
use Symfony\Component\Serializer\Attribute\Groups;
|
|
|
|
/**
|
|
* Contact d'un transporteur (1:n) — onglet Contact (M4). Jumeau de
|
|
* SupplierContact (M2) : au moins un champ rempli (RG-4.08, garanti par le
|
|
* CHECK chk_carrier_contact_filled + le Processor), max 2 telephones.
|
|
*
|
|
* WT3 (ERP-155/157) = LECTURE seule : proprietes en `carrier:item:read`
|
|
* (embarquees au detail). Les sous-ressources d'ecriture arrivent au WT7.
|
|
*/
|
|
#[ORM\Entity]
|
|
#[ORM\Table(name: 'carrier_contact')]
|
|
#[ORM\Index(name: 'idx_carrier_contact_carrier', columns: ['carrier_id'])]
|
|
#[ORM\Index(name: 'idx_carrier_contact_created_by', columns: ['created_by'])]
|
|
#[ORM\Index(name: 'idx_carrier_contact_updated_by', columns: ['updated_by'])]
|
|
#[Auditable]
|
|
class CarrierContact implements TimestampableInterface, BlamableInterface
|
|
{
|
|
use TimestampableBlamableTrait;
|
|
|
|
#[ORM\Id]
|
|
#[ORM\GeneratedValue]
|
|
#[ORM\Column]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?int $id = null;
|
|
|
|
#[ORM\ManyToOne(targetEntity: Carrier::class, inversedBy: 'contacts')]
|
|
#[ORM\JoinColumn(name: 'carrier_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
|
private ?Carrier $carrier = null;
|
|
|
|
#[ORM\Column(name: 'first_name', length: 120, nullable: true)]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?string $firstName = null;
|
|
|
|
#[ORM\Column(name: 'last_name', length: 120, nullable: true)]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?string $lastName = null;
|
|
|
|
#[ORM\Column(name: 'job_title', length: 120, nullable: true)]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?string $jobTitle = null;
|
|
|
|
#[ORM\Column(name: 'phone_primary', length: 20, nullable: true)]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?string $phonePrimary = null;
|
|
|
|
#[ORM\Column(name: 'phone_secondary', length: 20, nullable: true)]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?string $phoneSecondary = null;
|
|
|
|
#[ORM\Column(length: 180, nullable: true)]
|
|
#[Groups(['carrier:item:read'])]
|
|
private ?string $email = null;
|
|
|
|
#[ORM\Column(options: ['default' => 0])]
|
|
private int $position = 0;
|
|
|
|
public function getId(): ?int
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
public function getCarrier(): ?Carrier
|
|
{
|
|
return $this->carrier;
|
|
}
|
|
|
|
public function setCarrier(?Carrier $carrier): static
|
|
{
|
|
$this->carrier = $carrier;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getFirstName(): ?string
|
|
{
|
|
return $this->firstName;
|
|
}
|
|
|
|
public function setFirstName(?string $firstName): static
|
|
{
|
|
$this->firstName = $firstName;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getLastName(): ?string
|
|
{
|
|
return $this->lastName;
|
|
}
|
|
|
|
public function setLastName(?string $lastName): static
|
|
{
|
|
$this->lastName = $lastName;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getJobTitle(): ?string
|
|
{
|
|
return $this->jobTitle;
|
|
}
|
|
|
|
public function setJobTitle(?string $jobTitle): static
|
|
{
|
|
$this->jobTitle = $jobTitle;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getPhonePrimary(): ?string
|
|
{
|
|
return $this->phonePrimary;
|
|
}
|
|
|
|
public function setPhonePrimary(?string $phonePrimary): static
|
|
{
|
|
$this->phonePrimary = $phonePrimary;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getPhoneSecondary(): ?string
|
|
{
|
|
return $this->phoneSecondary;
|
|
}
|
|
|
|
public function setPhoneSecondary(?string $phoneSecondary): static
|
|
{
|
|
$this->phoneSecondary = $phoneSecondary;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getEmail(): ?string
|
|
{
|
|
return $this->email;
|
|
}
|
|
|
|
public function setEmail(?string $email): static
|
|
{
|
|
$this->email = $email;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getPosition(): int
|
|
{
|
|
return $this->position;
|
|
}
|
|
|
|
public function setPosition(int $position): static
|
|
{
|
|
$this->position = $position;
|
|
|
|
return $this;
|
|
}
|
|
}
|