58474404b4
- 4 entités Provider / ProviderContact / ProviderAddress / ProviderRib (#[Auditable] + Timestampable/Blamable), miroir Supplier* amputé de l'onglet Information et augmenté de provider.sites (M2M direct, RG-3.03). - Contrat de sérialisation à 3 maillons (groupes liste/détail, getter isArchived + SerializedName) ; référentiels comptables consommés en relation ORM partagée, Site/Category via contrats Shared. - DoctrineProviderRepository : createListQueryBuilder (filtres + tri) + hydratation anti-N+1 categories puis sites (relation directe) en requêtes IN bornées séparées. - Mapping ORM du module Technique (doctrine.yaml), catalogue COMMENT des tables provider*, index partiel uq_provider_company_name_active (test-db-setup), libellés audit i18n technique_*, whitelist Length du CP ProviderAddress. ApiResource posé en squelette : ProviderProvider / ProviderProcessor (hydratation effective, gating accounting, cloisonnement site, normalisation, 409, RG-3.07/3.08) relèvent d'ERP-134.
190 lines
5.8 KiB
PHP
190 lines
5.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Technique\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;
|
|
use Symfony\Component\Validator\Constraints as Assert;
|
|
|
|
/**
|
|
* Contact d'un prestataire (1:n) — onglet Contacts. Un bloc est valide des qu'au
|
|
* moins un champ est rempli (RG-3.04) : garantie portee par un CHECK BDD
|
|
* (chk_provider_contact_name) + le ProviderProcessor (ERP-134) ; l'entite reste
|
|
* permissive (tous les champs nullable).
|
|
*
|
|
* Embarque sous `provider.contacts` au detail (groupe provider:item:read,
|
|
* maillon (a) du contrat de serialisation). Maximum 2 telephones
|
|
* (phonePrimary + phoneSecondary).
|
|
*
|
|
* L'exposition en SOUS-RESSOURCE API (POST /providers/{id}/contacts, PATCH /
|
|
* DELETE) est un ticket ulterieur du M3 : pas d'#[ApiResource] ici (l'entite est
|
|
* pour l'instant uniquement embarquee via le detail du prestataire).
|
|
*
|
|
* Audite (#[Auditable]) + Timestampable / Blamable (pattern Shared standard).
|
|
*/
|
|
#[ORM\Entity]
|
|
#[ORM\Table(name: 'provider_contact')]
|
|
#[ORM\Index(name: 'idx_provider_contact_provider', columns: ['provider_id'])]
|
|
#[Auditable]
|
|
class ProviderContact implements TimestampableInterface, BlamableInterface
|
|
{
|
|
use TimestampableBlamableTrait;
|
|
|
|
#[ORM\Id]
|
|
#[ORM\GeneratedValue]
|
|
#[ORM\Column]
|
|
#[Groups(['provider:item:read'])]
|
|
private ?int $id = null;
|
|
|
|
#[ORM\ManyToOne(targetEntity: Provider::class, inversedBy: 'contacts')]
|
|
#[ORM\JoinColumn(name: 'provider_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
|
private ?Provider $provider = null;
|
|
|
|
// RG-3.04 : au moins un champ du contact renseigne (CHECK BDD + Processor). Les
|
|
// champs restent nullable au niveau ORM.
|
|
#[ORM\Column(length: 120, nullable: true)]
|
|
#[Assert\Length(max: 120, maxMessage: 'Le prénom ne peut dépasser {{ limit }} caractères.', normalizer: 'trim')]
|
|
#[Groups(['provider:item:read', 'provider:write:contacts'])]
|
|
private ?string $firstName = null;
|
|
|
|
#[ORM\Column(length: 120, nullable: true)]
|
|
#[Assert\Length(max: 120, maxMessage: 'Le nom ne peut dépasser {{ limit }} caractères.', normalizer: 'trim')]
|
|
#[Groups(['provider:item:read', 'provider:write:contacts'])]
|
|
private ?string $lastName = null;
|
|
|
|
#[ORM\Column(length: 120, nullable: true)]
|
|
#[Assert\Length(max: 120, maxMessage: 'La fonction ne peut dépasser {{ limit }} caractères.', normalizer: 'trim')]
|
|
#[Groups(['provider:item:read', 'provider:write:contacts'])]
|
|
private ?string $jobTitle = null;
|
|
|
|
// Pas de validation de format telephone (saisie libre), mais une Assert\Length
|
|
// calee sur la colonne VARCHAR(20) evite l'erreur Postgres (500 non rattachee au
|
|
// champ) au profit d'une 422 propre (ERP-107).
|
|
#[ORM\Column(length: 20, nullable: true)]
|
|
#[Assert\Length(max: 20, maxMessage: 'Le téléphone ne peut dépasser {{ limit }} caractères.', normalizer: 'trim')]
|
|
#[Groups(['provider:item:read', 'provider:write:contacts'])]
|
|
private ?string $phonePrimary = null;
|
|
|
|
#[ORM\Column(length: 20, nullable: true)]
|
|
#[Assert\Length(max: 20, maxMessage: 'Le téléphone secondaire ne peut dépasser {{ limit }} caractères.', normalizer: 'trim')]
|
|
#[Groups(['provider:item:read', 'provider:write:contacts'])]
|
|
private ?string $phoneSecondary = null;
|
|
|
|
#[ORM\Column(length: 180, nullable: true)]
|
|
#[Assert\Email(message: 'L\'adresse email n\'est pas valide.')]
|
|
#[Assert\Length(max: 180, maxMessage: 'L\'email ne peut dépasser {{ limit }} caractères.', normalizer: 'trim')]
|
|
#[Groups(['provider:item:read', 'provider:write:contacts'])]
|
|
private ?string $email = null;
|
|
|
|
// Ordre d'affichage du contact (gere serveur, non expose au M3).
|
|
#[ORM\Column(options: ['default' => 0])]
|
|
private int $position = 0;
|
|
|
|
public function getId(): ?int
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
public function getProvider(): ?Provider
|
|
{
|
|
return $this->provider;
|
|
}
|
|
|
|
public function setProvider(?Provider $provider): static
|
|
{
|
|
$this->provider = $provider;
|
|
|
|
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;
|
|
}
|
|
}
|