feat(logistique) : entité WeighingTicket + dette site.code (ERP-183)
Entité WeighingTicket - Entité métier complète (#[Auditable], TimestampableBlamableTrait, relations ORM Client/Supplier/Site) + contrat de sérialisation à 3 maillons (weighing_ticket:read / :item:read + contextes par opération). - Getters calculés displayDate et plateFreeFormat (#[SerializedName]), sécurité view/manage, pas de Delete/archive. - Validation #[Assert\*] messages FR + #[Assert\Callback] RG-5.03 (->atPath()), libellé i18n audit.entity.logistique_weighingticket. - Repository : interface Domain + DoctrineWeighingTicketRepository (recherche + tri number DESC, deletedAt IS NULL). Dette site.code - Site.code mappé VARCHAR(8) (groupes read/write), dérivation auto au PrePersist (2 premiers chiffres du CP), UniqueConstraint uq_site_code. - Migration Version20260617160000 : ALTER COLUMN code SET NOT NULL + COMMENT. - Fixtures (codes 86/17/82) et SiteApiTest ajustés. Câblage - doctrine.yaml : mapping ORM du module Logistique (absent du scaffold ERP-181). - ColumnCommentsCatalog : site.code + table weighing_ticket. Specs M5 versionnées (spec-back / spec-front / prompts).
This commit is contained in:
@@ -72,6 +72,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
#[ORM\Table(name: 'site')]
|
||||
#[Auditable]
|
||||
#[ORM\UniqueConstraint(name: 'uniq_site_name', columns: ['name'])]
|
||||
#[ORM\UniqueConstraint(name: 'uq_site_code', columns: ['code'])]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[UniqueEntity(fields: ['name'], message: 'Un site avec ce nom existe deja.')]
|
||||
class Site implements SiteInterface
|
||||
@@ -88,6 +89,16 @@ class Site implements SiteInterface
|
||||
#[Groups(['site:read', 'site:write', 'me:read'])]
|
||||
private string $name;
|
||||
|
||||
// Code court du site (86/17/82) — prefixe de numerotation des tickets de
|
||||
// pesee (RG-5.02, M5 Logistique). Auto-derive des 2 premiers chiffres du
|
||||
// code postal (departement) a la creation s'il n'est pas fourni
|
||||
// explicitement (onPrePersist, § 2.5), editable ensuite cote admin Sites.
|
||||
// Unique en base (uq_site_code).
|
||||
#[ORM\Column(length: 8)]
|
||||
#[Assert\Length(max: 8, maxMessage: 'Le code du site ne peut pas depasser {{ limit }} caracteres.')]
|
||||
#[Groups(['site:read', 'site:write', 'me:read'])]
|
||||
private ?string $code = null;
|
||||
|
||||
// Premiere ligne d'adresse : numero + voie. Requise.
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Assert\NotBlank(message: 'La rue est requise.')]
|
||||
@@ -188,6 +199,20 @@ class Site implements SiteInterface
|
||||
$this->updatedAt = new DateTimeImmutable();
|
||||
}
|
||||
|
||||
/**
|
||||
* A la creation, derive le code court du site des 2 premiers chiffres du
|
||||
* code postal (departement) si aucun code n'a ete fourni explicitement
|
||||
* (RG-5.02, § 2.5). Le code reste editable ensuite ; son unicite est
|
||||
* garantie en base par uq_site_code.
|
||||
*/
|
||||
#[ORM\PrePersist]
|
||||
public function onPrePersist(): void
|
||||
{
|
||||
if (null === $this->code || '' === trim($this->code)) {
|
||||
$this->code = substr($this->postalCode, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -205,6 +230,18 @@ class Site implements SiteInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCode(): ?string
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(?string $code): static
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStreet(): string
|
||||
{
|
||||
return $this->street;
|
||||
|
||||
Reference in New Issue
Block a user