# ADR-022 : Menu de l'application défini une seule fois, regroupé par métier

**Statut :** Accepté
**Date :** 2026-10-27
**Contexte :** Navigation de la SPA (`resources/js/common/layouts`) : menu latéral (`LeftSidebar.vue`) et menu horizontal (`MainMenus.vue`), au choix de l'utilisateur (bouton « mode du menu »)

---

## Contexte

Les deux menus écrivaient chacun, à la main, toutes leurs entrées et leurs conditions d'accès : 853 lignes et 110 conditions dans l'un, 634 lignes et 82 conditions dans l'autre. Ils avaient divergé. En mode horizontal, un utilisateur ne trouvait plus Caisse et banque, Rapprochement, Lots et péremption, Encaissements, Décaissements, Créances ni Alertes intelligentes. Chaque nouvelle fonctionnalité (ADR-015, ADR-018, ADR-020) devait être ajoutée deux fois, et l'une des deux finissait oubliée.

Le menu latéral comptait aussi environ 16 entrées au premier niveau, sans logique d'usage : l'ajustement et les transferts à la racine mais les lots sous « Inventaire », la caisse en 9ᵉ position, des alertes et un journal rangés dans « Rapports ».

## Décision

### 1. Une seule définition, des données

`menu/definition.js` décrit le menu comme une liste de données : clé, libellé, icône, route, permissions (au moins une ; `admin` les donne toutes), fonctionnalités de formule (toutes), condition particulière, badge, sous-menu. `visibleMenu(entrées, { perms, hasFeature })` retire ce que l'utilisateur ne peut pas ouvrir et les sous-menus devenus vides. Un sous-menu réduit à une seule entrée s'affiche comme cette entrée : la caisse reste à un clic pour qui n'a pas l'import des ventes.

`menu/useAppMenu.js` porte l'état commun : menu visible (superadmin ou entreprise), entrée sélectionnée, sous-menu ouvert, navigation, badge des pertes à valider. Les deux menus ne gardent que leur rendu (`inline` ou `horizontal`). Les entrées sont rendues **directement dans `a-menu`** : un composant intermédiaire empêche ant-design de mesurer les entrées du menu horizontal et de replier le surplus dans « … ».

L'entrée sélectionnée vient de `meta.menuKey` de la route, et le sous-menu ouvert est déduit de la définition. Les pages des paramètres sans entrée propre sélectionnent « Tous les paramètres ». Les routes, leurs noms et leurs adresses ne changent pas.

Le serveur reste seul juge (permissions, `check.feature`) : le menu ne fait que masquer.

### 2. Regroupement par métier

| Menu | Entrées |
|---|---|
| Tableau de bord | |
| Caisse | Point de vente, ventes de caisse importées |
| Ventes | Ventes, retours, encaissements, créances clients |
| Achats | Achats, réceptions, retours, décaissements |
| Produits | Produits, catégories, marques, fiches techniques |
| Stock | Ajustements, transferts, lots et péremptions, valorisation |
| Inventaire | Comptages, pertes, emplacements |
| Trésorerie | Caisse et banque, rapprochement, dépenses, catégories de dépenses |
| Tiers | Clients, fournisseurs |
| Rapports | Paiements, alerte de stock, rapports utilisateurs, alertes intelligentes, journal d'activité |
| Paramètres | Membres du personnel, tous les paramètres |

Chaque entrée garde exactement la condition d'accès qu'elle avait. Le fil d'Ariane des pages déplacées suit le nouveau groupe.

## Alternatives Considérées

### Garder deux menus et corriger le menu horizontal
Le plus rapide. Rejeté : la divergence reviendrait à la prochaine fonctionnalité, et les conditions resteraient impossibles à tester.

### Supprimer le mode horizontal
Moins de code. Rejeté : avec une définition unique, le garder ne coûte presque rien, et des utilisateurs l'ont peut-être choisi.

### Générer le menu depuis les routes (meta)
Une seule source aussi. Rejeté : les routes décrivent des pages, pas l'ordre ni le regroupement du menu ; plusieurs pages partagent une entrée (détail d'un comptage, création d'un achat).

## Conséquences

- Ajouter une page au menu : une ligne dans `definition.js`, testée par `resources/js/tests/menu/definition.test.js` (ce que voit chaque profil, clés uniques, une route par entrée).
- `meta.menuParent` des routes ne sert plus qu'à reconnaître les pages des paramètres.
- Nouveaux libellés `menu.till`, `menu.stock`, `menu.treasury`, `menu.all_settings`.
- Le guide de la gérante (`docs/`, hors dépôt) décrit les anciens chemins : à mettre à jour.

## Quand Réviser

- Si le nombre d'entrées de premier niveau dépasse ce que le mode horizontal affiche sans « … » sur un écran courant : regrouper davantage, ou réserver l'horizontal aux grands écrans.
- Si des modules installés (`appModules`) doivent s'insérer dans un groupe : leur faire fournir une entrée de définition plutôt qu'un composant.
