feat(commercial) : filtres répertoire clients via drawer (recherche, catégories, sites, archivés)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m47s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m3s

Front :
- Bouton « Filtres » (à droite d'Ajouter) ouvrant un drawer accordion (façon
  audit-log) : Recherche, Catégories (multi), Sites (multi), Statut (archivés).
  État brouillon → appliqué, 100 % local. Compteur de filtres actifs sur le bouton.
- Suppression du toggle « Voir les archivés » (remplacé par le bool du drawer).
- Export et liste partagent les mêmes filtres.
- useClientsRepository redevient un simple wrapper de usePaginatedList.

Back (contrat liste partagé liste + export) :
- createListQueryBuilder : categoryCodes[] (OR), siteIds[] (clients ayant ≥1
  adresse sur le site), archivedOnly (archives seules, prioritaire sur
  includeArchived). search inchangé.
- ClientProvider + ClientExportController lisent les nouveaux params (valeur
  unique ou liste ?key[]=). Tests fonctionnels (catégories multi, site, archivés).
This commit is contained in:
2026-06-02 14:49:21 +02:00
parent e6ac130bf1
commit e986980d68
9 changed files with 542 additions and 98 deletions
@@ -16,21 +16,31 @@ interface ClientRepositoryInterface
/**
* Construit un QueryBuilder de liste pour le repertoire clients.
* - Exclut toujours les clients soft-deletes (deleted_at IS NOT NULL, RG-1.24).
* - Exclut les archives sauf si $includeArchived = true (RG-1.25).
* - Archivage (RG-1.25) :
* - $archivedOnly = true -> uniquement les archives (is_archived = true) ;
* - sinon $includeArchived = true -> actifs + archives (echappatoire) ;
* - sinon (defaut) -> uniquement les actifs (is_archived = false).
* $archivedOnly a la priorite sur $includeArchived.
* - Tri par defaut : companyName ASC (RG-1.26).
* - $search : recherche fuzzy insensible a la casse sur companyName +
* lastName + email (metacaracteres LIKE echappes). Ignore si null/vide.
* - $categoryCode : restreint aux clients possedant au moins une categorie
* du code donne (ERP-78 : filtrage par code de Category, plus par type).
* Ignore si null/vide.
* - $categoryCodes : restreint aux clients possedant au moins une categorie
* dont le code est dans la liste (OR — ERP-78). Liste vide = pas de filtre.
* - $siteIds : restreint aux clients ayant au moins une adresse rattachee a
* l'un des sites donnes (OR — RG-1.10). Liste vide = pas de filtre.
*
* Filtrage centralise ICI (et non dans les providers/controllers) pour que
* la liste paginee (ClientProvider) et l'export (ClientExportController)
* partagent strictement la meme logique de selection.
*
* @param list<string> $categoryCodes
* @param list<int> $siteIds
*/
public function createListQueryBuilder(
bool $includeArchived = false,
?string $search = null,
?string $categoryCode = null,
array $categoryCodes = [],
array $siteIds = [],
bool $archivedOnly = false,
): QueryBuilder;
}