feat(catalog) : ERP-201 — référentiel StorageType exposé (filtre site) + seed Figma + catégories PRODUIT #152

Closed
matthieu wants to merge 1 commits from feat/erp-201-storage-type-expose-seed into feat/erp-200-product-provider-processor
Owner

Stack sur ERP-200 (base = feat/erp-200-product-provider-processor).

ERP-201 (1.5) — Référentiel StorageType + seeds (M6)

Endpoint GET /api/storage_types (lecture seule)

  • StorageTypeProvider : tri label ASC, filtre ?siteId[]= (sous-requête EXISTS corrélée, RG-6.06 — types dispo sur ≥ 1 site passé), pagination Hydra + échappatoire ?pagination=false (référentiel borné, alimente le multi-select).
  • createListQueryBuilder(array $siteIds) ajouté au repository (interface + impl Doctrine).
  • Provider câblé sur GetCollection + Get (sécurité catalog.products.view).

Seeds (fixtures idempotentes par lookup code)

  • StorageTypeFixtures : 10 types Figma (node 1503-34285) — BOISSEAU, BOISSEAU_DOSAGE, CASE, CELLULE, CONTAINER, CUVE_MELASSE, STOCKAGE_BIG_BAG, STOCKAGE_PALETTE, TAS, ZONEPROVISOIRE (HP-M6-02), rattachés aux 3 sites (86/17/82) via le contrat Shared SiteProviderInterface (pas d'import inter-module). Tourne dans tous les envs (référentiel).
  • CategoryTypeFixtures : ajout du type PRODUIT (réaligne dev/test sur le seed de la migration ERP-198).
  • CategoryFixtures : 4 catégories PRODUIT de démo (Céréales, Oléagineux, Aliments du bétail, Engrais — dev only).

Fix dette ERP-198/199 (bloquant)

product.states mappé en jsonb (options: ['jsonb' => true]) pour coller à la colonne JSONB de la migration. Sans ça, schema:update tentait ALTER states TYPE JSON → cassait le CHECK jsonb_array_lengthmake db-reset / test-db-setup en échec.

Vérifications

  • make db-reset — fixtures chargées, données vérifiées en SQL (10 types × 3 sites, 4 catégories PRODUIT).
  • make test 873 tests (le seul échec transitoire UploadedDocumentApiTest = permissions var/ après recréation des containers, corrigé via chown, sans rapport).
  • make php-cs-fixer-allow-risky
  • Filtre ?siteId[]= couvert fonctionnellement en ERP-203.
Stack sur ERP-200 (base = `feat/erp-200-product-provider-processor`). ## ERP-201 (1.5) — Référentiel StorageType + seeds (M6) ### Endpoint `GET /api/storage_types` (lecture seule) - **StorageTypeProvider** : tri `label ASC`, filtre **`?siteId[]=`** (sous-requête EXISTS corrélée, RG-6.06 — types dispo sur ≥ 1 site passé), pagination Hydra + échappatoire **`?pagination=false`** (référentiel borné, alimente le multi-select). - `createListQueryBuilder(array $siteIds)` ajouté au repository (interface + impl Doctrine). - Provider câblé sur `GetCollection` + `Get` (sécurité `catalog.products.view`). ### Seeds (fixtures idempotentes par lookup `code`) - **StorageTypeFixtures** : 10 types Figma (node 1503-34285) — `BOISSEAU`, `BOISSEAU_DOSAGE`, `CASE`, `CELLULE`, `CONTAINER`, `CUVE_MELASSE`, `STOCKAGE_BIG_BAG`, `STOCKAGE_PALETTE`, `TAS`, `ZONE` — **PROVISOIRE** (HP-M6-02), rattachés aux 3 sites (86/17/82) via le contrat Shared `SiteProviderInterface` (pas d'import inter-module). Tourne dans tous les envs (référentiel). - **CategoryTypeFixtures** : ajout du type `PRODUIT` (réaligne dev/test sur le seed de la migration ERP-198). - **CategoryFixtures** : 4 catégories PRODUIT de démo (Céréales, Oléagineux, Aliments du bétail, Engrais — dev only). ### Fix dette ERP-198/199 (bloquant) `product.states` mappé en **jsonb** (`options: ['jsonb' => true]`) pour coller à la colonne JSONB de la migration. Sans ça, `schema:update` tentait `ALTER states TYPE JSON` → cassait le CHECK `jsonb_array_length` → **make db-reset / test-db-setup en échec**. ### Vérifications - `make db-reset` ✅ — fixtures chargées, **données vérifiées en SQL** (10 types × 3 sites, 4 catégories PRODUIT). - `make test` ✅ **873 tests** (le seul échec transitoire `UploadedDocumentApiTest` = permissions `var/` après recréation des containers, corrigé via `chown`, sans rapport). - `make php-cs-fixer-allow-risky` ✅ - Filtre `?siteId[]=` couvert fonctionnellement en **ERP-203**.
matthieu added 1 commit 2026-06-25 09:42:05 +00:00
Endpoint StorageType (lecture seule) :
- StorageTypeProvider : tri label ASC, filtre ?siteId[]= (EXISTS corrélé, RG-6.06),
  pagination Hydra + échappatoire ?pagination=false (référentiel borné) ;
- createListQueryBuilder ajouté au repository (interface + impl) ;
- provider câblé sur GetCollection + Get de l'entité StorageType.

Seed (fixtures idempotentes par lookup code, miroir CategoryTypeFixtures) :
- StorageTypeFixtures : 10 types Figma (PROVISOIRE HP-M6-02), rattachés aux 3 sites
  (86/17/82) via le contrat Shared SiteProviderInterface (pas d'import inter-module) ;
- CategoryTypeFixtures : ajout du type PRODUIT (réaligne dev/test sur le seed migration ERP-198) ;
- CategoryFixtures : 4 catégories PRODUIT de démo (Céréales, Oléagineux, Aliments du bétail, Engrais).

Fix dette ERP-198/199 : mapping ORM de product.states aligné sur la colonne JSONB
de la migration (options jsonb=true). Sans ça, schema:update tentait ALTER states
TYPE JSON et cassait le CHECK jsonb_array_length -> make db-reset / test-db-setup en échec.

make db-reset OK (fixtures idempotentes, données vérifiées), make test vert (873), php-cs-fixer OK.
matthieu added the backM6-Produittype/feat labels 2026-06-25 09:42:14 +00:00
Author
Owner

Review back — ERP-201 (référentiel StorageType exposé + seed), read-only.

Périmètre : GET /api/storage_types + filtre ?siteId[], seed Figma, catégories PRODUIT.

Vérifié conforme :

  • StorageTypeProvider paginé (Paginator ORM) + ?pagination=false (échappatoire select d'un référentiel borné) — pas d'array brut.
  • Filtre ?siteId[] en EXISTS corrélé : ne tronque pas la collection sites embarquée du produit.
  • is_granted('catalog.products.view') sur le référentiel (servant le formulaire produit).
  • Seed CategoryType PRODUIT + catégories produit, select filtré ?typeCode=PRODUIT (RG-6.05).

Verdict : aucun retour obligatoire.

**Review back — ERP-201 (référentiel StorageType exposé + seed), read-only.** Périmètre : `GET /api/storage_types` + filtre `?siteId[]`, seed Figma, catégories PRODUIT. Vérifié conforme : - `StorageTypeProvider` paginé (Paginator ORM) + `?pagination=false` (échappatoire select d'un référentiel borné) — pas d'array brut. - Filtre `?siteId[]` en EXISTS corrélé : ne tronque pas la collection `sites` embarquée du produit. - `is_granted('catalog.products.view')` sur le référentiel (servant le formulaire produit). - Seed `CategoryType` PRODUIT + catégories produit, select filtré `?typeCode=PRODUIT` (RG-6.05). Verdict : ✅ aucun retour obligatoire.
Author
Owner

Review M6 « Produit » — relecture croisée (couche données + couche application) sur le diff cumulé develop…HEAD.

Verdict : 0 bloquant, 0 important.

  • Garde-fous archi verts : COMMENT ON COLUMN, Timestampable/Blamable, Auditable + i18n, pagination (règle absolue n°13), contraintes Assert\* en FR.
  • RBAC 3 miroirs alignés (sidebar / personas / SeedE2ECommand).
  • Export : priority:1 + #[IsGranted('catalog.products.view')], mêmes filtres que la liste — conforme.
  • 119 tests Catalog + garde-fous archi verts en isolation (BDD fraîche).

Nits relevés (non bloquants) :

  • product.states : DEFAULT '[]'::jsonb contredisait le CHECK (jsonb_array_length(states) >= 1) (default mort, jamais atteignable) → corrigé (commit 30e7839).
  • ProductExportControllerTest : le tearDown réutilisait la constante des category-types (TEST_CATEGORY_TYPE_PREFIX) pour purger des storage-types → constante dédiée TEST_STORAGE_PREFIX (commit 30e7839).
  • Import Site (cross-module) du controller utilisé seulement dans un commentaire @var ; DQL p.id != :id au lieu de <> : cosmétiques, laissés tels quels.
  • Provider ?pagination=false renvoyant un array : conforme (pattern établi ClientProvider/SupplierProvider, échappatoire documentée pour alimenter les selects).
**Review M6 « Produit »** — relecture croisée (couche données + couche application) sur le diff cumulé `develop…HEAD`. **Verdict : 0 bloquant, 0 important.** - Garde-fous archi verts : COMMENT ON COLUMN, Timestampable/Blamable, Auditable + i18n, pagination (règle absolue n°13), contraintes `Assert\*` en FR. - RBAC 3 miroirs alignés (sidebar / personas / SeedE2ECommand). - Export : `priority:1` + `#[IsGranted('catalog.products.view')]`, mêmes filtres que la liste — conforme. - 119 tests Catalog + garde-fous archi verts en isolation (BDD fraîche). **Nits relevés (non bloquants) :** - `product.states` : `DEFAULT '[]'::jsonb` contredisait le `CHECK (jsonb_array_length(states) >= 1)` (default mort, jamais atteignable) → corrigé (commit `30e7839`). - `ProductExportControllerTest` : le `tearDown` réutilisait la constante des category-types (`TEST_CATEGORY_TYPE_PREFIX`) pour purger des storage-types → constante dédiée `TEST_STORAGE_PREFIX` (commit `30e7839`). - Import `Site` (cross-module) du controller utilisé seulement dans un commentaire `@var` ; DQL `p.id != :id` au lieu de `<>` : cosmétiques, laissés tels quels. - Provider `?pagination=false` renvoyant un `array` : conforme (pattern établi `ClientProvider`/`SupplierProvider`, échappatoire documentée pour alimenter les selects).
Author
Owner

Consolidée dans #154 : la pile M6 a été reciblée sur develop en une seule MR pour un CI unique. Commits intégralement inclus dans #154 — fermée sans merge individuel.

Consolidée dans #154 : la pile M6 a été reciblée sur `develop` en une seule MR pour un CI unique. Commits intégralement inclus dans #154 — fermée sans merge individuel.
matthieu closed this pull request 2026-06-25 12:36:08 +00:00

Pull request closed

Sign in to join this conversation.