Files
orion/docs/architecture/menu-management.md
Samir Boulahtit e3cab29c1a docs: add module system and menu management architecture documentation
Add comprehensive documentation for:
- Module system architecture (three-tier classification, registry, events, migrations)
- Menu management system (registry, visibility config, module integration)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 22:21:23 +01:00

14 KiB

Menu Management Architecture

The Wizamart platform provides a flexible menu system that supports per-platform and per-user customization. This document explains the menu architecture, configuration options, and how menus integrate with the module system.

Overview

┌─────────────────────────────────────────────────────────────────────────┐
│                       MENU REGISTRY (Source of Truth)                    │
│  app/config/menu_registry.py                                            │
│                                                                          │
│  ┌─────────────────────────────┐  ┌─────────────────────────────┐      │
│  │   ADMIN_MENU_REGISTRY       │  │   VENDOR_MENU_REGISTRY      │      │
│  │   (Admin panel menus)       │  │   (Vendor dashboard menus)  │      │
│  └─────────────────────────────┘  └─────────────────────────────┘      │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                       VISIBILITY CONFIGURATION                           │
│  models/database/admin_menu_config.py                                   │
│                                                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                    AdminMenuConfig Table                         │   │
│  │  Stores visibility overrides (hidden items only)                 │   │
│  │  - Platform scope: applies to platform admins/vendors            │   │
│  │  - User scope: applies to specific super admin                   │   │
│  └─────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        FILTERED MENU OUTPUT                              │
│                                                                          │
│  Registry - Hidden Items - Disabled Modules = Visible Menu Items        │
└─────────────────────────────────────────────────────────────────────────┘

Frontend Types

The system supports two distinct frontend types:

Frontend Description Users
ADMIN Admin panel Super admins, platform admins
VENDOR Vendor dashboard Vendors on a platform
from models.database.admin_menu_config import FrontendType

# Use in code
FrontendType.ADMIN   # "admin"
FrontendType.VENDOR  # "vendor"

Menu Registry

The menu registry (app/config/menu_registry.py) is the single source of truth for menu structure. The database only stores visibility overrides.

Admin Menu Structure

ADMIN_MENU_REGISTRY = {
    "frontend_type": FrontendType.ADMIN,
    "sections": [
        {
            "id": "main",
            "label": None,  # No header
            "items": [
                {"id": "dashboard", "label": "Dashboard", "icon": "home", "url": "/admin/dashboard"},
            ],
        },
        {
            "id": "superAdmin",
            "label": "Super Admin",
            "super_admin_only": True,  # Only visible to super admins
            "items": [
                {"id": "admin-users", "label": "Admin Users", "icon": "shield", "url": "/admin/admin-users"},
            ],
        },
        # ... more sections
    ],
}

Admin Menu Sections

Section ID Label Description
main (none) Dashboard - always at top
superAdmin Super Admin Super admin only tools
platformAdmin Platform Administration Companies, vendors, messages
vendorOps Vendor Operations Products, customers, inventory, orders
marketplace Marketplace Letzshop integration
billing Billing & Subscriptions Tiers, subscriptions, billing history
contentMgmt Content Management Platforms, content pages, themes
devTools Developer Tools Components, icons
platformHealth Platform Health Capacity, testing, code quality
monitoring Platform Monitoring Imports, tasks, logs, notifications
settingsSection Platform Settings General settings, email templates, my menu

Vendor Menu Sections

Section ID Label Description
main (none) Dashboard, analytics
products Products & Inventory Products, inventory, marketplace import
sales Sales & Orders Orders, Letzshop orders, invoices
customers Customers Customers, messages, notifications
shop Shop & Content Content pages, media library
account Account & Settings Team, profile, billing, settings

Menu Item Properties

Each menu item has these properties:

Property Type Description
id string Unique identifier (used for config and access control)
label string Display text
icon string Heroicons icon name
url string Route URL
super_admin_only boolean (Optional) Only visible to super admins

Visibility Configuration

Opt-Out Model

The system uses an opt-out model:

  • All menu items are visible by default
  • Only hidden items are stored in the database
  • This keeps the database small and makes the default state explicit

Mandatory Items

Certain menu items cannot be hidden:

MANDATORY_MENU_ITEMS = {
    FrontendType.ADMIN: frozenset({
        "dashboard",    # Landing page
        "companies",    # Platform admin core
        "vendors",      # Platform admin core
        "admin-users",  # Super admin core
        "settings",     # Configuration access
        "my-menu",      # Must be able to undo changes
    }),
    FrontendType.VENDOR: frozenset({
        "dashboard",    # Landing page
        "settings",     # Configuration access
    }),
}

Scope Types

Menu configuration supports two scopes:

Scope Field Description Use Case
Platform platform_id Applies to all users on platform Hide features not used by platform
User user_id Applies to specific super admin Personal preference customization

Important Rules:

  • Exactly one scope must be set (platform XOR user)
  • User scope is only allowed for admin frontend (super admins only)
  • Vendor frontend only supports platform scope

Resolution Order

Admin Frontend:

Platform admin → Check platform config → Fall back to default (all visible)
Super admin   → Check user config → Fall back to default (all visible)

Vendor Frontend:

Vendor → Check platform config → Fall back to default (all visible)

Database Model

AdminMenuConfig Table

