b8dc3cb696
Auto Tag Develop / tag (push) Successful in 7s
Lot de correctifs sur l'écran Client (M1), + un retrait de règle métier et une petite fonctionnalité. ## Formulaire client (création / édition) - Boutons « ajouter un bloc » (Adresse, RIB) désactivés tant que le dernier bloc n'est pas valide. - Onglet Information : bouton Valider désactivé si aucun champ rempli (création) ; onglet Contact accessible dès la création (Information facultatif). - Champs « Relation » (Distributeur/Courtier) et « Prestation de triage » masqués par défaut, révélés seulement si une catégorie ordinaire (≠ Distributeur/Courtier) est sélectionnée. - Bloc RIB affiché uniquement si le type de règlement est LCR (création, édition, consultation) ; plus de RIB fantôme soumis. - Alignement du bas du textarea « Description » sur les autres champs. ## Recherche d'adresse (BAN) - Une erreur de l'API ne bloque plus définitivement la recherche : chaque frappe réessaie (le mode dégradé restait verrouillé). - Garde minimum 3 caractères avant l'appel à l'API. ## Répertoire client - Titres de colonne en noir 16px, corps + tags de site en 14px. ## Navigation - L'onglet actif est conservé au passage consultation ↔ édition (via history.state, hors URL). ## Règle métier - Retrait de RG-1.04 : l'onglet Information n'est plus obligatoire pour le rôle Commerciale — facultatif pour tous (back + tests + docs). Tests : suites front (Vitest) et back (PHPUnit) vertes hormis flakes d'infra connus. Reviewed-on: #76 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
83 lines
3.0 KiB
PHP
83 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Commercial\Application\Validator;
|
|
|
|
use ApiPlatform\Validator\Exception\ValidationException;
|
|
use App\Module\Commercial\Domain\Entity\Supplier;
|
|
use Symfony\Component\Validator\ConstraintViolation;
|
|
use Symfony\Component\Validator\ConstraintViolationList;
|
|
|
|
/**
|
|
* Validator metier RG-2.03 (completude Information cote fournisseur) :
|
|
* pour un utilisateur portant le role metier Commerciale, TOUS les champs de
|
|
* l'onglet Information sont obligatoires sur POST comme sur tout PATCH,
|
|
* independamment des champs reellement envoyes.
|
|
*
|
|
* Invoque par le SupplierProcessor des que l'utilisateur courant porte le role
|
|
* Commerciale (detection du role cote back). Pour les autres roles, ces champs
|
|
* restent optionnels — le validator n'est pas appele.
|
|
*
|
|
* NEW vs Client : ajoute le champ `volumeForecast` (volume previsionnel),
|
|
* specifique fournisseur.
|
|
*
|
|
* Leve une ValidationException (HTTP 422) listant chaque champ manquant, chaque
|
|
* violation portant son propertyPath (consommable par extractApiViolations,
|
|
* ERP-101), par coherence avec les violations Symfony rendues par API Platform.
|
|
*/
|
|
final class SupplierInformationCompletenessValidator
|
|
{
|
|
public function validate(Supplier $supplier): void
|
|
{
|
|
// Map champ -> valeur courante de l'onglet Information.
|
|
$fields = [
|
|
'description' => $supplier->getDescription(),
|
|
'competitors' => $supplier->getCompetitors(),
|
|
'foundedAt' => $supplier->getFoundedAt(),
|
|
'employeesCount' => $supplier->getEmployeesCount(),
|
|
'revenueAmount' => $supplier->getRevenueAmount(),
|
|
'directorName' => $supplier->getDirectorName(),
|
|
'profitAmount' => $supplier->getProfitAmount(),
|
|
'volumeForecast' => $supplier->getVolumeForecast(),
|
|
];
|
|
|
|
$violations = new ConstraintViolationList();
|
|
|
|
foreach ($fields as $property => $value) {
|
|
if ($this->isMissing($value)) {
|
|
$violations->add(new ConstraintViolation(
|
|
// Pas de nom de champ technique dans le message : la violation est
|
|
// deja rattachee au bon champ via son propertyPath (mappe inline
|
|
// cote front par useFormErrors).
|
|
'Ce champ est obligatoire pour le rôle Commerciale.',
|
|
null,
|
|
[],
|
|
$supplier,
|
|
$property,
|
|
$value,
|
|
));
|
|
}
|
|
}
|
|
|
|
if (count($violations) > 0) {
|
|
throw new ValidationException($violations);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Une valeur est manquante si null ou, pour une chaine, vide apres trim. Les
|
|
* zeros numeriques (employeesCount = 0, profitAmount = "0.00",
|
|
* volumeForecast = 0) sont des valeurs valides : on ne les considere pas
|
|
* manquants.
|
|
*/
|
|
private function isMissing(mixed $value): bool
|
|
{
|
|
if (null === $value) {
|
|
return true;
|
|
}
|
|
|
|
return is_string($value) && '' === trim($value);
|
|
}
|
|
}
|