feat(commercial) : export XLSX fournisseurs (ERP-91) (#70)
Auto Tag Develop / tag (push) Successful in 7s

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.

---------

Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #70
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
This commit was merged in pull request #70.
This commit is contained in:
2026-06-08 07:48:59 +00:00
committed by admin malio
parent 58cbfe4437
commit 97459e798f
5 changed files with 729 additions and 0 deletions
@@ -102,6 +102,31 @@ class DoctrineSupplierRepository extends ServiceEntityRepository implements Supp
;
}
public function hydrateContacts(array $suppliers): void
{
$ids = [];
foreach ($suppliers as $supplier) {
$id = $supplier->getId();
if (null !== $id) {
$ids[] = $id;
}
}
if ([] === $ids) {
return;
}
// Une seule requete IN bornee : remplit la collection `contacts` des MEMES
// instances Supplier (identity map). Tri par position pour que le « contact
// principal » (plus petit position) soit deterministe a l'export (§ 4.6).
$this->createQueryBuilder('s')
->leftJoin('s.contacts', 'sc')->addSelect('sc')
->where('s.id IN (:ids)')->setParameter('ids', $ids)
->orderBy('sc.position', 'ASC')
->getQuery()
->getResult()
;
}
/**
* Recherche fuzzy insensible a la casse sur companyName ET sur les contacts
* lies (firstName / lastName / email) — decision D1, refonte-contact (§ 4.1).