97d7cacd2c
Ecriture du formulaire principal transporteur (M4, WT4) : POST/PATCH via CarrierProcessor + CarrierFieldNormalizer, contraintes conditionnelles sur l'entite Carrier. - RG-4.01 : POST qualimatCarrier -> certificationType=QUALIMAT + FK persistee ; cas LIOT (name=LIOT) -> certification non requise, liotPlates accepte. - RG-4.02 : certificationType=AUTRE sans dischargeDocument -> 422 (Assert\Callback). - RG-4.03 : isChartered=true sans indexationRate/containerType/volumeM3 -> 422. - RG-4.12 : doublon de nom (parmi actifs) -> 409 (index partiel uq_carrier_name_active). - RG-4.13 : normalisation serveur (name UPPER, liotPlates ;-split/trim/UPPER) + methodes personne/telephone/email pour les sous-ressources Contact (WT7). - RG-4.14 : PATCH isArchived exige transport.carriers.archive (Admin seul), mode strict -> 403 + 422 si autre champ ; restauration en conflit -> 409. Operations Post/Patch ajoutees a l'ApiResource (lecture posee au WT3 conservee). RG conditionnelles portees par validateMainFormConsistency (Assert\Callback + ->atPath()) pour un propertyPath mappable inline (useFormErrors, ERP-101). certificationType / containerType whitelistes dans EXCLUDED_LENGTH_MIRROR (Choice borne deja les valeurs, miroir SupplierAddress::addressType). Tests : CarrierWriteApiTest (RG-4.01->4.03/4.12->4.14), CarrierRBACMatrixTest (matrice bureau/compta/commerciale/usine), CarrierArchiveTest (409 restauration), CarrierFieldNormalizerTest (RG-4.13). make test vert (750).
106 lines
3.2 KiB
PHP
106 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Transport\Application\Service;
|
|
|
|
/**
|
|
* Normalisation serveur des champs texte d'un Carrier / CarrierContact, appliquee
|
|
* par le CarrierProcessor (et les futurs processors de sous-ressources, WT6/7/8)
|
|
* AVANT persistance. Cf. spec-back M4 § 2.10 + RG-4.13. Jumeau de
|
|
* SupplierFieldNormalizer (M2), enrichi du cas LIOT (immatriculations).
|
|
*
|
|
* - name : UPPERCASE integral (RG-4.13)
|
|
* - firstName / lastName (personnes, sur CarrierContact) : Title Case (RG-4.13)
|
|
* - phone* : chiffres uniquement, ex "06.12.34.56.78" -> "0612345678" (RG-4.13).
|
|
* Le formatage d'affichage "XX XX XX XX XX" est de la responsabilite du front.
|
|
* - email : lowercase integral (RG-4.13)
|
|
* - liotPlates : liste « ; » -> split, trim, UPPER, rejoin "; " (cas LIOT RG-4.01).
|
|
*
|
|
* Toutes les methodes sont null-safe et trim-ent l'entree ; une chaine vide apres
|
|
* trim devient null (evite de persister "" dans des colonnes nullable).
|
|
*/
|
|
final class CarrierFieldNormalizer
|
|
{
|
|
/**
|
|
* Raison sociale en majuscules (RG-4.13). Conserve null tel quel ; une chaine
|
|
* non vide est trim + upper. Une chaine vide reste "" (champ obligatoire :
|
|
* c'est l'Assert\NotBlank qui rejette, pas le normalizer).
|
|
*/
|
|
public function normalizeName(?string $value): ?string
|
|
{
|
|
if (null === $value) {
|
|
return null;
|
|
}
|
|
|
|
return mb_strtoupper(trim($value), 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Nom/prenom de personne en Title Case (RG-4.13) : "JEAN dupont" ->
|
|
* "Jean Dupont". Une chaine vide apres trim devient null.
|
|
*/
|
|
public function normalizePersonName(?string $value): ?string
|
|
{
|
|
if (null === $value) {
|
|
return null;
|
|
}
|
|
|
|
$value = trim($value);
|
|
|
|
return '' === $value ? null : mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Email en minuscules (RG-4.13). Une chaine vide apres trim devient null.
|
|
*/
|
|
public function normalizeEmail(?string $value): ?string
|
|
{
|
|
if (null === $value) {
|
|
return null;
|
|
}
|
|
|
|
$value = trim($value);
|
|
|
|
return '' === $value ? null : mb_strtolower($value, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Telephone reduit aux chiffres (RG-4.13) : "06.12.34.56.78" -> "0612345678".
|
|
* Une valeur sans aucun chiffre devient null.
|
|
*/
|
|
public function normalizePhone(?string $value): ?string
|
|
{
|
|
if (null === $value) {
|
|
return null;
|
|
}
|
|
|
|
$digits = preg_replace('/\D+/', '', $value) ?? '';
|
|
|
|
return '' === $digits ? null : $digits;
|
|
}
|
|
|
|
/**
|
|
* Immatriculations LIOT (RG-4.01 / RG-4.13) : la saisie « ; »-separee est
|
|
* decoupee, chaque plaque trim + UPPER, les segments vides ecartes, puis
|
|
* recomposee avec le separateur canonique "; ". Une saisie sans aucune plaque
|
|
* exploitable devient null.
|
|
*/
|
|
public function normalizeLiotPlates(?string $value): ?string
|
|
{
|
|
if (null === $value) {
|
|
return null;
|
|
}
|
|
|
|
$plates = [];
|
|
foreach (explode(';', $value) as $plate) {
|
|
$plate = trim($plate);
|
|
if ('' !== $plate) {
|
|
$plates[] = mb_strtoupper($plate, 'UTF-8');
|
|
}
|
|
}
|
|
|
|
return [] === $plates ? null : implode('; ', $plates);
|
|
}
|
|
}
|