From c9c6d043a74e9419a9eec0228958b217ebdf6eb7 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 29 Jun 2026 15:24:08 +0200 Subject: [PATCH] =?UTF-8?q?feat(catalog)=20:=20M7=20=E2=80=94=20permission?= =?UTF-8?q?s=20catalog.storages.*=20+=20sidebar=20+=203=20miroirs=20RBAC?= =?UTF-8?q?=20(ERP-210)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/sidebar.php | 10 ++++++++++ frontend/i18n/locales/fr.json | 3 ++- frontend/tests/e2e/_fixtures/personas.ts | 14 ++++++++++---- src/Module/Catalog/CatalogModule.php | 5 +++++ .../Core/Infrastructure/Console/SeedE2ECommand.php | 4 ++++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/config/sidebar.php b/config/sidebar.php index 7fd5bea..82130db 100644 --- a/config/sidebar.php +++ b/config/sidebar.php @@ -172,6 +172,16 @@ return [ 'module' => 'catalog', 'permission' => 'catalog.categories.view', ], + // Stockage (M7, ERP-210). Admin-only : gate par `catalog.storages.view` + // et son module owner `catalog`. Reutilise le referentiel StorageType + // du M6. Place pres des autres items Catalog (produits, categories). + [ + 'label' => 'sidebar.catalog.storages', + 'to' => '/admin/storages', + 'icon' => 'mdi:warehouse', + 'module' => 'catalog', + 'permission' => 'catalog.storages.view', + ], [ 'label' => 'sidebar.core.audit_log', 'to' => '/admin/audit-log', diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index d17f6f8..189cb00 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -53,7 +53,8 @@ }, "catalog": { "categories": "Gestion des catégories", - "products": "Catalogue produits" + "products": "Catalogue produits", + "storages": "Gestion des stockages" } }, "dashboard": { diff --git a/frontend/tests/e2e/_fixtures/personas.ts b/frontend/tests/e2e/_fixtures/personas.ts index 8417805..6299968 100644 --- a/frontend/tests/e2e/_fixtures/personas.ts +++ b/frontend/tests/e2e/_fixtures/personas.ts @@ -35,7 +35,7 @@ export interface Persona { // sidebar-visibility pour driver la matrice. Les valeurs correspondent // aux slugs de route (`/admin/`), volontairement stables quand // la copie/i18n change. - expectedAdminLinks: Array<'users' | 'roles' | 'sites' | 'audit-log' | 'categories' | 'products'> + expectedAdminLinks: Array<'users' | 'roles' | 'sites' | 'audit-log' | 'categories' | 'products' | 'storages'> } const SHARED_PASSWORD = 'e2e-secret' @@ -47,7 +47,7 @@ export const personas: Record = { password: SHARED_PASSWORD, isAdmin: true, permissions: [], - expectedAdminLinks: ['users', 'roles', 'sites', 'categories', 'products', 'audit-log'], + expectedAdminLinks: ['users', 'roles', 'sites', 'categories', 'products', 'storages', 'audit-log'], }, 'user-full': { key: 'user-full', @@ -71,6 +71,12 @@ export const personas: Record = { // `/admin/products` -> ajoute le lien `products` a expectedAdminLinks. 'catalog.products.view', 'catalog.products.manage', + // Stockage (M7, ERP-210). Admin-only : mappe sur le persona "tout", + // pas de nouveau persona (regle ABSOLUE n°7). L'item vit dans la + // section Administration sur la route `/admin/storages` -> ajoute le + // lien `storages` a expectedAdminLinks. + 'catalog.storages.view', + 'catalog.storages.manage', // Commercial — Repertoire clients (M1). Mappe ici sur le persona // "tout" en attendant les vrais roles metier (bureau/compta/ // commerciale/usine) seedes par ERP-74. Pas de nouveau persona @@ -121,7 +127,7 @@ export const personas: Record = { 'logistique.weighing_tickets.view', 'logistique.weighing_tickets.manage', ], - expectedAdminLinks: ['users', 'roles', 'sites', 'categories', 'products', 'audit-log'], + expectedAdminLinks: ['users', 'roles', 'sites', 'categories', 'products', 'storages', 'audit-log'], }, 'user-readonly': { key: 'user-readonly', @@ -166,4 +172,4 @@ export function getPersona(key: PersonaKey): Persona { return personas[key] } -export const ALL_ADMIN_LINKS = ['users', 'roles', 'sites', 'categories', 'products', 'audit-log'] as const +export const ALL_ADMIN_LINKS = ['users', 'roles', 'sites', 'categories', 'products', 'storages', 'audit-log'] as const diff --git a/src/Module/Catalog/CatalogModule.php b/src/Module/Catalog/CatalogModule.php index c5154f9..c2ed730 100644 --- a/src/Module/Catalog/CatalogModule.php +++ b/src/Module/Catalog/CatalogModule.php @@ -47,6 +47,11 @@ final class CatalogModule // Item sidebar dans la section Administration, sous « Repertoire transporteurs ». ['code' => 'catalog.products.view', 'label' => 'Voir les produits'], ['code' => 'catalog.products.manage', 'label' => 'Gérer les produits (créer, éditer)'], + // Stockage (M7, ERP-210) : admin-only. Reutilise le referentiel + // StorageType du M6. Item sidebar dans la section Administration, + // pres des items Catalog (produits, categories). + ['code' => 'catalog.storages.view', 'label' => 'Voir les stockages'], + ['code' => 'catalog.storages.manage', 'label' => 'Gérer les stockages (créer, éditer)'], ]; } } diff --git a/src/Module/Core/Infrastructure/Console/SeedE2ECommand.php b/src/Module/Core/Infrastructure/Console/SeedE2ECommand.php index 5c7ba71..553230c 100644 --- a/src/Module/Core/Infrastructure/Console/SeedE2ECommand.php +++ b/src/Module/Core/Infrastructure/Console/SeedE2ECommand.php @@ -190,6 +190,10 @@ final class SeedE2ECommand extends Command // p.3) : mappe sur le persona "tout". Miroir de personas.ts. 'catalog.products.view', 'catalog.products.manage', + // Stockage (M7, ERP-210). Admin-only : mappe sur le persona + // "tout". Miroir de personas.ts. + 'catalog.storages.view', + 'catalog.storages.manage', // Commercial — Repertoire clients (M1). Mappe ici sur le // persona "tout" en attendant les vrais roles metier // (bureau/compta/commerciale/usine) seedes par ERP-74.