CREATE TABLE admin_menu_configs (
    id SERIAL PRIMARY KEY,
    frontend_type VARCHAR(10) NOT NULL,  -- 'admin' or 'vendor'
    platform_id INTEGER REFERENCES platforms(id),
    user_id INTEGER REFERENCES users(id),
    menu_item_id VARCHAR(50) NOT NULL,
    is_visible BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,

    -- Constraints
    CONSTRAINT uq_frontend_platform_menu_config
        UNIQUE (frontend_type, platform_id, menu_item_id),
    CONSTRAINT uq_frontend_user_menu_config
        UNIQUE (frontend_type, user_id, menu_item_id),
    CONSTRAINT ck_admin_menu_config_scope
        CHECK ((platform_id IS NOT NULL AND user_id IS NULL) OR
               (platform_id IS NULL AND user_id IS NOT NULL)),
    CONSTRAINT ck_user_scope_admin_only
        CHECK ((user_id IS NULL) OR (frontend_type = 'admin'))
);

Examples

# Platform "OMS" hides inventory from admin panel
AdminMenuConfig(
    frontend_type=FrontendType.ADMIN,
    platform_id=1,
    menu_item_id="inventory",
    is_visible=False
)

# Platform "OMS" hides letzshop from vendor dashboard
AdminMenuConfig(
    frontend_type=FrontendType.VENDOR,
    platform_id=1,
    menu_item_id="letzshop",
    is_visible=False
)

# Super admin "john" hides code-quality from their admin panel
AdminMenuConfig(
    frontend_type=FrontendType.ADMIN,
    user_id=5,
    menu_item_id="code-quality",
    is_visible=False
)

Module Integration

Menu items are associated with modules. When a module is disabled for a platform, its menu items are automatically hidden.

Module to Menu Item Mapping

Each module defines its menu items per frontend:

# In module definition
billing_module = ModuleDefinition(
    code="billing",
    menu_items={
        FrontendType.ADMIN: ["subscription-tiers", "subscriptions", "billing-history"],
        FrontendType.VENDOR: ["billing", "invoices"],
    },
)

Menu Filtering Logic

from app.modules.service import module_service

# Get available menu items (module-aware)
available_items = module_service.get_module_menu_items(
    db, platform_id, FrontendType.ADMIN
)

# Check if specific menu item's module is enabled
is_available = module_service.is_menu_item_module_enabled(
    db, platform_id, "subscription-tiers", FrontendType.ADMIN
)

Three-Layer Filtering

The final visible menu is computed by three layers:

  1. Registry: All possible menu items
  2. Module Enablement: Items from disabled modules are hidden
  3. Visibility Config: Explicitly hidden items are removed
Final Menu = Registry Items
           - Items from Disabled Modules
           - Items with is_visible=False in config
           - Items not matching user role (super_admin_only)

Helper Functions

Getting Menu Items

from app.config.menu_registry import (
    get_all_menu_item_ids,
    get_menu_item,
    is_super_admin_only_item,
    ADMIN_MENU_REGISTRY,
    VENDOR_MENU_REGISTRY,
)

# Get all item IDs for a frontend
admin_items = get_all_menu_item_ids(FrontendType.ADMIN)
# Returns: {'dashboard', 'admin-users', 'companies', ...}

# Get specific item details
item = get_menu_item(FrontendType.ADMIN, "subscription-tiers")
# Returns: {
#     'id': 'subscription-tiers',
#     'label': 'Subscription Tiers',
#     'icon': 'tag',
#     'url': '/admin/subscription-tiers',
#     'section_id': 'billing',
#     'section_label': 'Billing & Subscriptions'
# }

# Check if item requires super admin
is_restricted = is_super_admin_only_item("admin-users")  # True

Menu Enums

from app.config.menu_registry import AdminMenuItem, VendorMenuItem

# Use enums for type safety
AdminMenuItem.DASHBOARD.value  # "dashboard"
AdminMenuItem.INVENTORY.value  # "inventory"

VendorMenuItem.PRODUCTS.value   # "products"
VendorMenuItem.ANALYTICS.value  # "analytics"

Access Control

Route Protection

from app.api.deps import require_menu_access

@router.get("/admin/inventory")
async def inventory_page(
    _access: bool = Depends(require_menu_access("inventory", FrontendType.ADMIN))
):
    # Only accessible if menu item is visible for user's context
    pass

Sidebar Rendering

The sidebar template filters items based on:

  1. Module enablement
  2. Visibility configuration
  3. User role (super admin check)
{% for section in menu_sections %}
  {% if not section.super_admin_only or current_user.is_super_admin %}
    {% for item in section.items %}
      {% if item.id in visible_menu_items %}
        <a href="{{ item.url }}">{{ item.label }}</a>
      {% endif %}
    {% endfor %}
  {% endif %}
{% endfor %}

UI for Menu Configuration

Platform Admin Menu Config

Located at /admin/platform-menu-config (accessible by super admins):

  • Configure which menu items are visible for platform admins
  • Configure which menu items are visible for vendors on this platform
  • Mandatory items cannot be unchecked

Personal Menu Config (Super Admins)

Located at /admin/my-menu:

  • Super admins can customize their own admin panel menu
  • Personal preferences that don't affect other users
  • Useful for hiding rarely-used features

Best Practices

Do

  • Use menu item enums (AdminMenuItem, VendorMenuItem) for type safety
  • Check module enablement before showing module-specific menu items
  • Respect mandatory items - don't try to hide them
  • Use require_menu_access dependency to protect routes

Don't

  • Hardcode menu item IDs as strings (use enums)
  • Store is_visible=True in database (default state, wastes space)
  • Allow hiding mandatory items via API
  • Create menu items without registering them in the registry