feat(commercial) : export XLSX fournisseurs (ERP-91) #70

Merged
malio merged 1 commits from feature/ERP-91-export-xlsx-m2 into develop 2026-06-08 07:48:59 +00:00
Owner

Export XLSX du répertoire fournisseurs (spec-back M2 § 4.6), jumeau de l'export client M1. Stack : cible feature/ERP-90-rbac-fournisseurs (ERP-84→91 non encore mergés dans develop).

Périmètre

  • SupplierExportController avec #[Route(priority: 1)] (anti-conflit API Platform {id}) + is_granted('commercial.suppliers.view').
  • Mêmes filtres que la liste (includeArchived/archivedOnly/search/categoryCode/siteId) via createListQueryBuilder() partagé avec le SupplierProvider ; non archivés par défaut.
  • Colonnes : Nom fournisseur, Contact principal (Nom + Prénom du SupplierContact de plus petit position, ERP-106), Tél principal, Tél secondaire, Email, Catégories (CSV), Sites (CSV), SIREN omis sans accounting.view, Date de création.
  • Fichier repertoire-fournisseurs-{YYYYMMDD}.xlsx.
  • hydrateContacts() ajouté au repository : chargement batché des contacts en une requête IN (anti-N+1). Méthode dédiée à l'export — la liste paginée n'embarque pas les contacts, on ne lui impose pas ce coût.

Correctif hors-périmètre (signalé)

Tables supplier* ajoutées à ColumnCommentsCatalog : leurs COMMENT ON COLUMN (posés par la migration ERP-85) étaient dropés par le schema:update --force du test-db-setup et non restaurés (catalogue = source rejouée par app:apply-column-comments), cassant ColumnsHaveSqlCommentTest dès un re-setup de la base de test. Trou laissé par ERP-85/86, vert tant que personne ne re-setup la base.

Tests

  • SupplierExportControllerTest (9 cas) : réponse/filename, exclusion archives, filtre search, contact principal, colonnes catégories/sites, gating SIREN avec/sans accounting.view, 403, 401.
  • make test : 508 tests / 2035 assertions, 0 échec. php-cs-fixer clean.
Export XLSX du répertoire fournisseurs (spec-back M2 § 4.6), jumeau de l'export client M1. **Stack : cible `feature/ERP-90-rbac-fournisseurs`** (ERP-84→91 non encore mergés dans develop). ## Périmètre - **`SupplierExportController`** avec `#[Route(priority: 1)]` (anti-conflit API Platform `{id}`) + `is_granted('commercial.suppliers.view')`. - Mêmes filtres que la liste (`includeArchived`/`archivedOnly`/`search`/`categoryCode`/`siteId`) via `createListQueryBuilder()` partagé avec le `SupplierProvider` ; non archivés par défaut. - Colonnes : Nom fournisseur, **Contact principal** (Nom + Prénom du `SupplierContact` de plus petit `position`, ERP-106), Tél principal, Tél secondaire, Email, Catégories (CSV), Sites (CSV), **SIREN omis sans `accounting.view`**, Date de création. - Fichier `repertoire-fournisseurs-{YYYYMMDD}.xlsx`. - **`hydrateContacts()`** ajouté au repository : chargement batché des contacts en une requête `IN` (anti-N+1). Méthode dédiée à l'export — la liste paginée n'embarque pas les contacts, on ne lui impose pas ce coût. ## Correctif hors-périmètre (signalé) Tables `supplier*` ajoutées à `ColumnCommentsCatalog` : leurs `COMMENT ON COLUMN` (posés par la migration ERP-85) étaient dropés par le `schema:update --force` du `test-db-setup` et non restaurés (catalogue = source rejouée par `app:apply-column-comments`), cassant `ColumnsHaveSqlCommentTest` dès un re-setup de la base de test. Trou laissé par ERP-85/86, vert tant que personne ne re-setup la base. ## Tests - `SupplierExportControllerTest` (9 cas) : réponse/filename, exclusion archives, filtre search, contact principal, colonnes catégories/sites, gating SIREN avec/sans `accounting.view`, 403, 401. - `make test` : 508 tests / 2035 assertions, 0 échec. `php-cs-fixer` clean.
matthieu added the backM2-Fournisseurtype/feat labels 2026-06-05 12:58:00 +00:00
Author
Owner

Review MR #70 — remarques (non bloquantes, cosmétiques)

