feat(catalog) : taxonomie FOURNISSEUR (type + filtre ?typeCode= + seed) (ERP-84) (#63)
Auto Tag Develop / tag (push) Successful in 8s

## ERP-84 — Taxonomie FOURNISSEUR (Catalog)

Prérequis du multi-select « Catégorie » de l'écran Ajouter fournisseur (#94) et de #92.
Spec : `docs/specs/M2-suppliers/spec-back.md` § 2.4 + § 4.7.

### Contexte
ERP-78 avait unifié la taxonomie sur un **type unique CLIENT** ; `GET /api/categories?typeCode=FOURNISSEUR` renvoyait alors les catégories CLIENT (filtre **ignoré**, un seul `CategoryType`). Le filtre `?typeCode=` n'existait pas en prod.

### Changements
- **Filtre `?typeCode=` réel** sur `GET /api/categories` : `CategoryProvider` lit le filtre (même pattern que `includeDeleted`) et le passe à `DoctrineCategoryRepository::createListQueryBuilder`, qui joint le `CategoryType` et filtre sur son `code`. N'altère pas l'échappatoire `?pagination=false` ni la pagination Hydra.
- **CategoryType FOURNISSEUR recréé** : migration racine `Version20260605120000` (`INSERT … ON CONFLICT` pour le type + 5 catégories de démo en `NOT EXISTS` : Négociant, Coopérative, Producteur, Grossiste, Importateur). Aucune colonne créée → pas de `COMMENT ON COLUMN`.
- **Fixtures étendues** : `CategoryTypeFixtures` + `CategoryFixtures` seedent FOURNISSEUR de façon idempotente (survit à `make db-reset`).
- **Test** : `CategoryTypeCodeFilterTest` (filtre exclusif, compat pagination Hydra, code inexistant → liste vide).

### Vérifications
- `make php-cs-fixer-allow-risky` : clean.
- `make test` : **483 tests OK** (1844 assertions).
- Après `make db-reset` :
  - `/api/category_types` → `CLIENT` + `FOURNISSEUR`.
  - `?typeCode=FOURNISSEUR` → uniquement les 5 catégories FOURNISSEUR.
  - `?typeCode=CLIENT` → 11 catégories, type unique CLIENT.

### Critères d'acceptation
- [x] `CategoryType` FOURNISSEUR présent après `make db-reset`.
- [x] `?typeCode=FOURNISSEUR` ne renvoie QUE les catégories FOURNISSEUR.
- [x] Catégories fournisseurs seedées sous ce type.
- [x] `make test` vert.

---------

Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #63
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 #63.
This commit is contained in:
2026-06-08 06:57:32 +00:00
committed by admin malio
parent 786638a02f
commit 0b33bcb0f2
7 changed files with 287 additions and 50 deletions
@@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
namespace App\Tests\Module\Catalog\Api;
/**
* Tests du filtre `?typeCode=` sur GET /api/categories (ERP-84).
*
* Brique manquante avant le M2 : le filtre n'existait pas en prod (ERP-78 avait
* unifie sur un type unique CLIENT). Apres implementation :
* - `?typeCode=FOURNISSEUR` ne renvoie QUE les categories du type FOURNISSEUR ;
* - le filtre n'altere pas l'echappatoire `?pagination=false` ;
* - un code inexistant renvoie une liste vide (pas d'erreur).
*
* @internal
*/
final class CategoryTypeCodeFilterTest extends AbstractCatalogApiTestCase
{
public function testTypeCodeFilterReturnsOnlyMatchingType(): void
{
$clientType = $this->createCategoryType('TEST_CLIENT');
$supplierType = $this->createCategoryType('TEST_FOURNISSEUR');
$this->createCategory(self::TEST_CATEGORY_PREFIX.'client_one', $clientType);
$this->createCategory(self::TEST_CATEGORY_PREFIX.'supplier_one', $supplierType);
$this->createCategory(self::TEST_CATEGORY_PREFIX.'supplier_two', $supplierType);
$client = $this->createAdminClient();
$response = $client->request('GET', '/api/categories?typeCode=TEST_FOURNISSEUR&pagination=false');
self::assertSame(200, $response->getStatusCode());
$members = $response->toArray()['member'];
$names = array_map(fn (array $m): string => $m['name'], $members);
$testOnly = array_values(array_filter(
$names,
fn (string $n): bool => str_starts_with($n, self::TEST_CATEGORY_PREFIX),
));
sort($testOnly);
self::assertSame(
[
self::TEST_CATEGORY_PREFIX.'supplier_one',
self::TEST_CATEGORY_PREFIX.'supplier_two',
],
$testOnly,
'Le filtre ?typeCode= doit ne renvoyer QUE les categories du type demande.',
);
// Tous les types embarques doivent etre le type filtre.
foreach ($members as $member) {
self::assertSame('TEST_FOURNISSEUR', $member['categoryType']['code']);
}
}
public function testTypeCodeFilterWorksWithPagination(): void
{
$supplierType = $this->createCategoryType('TEST_FOURNISSEUR');
$this->createCategory(self::TEST_CATEGORY_PREFIX.'paginated', $supplierType);
$client = $this->createAdminClient();
// Sans ?pagination=false : on doit obtenir l'enveloppe Hydra paginee.
$response = $client->request('GET', '/api/categories?typeCode=TEST_FOURNISSEUR');
self::assertSame(200, $response->getStatusCode());
$data = $response->toArray();
self::assertArrayHasKey('totalItems', $data, 'Le filtre ne doit pas casser la pagination Hydra.');
self::assertArrayHasKey('member', $data);
foreach ($data['member'] as $member) {
self::assertSame('TEST_FOURNISSEUR', $member['categoryType']['code']);
}
}
public function testUnknownTypeCodeReturnsEmptyList(): void
{
$type = $this->createCategoryType('TEST_CLIENT');
$this->createCategory(self::TEST_CATEGORY_PREFIX.'lonely', $type);
$client = $this->createAdminClient();
$response = $client->request('GET', '/api/categories?typeCode=TEST_DOES_NOT_EXIST&pagination=false');
self::assertSame(200, $response->getStatusCode());
self::assertSame([], $response->toArray()['member']);
}
}