feat(technique) : module Technique + taxonomie categories prestataires #89
Reference in New Issue
Block a user
Delete Branch "feat/erp-m3-technique-module-taxonomie"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
M3 — Ticket 1.1 : module Technique + taxonomie catégories prestataires
Prérequis de tout le M3 (répertoire prestataires). Spec :
docs/specs/M3-prestataires/spec-back.md§ 2.1 + § 2.4.Contenu
Technique(src/Module/Technique/TechniqueModule.php) :ID=technique,LABEL=Technique,REQUIRED=false,permissions()(5 codestechnique.providers.*: view / manage / accounting.view / accounting.manage / archive).config/modules.php→/api/modulesexposetechnique.frontend/modules/technique/(auto-détecté).CategoryType(codePRESTATAIRE/ labelPrestataire) + 3 catégories (Maintenance industrielle, Nettoyage, Transport).Version20260612080000(ON CONFLICT DO NOTHING+NOT EXISTS, jonction M2Mcategory_category_type— schéma courant, pas l'anciencategory_type_id).CategoryTypeFixtures/CategoryFixturesétendues (survivent au purgerdb-reset).Critères d'acceptation ✅
app:sync-permissions→ 5 codes en base)TechniqueModule::classdansconfig/modules.phpGET /api/categories?typeCode=PRESTATAIREfiltre correctementTests
TechniqueModuleTest: identité + jeu de 5 permissions figé.CategoryPrestataireSeedTest:?typeCode=PRESTATAIREne renvoie QUE le type PRESTATAIRE + pagination Hydra préservée.make test: 589 tests OK ·php-cs-fixer: 0 correction ·make db-reset: type + 3 catégories présents, idempotent.Hors-périmètre (tickets M3 suivants)
Section sidebar « Technique », personas RBAC E2E, et entités
Provider*(l'écran/providersn'existe pas encore → pas de lien mort introduit ici).Revue de code (correctness + altitude) — 1 point substantiel (migration) + 1 note de contexte RBAC. Le reste de la MR (shape du module, tests, down(), colonnes de l'INSERT) est cohérent avec les conventions.
@@ -0,0 +77,4 @@INSERT INTO category (name, code, created_at, updated_at)SELECT :name, :code, NOW(), NOW()WHERE NOT EXISTS (SELECT 1 FROM category c WHERE c.code = :code AND c.deleted_at IS NULLIdempotence partielle : le garde ne couvre que
code, pasname(risque d'échec de migration sur une prod existante).Le
NOT EXISTSne teste quec.code = :code, maisuq_category_name_active(créé enVersion20260608120000) impose une unicité GLOBALE surLOWER(name)parmi les actifs (CREATE UNIQUE INDEX uq_category_name_active ON category (LOWER(name)) WHERE deleted_at IS NULL).Scénario d'échec concret : M3 est ajouté à une prod déjà en service (M1/M2). Si un utilisateur y a déjà créé une catégorie active nommée « Transport » ou « Nettoyage » (libellés très génériques) sous un autre
code, alors :codepasse (le codeTRANSPORTest libre) ;INSERTvioleuq_category_name_activesurLOWER(name)→ la migrationmake migration-migrateavorte sur une violation de contrainte unique.À noter : la sœur
Version20260605120000(FOURNISSEUR) utilisait le même pattern mais tournait sous l'ancien indexuq_category_name_type_active(unicité PAR TYPE) — la collision globale n'existait pas encore. Ce n'est plus le cas ici.Recommandation — élargir le garde au nom (collision-safe plutôt que crash) :
En cas de collision de nom, la catégorie n'est pas seedée (et donc pas rattachée au type via la jonction qui cible
c.code = :code) — comportement dégradé acceptable, vs. un échec dur de la migration. La doc d'idempotence du docblock (§ « Idempotence ») mériterait d'être alignée en conséquence.@@ -0,0 +44,4 @@* Comptabilite et une a l'archivage (cf. spec-back M3 § 2.9 + § 5.1).** @return array<int, array{code: string, label: string}>*/Contexte RBAC — 3 miroirs (règle ABSOLUE n°8) : OK pour ce ticket, à ne pas oublier au ticket suivant.
Ce module déclare 5 permissions
technique.providers.*mais ne touche pasconfig/sidebar.php,frontend/tests/e2e/_fixtures/personas.tsniSeedE2ECommand.php. C'est cohérent avec le périmètre annoncé (pas encore d'écran/providers, donc pas de permission testable au sens de.claude/rules/testing.md) etapp:sync-permissionslit bienconfig/modules.php→ les 5 codes sont upsertés.Aucun garde-fou ne casse ici. Simple rappel : dès que l'écran prestataires arrivera (rattachement à un item sidebar + persona), les 3 miroirs devront bouger ensemble sous peine de drift / faux positif E2E.