Verdict : PR propre, jumeau fidèle de l'export client M1. Tests verts (SupplierExportControllerTest 9/9, ColumnsHaveSqlCommentTest OK), catalogue ColumnCommentsCatalog vérifié colonne par colonne contre la migration Version20260605130000. Rien à corriger impérativement.

Deux remarques mineures :

  1. Tri redondant dans hydrateContacts (DoctrineSupplierRepository.php:124) — le ORDER BY sc.position ASC de la requête est doublé par le usort() de principalContact() (SupplierExportController.php:192). Le commentaire « pour que le contact principal soit déterministe à l'export » est un peu trompeur : c'est le usort qui décide réellement. On peut retirer l'orderBy (travail DB inutile) ou retirer le usort.

  2. Contact principal non déterministe à position égale (SupplierExportController.php:192-197) — ni la requête ni le usort n'ont de critère secondaire (ex. id). Si deux contacts partagent la même position, le contact principal retenu est arbitraire d'un run à l'autre. Cas limite (positions normalement distinctes), faible sévérité — un tiebreaker $a->getPosition() <=> $b->getPosition() ?: $a->getId() <=> $b->getId() lèverait le doute.

**Review MR #70 — remarques (non bloquantes, cosmétiques)** Verdict : PR propre, jumeau fidèle de l'export client M1. Tests verts (`SupplierExportControllerTest` 9/9, `ColumnsHaveSqlCommentTest` OK), catalogue `ColumnCommentsCatalog` vérifié colonne par colonne contre la migration `Version20260605130000`. Rien à corriger impérativement. Deux remarques mineures : 1. **Tri redondant dans `hydrateContacts`** (`DoctrineSupplierRepository.php:124`) — le `ORDER BY sc.position ASC` de la requête est doublé par le `usort()` de `principalContact()` (`SupplierExportController.php:192`). Le commentaire « pour que le contact principal soit déterministe à l'export » est un peu trompeur : c'est le `usort` qui décide réellement. On peut retirer l'`orderBy` (travail DB inutile) **ou** retirer le `usort`. 2. **Contact principal non déterministe à `position` égale** (`SupplierExportController.php:192-197`) — ni la requête ni le `usort` n'ont de critère secondaire (ex. `id`). Si deux contacts partagent la même `position`, le contact principal retenu est arbitraire d'un run à l'autre. Cas limite (positions normalement distinctes), faible sévérité — un tiebreaker `$a->getPosition() <=> $b->getPosition() ?: $a->getId() <=> $b->getId()` lèverait le doute.
malio changed target branch from feature/ERP-90-rbac-fournisseurs to develop 2026-06-08 07:48:44 +00:00
matthieu added 1 commit 2026-06-08 07:48:51 +00:00
feat(commercial) : export XLSX fournisseurs (SupplierExportController, SIREN gaté accounting.view) (ERP-91)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 2m3s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m7s
c6a0a51810
Export XLSX du répertoire fournisseurs (spec § 4.6), jumeau de l'export client M1.

- SupplierExportController avec #[Route(priority: 1)] (anti-conflit API Platform {id}),
  is_granted('commercial.suppliers.view'). Mêmes filtres que la liste
  (includeArchived/archivedOnly/search/categoryCode/siteId) via createListQueryBuilder()
  partagé avec le SupplierProvider ; non archivés par défaut.
- Colonnes : Nom, Contact principal (SupplierContact de plus petit position — ERP-106),
  Tél principal/secondaire, Email, Catégories (CSV), Sites (CSV), SIREN (omis sans
  accounting.view), Date de création.
- hydrateContacts() ajouté au repository (chargement batché des contacts en une requête
  IN, anti-N+1) — méthode dédiée à l'export, la liste paginée n'embarque pas les contacts.
- Tables supplier* ajoutées à ColumnCommentsCatalog : leurs COMMENT (posés par la
  migration ERP-85) étaient dropés par le schema:update --force du test-db-setup et non
  restaurés, cassant ColumnsHaveSqlCommentTest dès un re-setup de la base de test.
- Test fonctionnel SupplierExportControllerTest (9 cas).
matthieu force-pushed feature/ERP-91-export-xlsx-m2 from e917c413dc to c6a0a51810 2026-06-08 07:48:51 +00:00 Compare
malio merged commit 97459e798f into develop 2026-06-08 07:48:59 +00:00
malio deleted branch feature/ERP-91-export-xlsx-m2 2026-06-08 07:48:59 +00:00
Sign in to join this conversation.