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>
This commit was merged in pull request #76.
This commit is contained in:
+8
-37
@@ -9,11 +9,8 @@ use ApiPlatform\State\ProcessorInterface;
|
||||
use ApiPlatform\Validator\Exception\ValidationException;
|
||||
use App\Module\Commercial\Application\Service\ClientFieldNormalizer;
|
||||
use App\Module\Commercial\Application\Validator\ClientAccountingCompletenessValidator;
|
||||
use App\Module\Commercial\Application\Validator\ClientInformationCompletenessValidator;
|
||||
use App\Module\Commercial\Domain\Entity\Client;
|
||||
use App\Shared\Domain\Contract\BusinessRoleAwareInterface;
|
||||
use App\Shared\Domain\Contract\CategoryInterface;
|
||||
use App\Shared\Domain\Security\BusinessRoles;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -44,8 +41,8 @@ use Symfony\Component\Validator\ConstraintViolationList;
|
||||
* 2. Normalisation serveur (RG-1.18 a 1.21) via ClientFieldNormalizer.
|
||||
* 3. Regles metier : RG-1.03 (distributor/broker
|
||||
* exclusifs + type de categorie), RG-1.12 (Virement -> banque),
|
||||
* RG-1.13 (LCR -> >= 1 RIB), RG-1.04 (completude Information exigee sur POST
|
||||
* et tout PATCH pour le role Commerciale).
|
||||
* RG-1.13 (LCR -> >= 1 RIB). L'onglet Information est entierement facultatif
|
||||
* (RG-1.04 retiree : plus d'obligation, y compris pour le role Commerciale).
|
||||
* 4. Pose / retrait de archivedAt (RG-1.22 true=now, RG-1.23 false=null).
|
||||
* 5. Persistance via le persist_processor Doctrine, avec traduction des
|
||||
* collisions d'unicite en 409 (RG-1.16 doublon de nom ; RG-1.23 conflit de
|
||||
@@ -108,7 +105,6 @@ final class ClientProcessor implements ProcessorInterface
|
||||
#[Autowire(service: 'api_platform.doctrine.orm.state.persist_processor')]
|
||||
private readonly ProcessorInterface $persistProcessor,
|
||||
private readonly ClientFieldNormalizer $normalizer,
|
||||
private readonly ClientInformationCompletenessValidator $informationValidator,
|
||||
private readonly ClientAccountingCompletenessValidator $accountingValidator,
|
||||
private readonly Security $security,
|
||||
private readonly RequestStack $requestStack,
|
||||
@@ -142,7 +138,6 @@ final class ClientProcessor implements ProcessorInterface
|
||||
$this->validateDistributorBroker($data);
|
||||
$this->validateAccountingConsistency($data);
|
||||
$this->validateAccountingCompleteness($data);
|
||||
$this->validateInformationCompleteness($data);
|
||||
|
||||
try {
|
||||
return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
|
||||
@@ -511,9 +506,9 @@ final class ClientProcessor implements ProcessorInterface
|
||||
* ce n'est pas une validation d'onglet (edition ponctuelle preservee). bank /
|
||||
* RIB restent geres par validateAccountingConsistency (RG-1.12 / RG-1.13).
|
||||
*
|
||||
* Colonnes nullable en base + validateur contextuel (meme parti que RG-1.04) :
|
||||
* un Assert\NotBlank sur l'entite casserait le POST de l'onglet principal, qui
|
||||
* n'envoie aucun champ comptable.
|
||||
* Colonnes nullable en base + validateur contextuel : un Assert\NotBlank sur
|
||||
* l'entite casserait le POST de l'onglet principal, qui n'envoie aucun champ
|
||||
* comptable.
|
||||
*/
|
||||
private function validateAccountingCompleteness(Client $data): void
|
||||
{
|
||||
@@ -526,21 +521,6 @@ final class ClientProcessor implements ProcessorInterface
|
||||
$this->accountingValidator->validate($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* RG-1.04 (durcie ERP-74) : si l'utilisateur porte le role metier
|
||||
* Commerciale, TOUS les champs de l'onglet Information sont obligatoires sur
|
||||
* POST comme sur TOUT PATCH — independamment des champs reellement envoyes
|
||||
* (plus de condition d'intersection avec INFORMATION_FIELDS). Garantit qu'un
|
||||
* client cree/edite par une Commerciale ne reste jamais avec un onglet
|
||||
* Information incomplet.
|
||||
*/
|
||||
private function validateInformationCompleteness(Client $data): void
|
||||
{
|
||||
if ($this->currentUserIsCommerciale()) {
|
||||
$this->informationValidator->validate($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vrai si au moins une categorie du client porte le code donne. S'appuie sur
|
||||
* CategoryInterface::getCode() (pas d'import de Category — regle ABSOLUE n°1).
|
||||
@@ -556,21 +536,12 @@ final class ClientProcessor implements ProcessorInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
private function currentUserIsCommerciale(): bool
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
|
||||
return $user instanceof BusinessRoleAwareInterface
|
||||
&& $user->hasBusinessRole(BusinessRoles::COMMERCIALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cles ecrivables effectivement presentes dans le payload : on retire les
|
||||
* cles JSON-LD (@id, @context, @var...) et tout champ non rattache a un
|
||||
* groupe d'ecriture connu. C'est la base du 422 d'archivage (RG-1.22) et du
|
||||
* declenchement conditionnel de RG-1.04 — sans elles, un PATCH
|
||||
* « representation complete » porteur de @id ferait croire a une
|
||||
* modification multi-onglets.
|
||||
* groupe d'ecriture connu. C'est la base du 422 d'archivage (RG-1.22) —
|
||||
* sans elles, un PATCH « representation complete » porteur de @id ferait
|
||||
* croire a une modification multi-onglets.
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
|
||||
@@ -234,7 +234,7 @@ class ClientFixtures extends Fixture implements DependentFixtureInterface
|
||||
$this->addAddress($services, ['Chatellerault'], '86100', 'Châtellerault', '15 rue du Conseil', isDelivery: true);
|
||||
}
|
||||
|
||||
// === Onglet Information complet (RG-1.04) ===
|
||||
// === Onglet Information complet (exemple de fiche renseignee) ===
|
||||
[$holding, $isNew] = $this->ensureClient(
|
||||
$manager,
|
||||
companyName: 'Holding Premium Invest',
|
||||
|
||||
Reference in New Issue
Block a user