Commit Graph

5 Commits

Author SHA1 Message Date
Matthieu 027e80cc4b test(commercial) : cover RG-1.01..1.29 except role-gated (M1) 2026-06-01 16:50:05 +02:00
Matthieu 9f3037c5c4 feat(commercial) : add clients XLSX export endpoint 2026-06-01 16:18:23 +02:00
Matthieu c21bfea7f6 feat(commercial) : add client sub-resources processors (contacts/addresses/ribs)
Expose les sous-ressources Contacts / Adresses / RIB du repertoire clients
(M1, spec § 4.5) :

- 3 Processors dedies (ClientContactProcessor, ClientAddressProcessor,
  ClientRibProcessor) : normalisation serveur reutilisant ClientFieldNormalizer
  (RG-1.19 capitalize, RG-1.20 telephones chiffres, RG-1.21 emails/billingEmail
  lowercase) + regles metier.
- Operations API Platform :
  - POST /api/clients/{id}/contacts|addresses, PATCH/DELETE /api/client_contacts|addresses/{id}
    (security commercial.clients.manage)
  - POST /api/clients/{id}/ribs, PATCH/DELETE /api/client_ribs/{id}
    (security commercial.clients.accounting.manage)
  - GET item par sous-ressource (lecture unitaire) ; pas de GET collection
    autonome (lecture via le parent, non concernee par la pagination ERP-72).
- Regles de gestion :
  - RG-1.13 : DELETE du dernier RIB d'un client en reglement LCR -> 409.
  - RG-1.14 : DELETE du dernier contact d'un client -> 409 (completude front au M1).
  - RG-1.05 : prenom OU nom du contact obligatoire -> 422.
- Validations deja portees par l'entite et desormais exercees : Assert\Count(min:1)
  sur ClientAddress.sites (RG-1.10), Assert\Regex code postal (RG-1.09),
  Assert\Iban / Assert\Bic sur ClientRib.
- SiteReferenceDenormalizer : resout les IRIs /api/sites vers SiteInterface
  (meme pattern que CategoryReferenceDenormalizer, sans import cross-module).
- Ajout de symfony/intl, requis par Assert\Bic.

Tests : ClientSubResourceApiTest (13 cas) couvrant CRUD, normalisation,
RG-1.13/1.14, gating 403 sur client_ribs sans accounting.manage. Suite back
complete au vert (383 tests).
2026-06-01 16:18:23 +02:00
Matthieu f29587f113 feat(commercial) : expose accounting referentials read-only API
Expose TvaMode, PaymentDelay, PaymentType et Bank en lecture seule
(GetCollection + Get), security commercial.clients.view au niveau
operations + ressource. Aucune ecriture declaree -> POST/PATCH/DELETE
renvoient 405.

Tri par defaut position ASC puis label ASC (spec M1 § 4.7). Pagination
serveur conservee (ERP-72) avec paginationClientEnabled pour activer
l'echappatoire ?pagination=false (alimenter un select sans pagination).

Endpoints : GET /api/tva_modes, /api/payment_delays, /api/payment_types,
/api/banks. Tests fonctionnels : 200 + seed, tri position/label,
405 ecritures, 403 sans permission, 401 anonyme, pagination toggle.
2026-06-01 16:18:23 +02:00
Matthieu d3d00425f7 feat(commercial) : add Client API Platform provider + processor + business rules
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).
2026-06-01 14:50:45 +02:00