feat(technique) : module Technique + taxonomie categories prestataires
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 2m13s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m27s

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:
Matthieu
2026-06-12 09:23:08 +02:00
parent 7d8a633eee
commit 6ceef62056
11 changed files with 1795 additions and 3 deletions
@@ -17,7 +17,9 @@ use Symfony\Component\DependencyInjection\Attribute\Autowire;
* Fixtures dev/test du module Catalog : categories de demonstration rattachees
* a leur CategoryType. Le type CLIENT porte ~11 categories clients (refonte
* taxonomie ERP-78) ; le type FOURNISSEUR porte les categories fournisseurs
* (ERP-84 : Negociant, Cooperative...). Chaque categorie porte un `code` stable.
* (ERP-84 : Negociant, Cooperative...) ; le type PRESTATAIRE porte les categories
* prestataires (M3 1.1 : Maintenance industrielle, Nettoyage, Transport). Chaque
* categorie porte un `code` stable.
* Alimente le repertoire clients (ClientFixtures, module Commercial) avec des
* donnees realistes couvrant RG-1.03 (codes DISTRIBUTEUR / COURTIER) et RG-1.29
* (codes interdits sur adresse), et le multi-select Categorie fournisseur (M2).
@@ -71,6 +73,11 @@ class CategoryFixtures extends Fixture implements DependentFixtureInterface
'Grossiste' => 'GROSSISTE',
'Importateur' => 'IMPORTATEUR',
],
'PRESTATAIRE' => [
'Maintenance industrielle' => 'MAINTENANCE_INDUSTRIELLE',
'Nettoyage' => 'NETTOYAGE',
'Transport' => 'TRANSPORT',
],
];
public function __construct(
@@ -21,6 +21,10 @@ use Doctrine\Persistence\ObjectManager;
* taxonomie distincte des fournisseurs (Negociant, Cooperative...). Mirroir de
* la migration Version20260605120000.
*
* M3 1.1 : ajout du type PRESTATAIRE (code PRESTATAIRE, label « Prestataire »),
* taxonomie distincte des prestataires (Maintenance industrielle, Nettoyage,
* Transport). Mirroir de la migration Version20260612080000.
*
* Pourquoi une fixture EN PLUS du seed de la migration : `category_type` est une
* entite managee par l ORM, donc le purger Doctrine la vide avant chaque
* `doctrine:fixtures:load`. Sans cette fixture, le type CLIENT seede par la
@@ -36,12 +40,13 @@ class CategoryTypeFixtures extends Fixture
{
/**
* Source unique des types : code technique => libelle FR. Doit rester aligne
* sur le seed des migrations Version20260602100000 (CLIENT) et
* Version20260605120000 (FOURNISSEUR).
* sur le seed des migrations Version20260602100000 (CLIENT),
* Version20260605120000 (FOURNISSEUR) et Version20260612080000 (PRESTATAIRE).
*/
private const TYPES = [
'CLIENT' => 'Client',
'FOURNISSEUR' => 'Fournisseur',
'PRESTATAIRE' => 'Prestataire',
];
public function __construct(
+58
View File
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace App\Module\Technique;
/**
* Module Technique (M3) — pole distinct du Commercial qui porte le repertoire
* prestataires (entites Provider* livrees par les tickets suivants du M3).
*
* Decision Matthieu (11/06/2026) : le repertoire prestataires vit dans un
* module a part entiere « Technique » (et non sous Commercial), conformement au
* docx source. Ce module est activable/desactivable comme les autres
* (cf. config/modules.php), non requis au boot.
*
* Au ticket 1.1, le module ne porte encore aucune entite : il declare seulement
* son identite et son jeu de permissions (cf. spec-back M3 § 2.1 + § 5.1). Le
* cablage de la section sidebar « Technique » et l'attribution des permissions
* aux roles interviennent avec l'ecran prestataires (tickets ulterieurs).
*/
final class TechniqueModule
{
public const string ID = 'technique';
public const string LABEL = 'Technique';
public const bool REQUIRED = false;
/**
* Liste declarative des permissions RBAC exposees par le module Technique.
*
* Consommee par la commande `app:sync-permissions` (SyncPermissionsCommand)
* qui se charge d'upserter ces entrees dans la table `permission`, de
* reactiver les codes precedemment marques orphelins et de marquer comme
* orphelins ceux qui ont disparu du code source.
*
* La cle `module` est auto-injectee par le sync command a partir de
* `self::ID`, il est donc inutile de la repeter dans chaque entree.
*
* Convention de nommage des codes : `module.resource[.sub].action` en
* snake_case, le prefixe module devant correspondre exactement a
* `self::ID` (verifie par la commande de synchronisation).
*
* Granularite alignee sur Commercial (les prestataires sont le jumeau des
* fournisseurs) : view + manage, plus deux permissions dediees a l'onglet
* Comptabilite et une a l'archivage (cf. spec-back M3 § 2.9 + § 5.1).
*
* @return array<int, array{code: string, label: string}>
*/
public static function permissions(): array
{
return [
['code' => 'technique.providers.view', 'label' => 'Voir les prestataires'],
['code' => 'technique.providers.manage', 'label' => 'Créer / modifier les prestataires (hors onglet Comptabilité)'],
['code' => 'technique.providers.accounting.view', 'label' => 'Voir l\'onglet Comptabilité d\'un prestataire'],
['code' => 'technique.providers.accounting.manage', 'label' => 'Modifier l\'onglet Comptabilité d\'un prestataire'],
['code' => 'technique.providers.archive', 'label' => 'Archiver / restaurer un prestataire'],
];
}
}