Branche l'API REST du repertoire clients (M1) sur l'entite Client preparee en
ERP-54. Operations GetCollection / Get / Post / Patch (pas de Delete au M1 :
l'archivage passe par PATCH isArchived).
ClientProvider :
- liste paginee (Paginator ORM, aligne sur la convention ERP-72) + echappatoire
?pagination=false
- exclut archives + soft-deletes par defaut (RG-1.24), ?includeArchived=true
reintegre les archives (RG-1.25)
- tri companyName ASC (RG-1.26), filtres ?search (fuzzy companyName/lastName/
email) et ?categoryType=<code>
- detail : 404 sur soft-delete, embarque contacts/adresses/ribs
ClientProcessor :
- normalisation serveur via ClientFieldNormalizer (RG-1.18 a 1.21)
- 409 sur doublon de nom de societe (RG-1.16) ; 409 dedie sur conflit de
restauration (RG-1.23)
- gating par onglet : champ comptable -> accounting.manage, isArchived ->
archive, mode strict 403 sur tout le payload (RG-1.28) ; archivage exclusif
(RG-1.22) + pose/retrait archivedAt
- regles metier RG-1.01 (prenom/nom), RG-1.03 (distributor/broker exclusifs +
controle du type de categorie), RG-1.12 (Virement -> banque), RG-1.13 (LCR ->
>= 1 RIB), RG-1.04 (completude Information pour le role Commerciale)
Lecture comptable conditionnelle : ClientReadGroupContextBuilder ajoute le
groupe client:read:accounting selon commercial.clients.accounting.view.
Resolution des references categorie : CategoryReferenceDenormalizer resout les
IRI vers Category quand la propriete est type-hintee par le contrat
CategoryInterface (denormalisation impossible sur une interface sinon).
Contrats Shared :
- CategoryInterface::getCategoryTypeCode() (implemente par Category) pour la
verification de type sans import inter-modules
- BusinessRoleAwareInterface (implemente par User) + BusinessRoles::COMMERCIALE
pour detecter le role metier ; le code de role sera seede par ERP-74 et
reutilise par ERP-59/60. RG-1.04 reste dormante tant qu'aucun user ne porte
ce role.
Coordination stack :
- chaines de permission commercial.clients.* referencees ici, declarees en
ERP-59 (tests RBAC complets en ERP-60)
- config globale de pagination (itemsPerPage client, max 50) portee par ERP-72
- referentiels comptables (PaymentType/Bank/...) exposes en ERP-56
Tests : 31 tests Commercial (integration admin sur les regles metier + unitaires
sur le gating, RG-1.04/1.12/1.13 et le context builder). Suite complete verte
(339 tests).
Entites metier (Client, ClientContact, ClientAddress, ClientRib) avec
#[Auditable] + Timestampable/Blamable, et 4 referentiels comptables statiques
(TvaMode, PaymentDelay, PaymentType, Bank). 8 repositories interfaces + impl
Doctrine. Aucun ApiResource (Provider/Processor = ERP-55).
- Client : 2 FK auto-referentes distributor/broker (mutuellement exclusives,
CHECK en base), M2M categories, FK referentiels comptables, groupes de
serialisation par onglet. Pas de #[ORM\UniqueConstraint] : unicite du nom de
societe portee par l'index partiel Postgres (decision Q4).
- ClientRib : tous les champs audites, aucun #[AuditIgnore] sur iban/bic
(decision 29/05, audit admin-only).
- M2M Category via le contrat Shared CategoryInterface + resolve_target_entities
(regle n°1, pas d'import inter-modules) ; sites via SiteInterface.
- CommercialReferentialFixtures : re-seed idempotent des 4 referentiels (sinon
vides apres db-reset car desormais tables mappees, purgees par les fixtures).
- Referentiels whitelistes dans EntitiesAreTimestampableBlamableTest::EXCLUDED.
- doctrine.yaml : mapping ORM du module Commercial + resolve CategoryInterface.
- ColumnCommentsCatalog : ajout des colonnes M1 (chemin schema:update/test) ;
migration retrofit Version20260528120000 filtree sur les tables existantes
pour ne pas casser sur les tables des modules crees plus tard.
- makefile test-db-setup : recreation de l'index partiel uq_client_company_name_active.
Refs ERP-54.