feat(technique) : module Technique + taxonomie categories prestataires
Cree le nouveau module Technique (pole distinct du Commercial) prerequis du M3 repertoire prestataires : - TechniqueModule (ID=technique, REQUIRED=false) + 5 permissions RBAC technique.providers.* (view / manage / accounting.view / accounting.manage / archive), declarees pour app:sync-permissions. - Activation dans config/modules.php + layer front frontend/modules/technique/. - Seed taxonomie : nouveau CategoryType PRESTATAIRE + 3 categories (Maintenance industrielle, Nettoyage, Transport) via migration idempotente (ON CONFLICT / NOT EXISTS, jonction M2M category_category_type) ET fixtures CategoryType/Category (survivent au purger db-reset). - Tests : structure du module (5 permissions figees) + filtre GET /api/categories?typeCode=PRESTATAIRE. Inclut la spec back/front M3 et le RETEX M1.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Catalog\Api;
|
||||
|
||||
use App\Module\Catalog\Domain\Entity\CategoryType;
|
||||
|
||||
/**
|
||||
* Tests du seed de la taxonomie PRESTATAIRE (M3 1.1) cote API.
|
||||
*
|
||||
* Le multi-select « Categorie » du prestataire (formulaire principal + adresse)
|
||||
* consomme `GET /api/categories?typeCode=PRESTATAIRE`. Ce test prouve que :
|
||||
* - le filtre `?typeCode=PRESTATAIRE` ne renvoie QUE les categories du type
|
||||
* PRESTATAIRE (aucune fuite de categorie d'un autre type) ;
|
||||
* - chaque membre renvoye porte bien le type PRESTATAIRE dans `categoryTypes`.
|
||||
*
|
||||
* NB : la base de test est purgee de toute categorie / type entre chaque test
|
||||
* (cf. AbstractCatalogApiTestCase::cleanupCatalogTestData), donc le type et les
|
||||
* categories PRESTATAIRE sont materialises ici (et non lus depuis le seed de la
|
||||
* migration / fixture, qui ne survit pas a la purge). On valide ainsi le contrat
|
||||
* du filtre sur le code reel `PRESTATAIRE`. La presence du seed apres un
|
||||
* `make db-reset` reel est, elle, verifiee par l'idempotence des fixtures.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class CategoryPrestataireSeedTest extends AbstractCatalogApiTestCase
|
||||
{
|
||||
/**
|
||||
* Categories de demonstration seedees par la migration / fixture PRESTATAIRE.
|
||||
*/
|
||||
private const array PROVIDER_CATEGORIES = [
|
||||
'Maintenance industrielle',
|
||||
'Nettoyage',
|
||||
'Transport',
|
||||
];
|
||||
|
||||
public function testTypeCodePrestataireReturnsOnlyProviderCategories(): void
|
||||
{
|
||||
$providerType = $this->getOrCreatePrestataireType();
|
||||
foreach (self::PROVIDER_CATEGORIES as $name) {
|
||||
$this->createCategory($name, $providerType);
|
||||
}
|
||||
|
||||
// Bruit : un type + une categorie d'un autre type ne doivent PAS fuiter.
|
||||
$noiseType = $this->createCategoryType('TEST_FOURNISSEUR', 'Test Fournisseur');
|
||||
$this->createCategory(self::TEST_CATEGORY_PREFIX.'noise', $noiseType);
|
||||
|
||||
$client = $this->createAdminClient();
|
||||
$response = $client->request('GET', '/api/categories?typeCode=PRESTATAIRE&pagination=false');
|
||||
self::assertSame(200, $response->getStatusCode());
|
||||
|
||||
$members = $response->toArray()['member'];
|
||||
$names = array_map(static fn (array $m): string => $m['name'], $members);
|
||||
sort($names);
|
||||
|
||||
$expected = self::PROVIDER_CATEGORIES;
|
||||
sort($expected);
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$names,
|
||||
'Le filtre ?typeCode=PRESTATAIRE doit ne renvoyer QUE les categories du type PRESTATAIRE.',
|
||||
);
|
||||
|
||||
// Chaque categorie remontee doit PORTER le type PRESTATAIRE.
|
||||
foreach ($members as $member) {
|
||||
self::assertContains('PRESTATAIRE', array_column($member['categoryTypes'], 'code'));
|
||||
}
|
||||
}
|
||||
|
||||
public function testTypeCodePrestataireKeepsHydraPagination(): void
|
||||
{
|
||||
$providerType = $this->getOrCreatePrestataireType();
|
||||
$this->createCategory('Maintenance industrielle', $providerType);
|
||||
|
||||
$client = $this->createAdminClient();
|
||||
$response = $client->request('GET', '/api/categories?typeCode=PRESTATAIRE');
|
||||
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::assertContains('PRESTATAIRE', array_column($member['categoryTypes'], 'code'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recupere le type PRESTATAIRE reel, ou le cree s'il est absent. Le code
|
||||
* `PRESTATAIRE` est seede par CategoryTypeFixtures (present en debut de suite),
|
||||
* mais le cleanup purge tous les `category_type` entre les tests : selon
|
||||
* l'ordre d'execution, le type peut donc exister ou non. Le get-or-create rend
|
||||
* le test robuste sans dependre du seed ni le dupliquer.
|
||||
*/
|
||||
private function getOrCreatePrestataireType(): CategoryType
|
||||
{
|
||||
$em = $this->getEm();
|
||||
$existing = $em->getRepository(CategoryType::class)->findOneBy(['code' => 'PRESTATAIRE']);
|
||||
|
||||
if ($existing instanceof CategoryType) {
|
||||
return $existing;
|
||||
}
|
||||
|
||||
return $this->createCategoryType('PRESTATAIRE', 'Prestataire');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user