RG inter-champs via Assert\Callback->atPath() sur l'entite Supplier (decision
figee ERP-89), pour un 422 a propertyPath consommable par extractApiViolations :
- RG-2.10 : categories de type FOURNISSEUR (supplier.categories) -> atPath('categories')
- RG-2.07 : VIREMENT impose une banque -> atPath('bank')
- RG-2.08 : LCR impose au moins un RIB -> atPath('ribs')
RG-2.03 (completude Information pour le role Commerciale, detection back via
BusinessRoleAwareInterface) portee par SupplierInformationCompletenessValidator,
invoque par le SupplierProcessor.
Tests : SupplierValidationTest (Callbacks 2.07/2.08/2.10),
SupplierInformationCompletenessValidatorTest, SupplierProcessorTest (RG-2.03).
Ajoute les opérations API Platform et les Processors d'écriture des
sous-collections du fournisseur (POST/PATCH/DELETE + GET unitaire) :
- SupplierContactProcessor : rattachement parent, normalisation serveur
(RG-2.12), validation RG-2.04 (prénom OU nom). DELETE libre (RG-2.13).
- SupplierAddressProcessor : rattachement parent. RG-2.05/2.06/2.09 portées
par les contraintes d'entité ; RG-2.10 (catégorie type FOURNISSEUR) via
Assert\Callback validateCategoryType.
- SupplierRibProcessor : rattachement parent, RG-2.08 (refus DELETE du
dernier RIB sous LCR -> 409).
Security différenciée : contacts/adresses -> commercial.suppliers.manage ;
ribs -> commercial.suppliers.accounting.manage (+ .view pour le GET).
POST en read:false (parent rattaché manuellement, 404 si absent) — parade
NonUniqueResult du M1. Messages FR (ERP-107) + propertyPath aligné (ERP-101).
Branche les operations API du repertoire fournisseurs (M2), jumelles du M1 :
- SupplierProvider : liste paginee (Paginator ORM), exclusion archives +
soft-deletes par defaut, filtres includeArchived/categoryCode/siteId/search,
echappatoire ?pagination=false, item 404 si soft-delete (RG-2.17).
- SupplierProcessor : normalisation companyName, archivage isArchived/archivedAt
(RG-2.14/2.15), gating fin accounting/manage en mode strict (403 sur tout le
payload hors-permission, RG-2.16), 409 doublon companyName + conflit de
restauration (RG-2.11).
- SupplierReadGroupContextBuilder : ajoute supplier:read:accounting au contexte
de lecture si accounting.view (gating compta + RIB par omission de cle). Un
Provider ne peut pas influencer les groupes de serialisation : c'est le point
d'extension idiomatique, miroir de ClientReadGroupContextBuilder.
- SupplierFieldNormalizer : normalisation serveur (RG-2.12).
- Supplier : ajout #[ApiResource] (GetCollection/Get/Post/Patch) wirant
Provider/Processor.
Validators metier (RG-2.03/2.07/2.08/2.10) = ticket suivant.
make test vert (483/483), php-cs-fixer applique.
Entités jumelles du M1 client, mapping ORM aligné sur la migration ERP-85,
sans contact inline (ERP-106) :
- Supplier (#[Auditable] + Timestampable/Blamable) : formulaire principal,
Information (+ volumeForecast), Comptabilité (FK référentiels M1), archivage,
soft-delete préparé. Catégories M2M via CategoryInterface (règle n°1).
- SupplierContact / SupplierAddress (enum addressType, bennes, triageProvider)
/ SupplierRib.
- Repositories : interfaces Domain + impls Doctrine. DoctrineSupplierRepository
porte les fetch-joins anti-N+1 de la liste (categories + addresses.sites en
2 passes, pattern ERP-100) et les filtres (search companyName + contacts,
categoryCode, siteId, archivage).
Contrat de sérialisation (RETEX M1, 3 maillons posés sur l'entité) :
read-groups sur les propriétés, getters isArchived/isTriageProvider avec
SerializedName, embed contacts/addresses (supplier:item:read) et ribs
(supplier:read:accounting). L'#[ApiResource] + Provider/Processor sont au
ticket suivant (ERP-87).
Validation FR (ERP-107) : messages FR sur toutes les contraintes, Length(max)
calé sur les colonnes. Garde-fou EntityConstraintsHaveFrenchMessageTest étendu
(Assert\Choice + whitelist addressType/postalCode). Clés i18n audit des 4
entités ajoutées.
make test : 483/483 OK.
Recree le CategoryType FOURNISSEUR (unifie sur CLIENT par ERP-78) et implemente
un vrai filtre ?typeCode= sur GET /api/categories (inexistant en prod).
- CategoryProvider lit ?typeCode= depuis les filtres (meme pattern que
includeDeleted) et le passe au repository ; naltere pas ?pagination=false.
- DoctrineCategoryRepository::createListQueryBuilder joint le CategoryType et
filtre sur son code (compatible Paginator ORM fetchJoinCollection).
- Migration racine Version20260605120000 : seed du type FOURNISSEUR en
ON CONFLICT + 5 categories de demo (Negociant, Cooperative, Producteur,
Grossiste, Importateur) en NOT EXISTS. Aucune colonne creee.
- CategoryTypeFixtures / CategoryFixtures etendus a FOURNISSEUR (idempotent,
survit a make db-reset).
- Test CategoryTypeCodeFilterTest : filtre exclusif, compat pagination Hydra,
code inexistant -> liste vide.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.