feat(catalog) : ERP-202 — export XLSX du catalogue produits #153
Reference in New Issue
Block a user
Delete Branch "feat/erp-202-product-export-xlsx"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
ERP-202 (1.6) — Export XLSX des produits
Endpoint
GET /api/products/export.xlsx(controller Symfony custom, miroirClientExportController/CarrierExportController).Contenu
priority: 1pour éviter le conflit API Platform/api/products/{id}.{_format};#[IsGranted('catalog.products.view')].code), Nom, États (Achat/Vendu/Autre joints), Catégorie, Sites, Types de stockage, Fabriqué, Contient mélasse.ProductProvider) :?search,?categoryId/?categoryCode,?state,?siteId[]. Produits soft-deleted toujours exclus (RG-6.09, § 2.7).SpreadsheetExporterInterface(PhpSpreadsheet) ;Content-Typexlsx +Content-Disposition: attachment.Tests
ProductExportControllerTest(7 tests, 51 assertions) : en-têtes + ligne de données, exclusion soft-delete, filtres?search/?state, peuplement de toutes les colonnes métier, 403 sans permission, 401 anonyme.Note — étape 4 du ticket (whitelist
CollectionsArePaginatedTest::EXCLUDED)Non appliquée car non pertinente : ce garde-fou ne scanne que les opérations
GetCollectiondes#[ApiResource]. L'export est un controller Symfony custom, jamais évalué par ce test — etEXCLUDEDest vide alors que les exports Client/Provider/Carrier existent déjà. Ajouter une entrée serait du code mort. Suite verte sans whitelist.Vérifications
make test FILES=tests/Module/Catalog/Api/ProductExportControllerTest.php→ OK (7/51)make test FILES="tests/Architecture tests/Module/Catalog"→ OK (105/1015)make php-cs-fixer-check→ conformeReview back — ERP-202 (export XLSX), read-only.
Périmètre :
GET /api/products/export.xlsx, export complet filtres appliqués.Vérifié conforme :
/api/avecpriority: 1sur la route (évite le conflit API Platform{id}.{_format}).#[IsGranted('catalog.products.view')].SpreadsheetExporterInterface(Shared) — pas d'import inter-module.ProductExportControllerTest(extendsAbstractCatalogApiTestCase, autonome) : scope + colonnes + enum états.Verdict : ✅ aucun retour obligatoire.
Review M6 « Produit » — relecture croisée (couche données + couche application) sur le diff cumulé
develop…HEAD.Verdict : 0 bloquant, 0 important.
Assert\*en FR.priority:1+#[IsGranted('catalog.products.view')], mêmes filtres que la liste — conforme.Nits relevés (non bloquants) :
product.states:DEFAULT '[]'::jsonbcontredisait leCHECK (jsonb_array_length(states) >= 1)(default mort, jamais atteignable) → corrigé (commit30e7839).ProductExportControllerTest: letearDownréutilisait la constante des category-types (TEST_CATEGORY_TYPE_PREFIX) pour purger des storage-types → constante dédiéeTEST_STORAGE_PREFIX(commit30e7839).Site(cross-module) du controller utilisé seulement dans un commentaire@var; DQLp.id != :idau lieu de<>: cosmétiques, laissés tels quels.?pagination=falserenvoyant unarray: conforme (pattern établiClientProvider/SupplierProvider, échappatoire documentée pour alimenter les selects).Consolidée dans #154 : la pile M6 a été reciblée sur
developen une seule MR pour un CI unique. Commits intégralement inclus dans #154 — fermée sans merge individuel.Pull request closed