From 31e3d0fcba69c0795b1c065db46fc12f2d7d56b8 Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Sun, 1 Feb 2026 21:29:03 +0100 Subject: [PATCH] refactor: remove deprecated menu_registry.py in favor of module-driven menus - Delete app/config/menu_registry.py (centralized menu definitions) - Update app/config/__init__.py to remove menu_registry exports - Migrate menu_service.py to use menu_discovery_service exclusively - Add helper methods to menu_discovery_service.py: - get_all_menu_item_ids() - get all item IDs for a frontend type - get_menu_item() - get specific menu item by ID - is_super_admin_only_item() - check if item is super-admin only - get_menu_item_module() - get module code for a menu item Menu items are now defined in each module's definition.py file and aggregated by MenuDiscoveryService at runtime, enabling true module-driven architecture. Co-Authored-By: Claude Opus 4.5 --- app/config/__init__.py | 18 +- app/config/menu_registry.py | 546 ------------------ .../core/services/menu_discovery_service.py | 95 +++ app/modules/core/services/menu_service.py | 177 +++--- 4 files changed, 174 insertions(+), 662 deletions(-) delete mode 100644 app/config/menu_registry.py diff --git a/app/config/__init__.py b/app/config/__init__.py index f0aa0e54..0e0265da 100644 --- a/app/config/__init__.py +++ b/app/config/__init__.py @@ -1,18 +1,8 @@ # app/config/__init__.py """Configuration modules for the application.""" -from .menu_registry import ( - ADMIN_MENU_REGISTRY, - VENDOR_MENU_REGISTRY, - AdminMenuItem, - VendorMenuItem, - get_all_menu_item_ids, -) +# Note: menu_registry.py has been deprecated in favor of module-driven menus. +# Menu items are now defined in each module's definition.py file and aggregated +# by MenuDiscoveryService (app/modules/core/services/menu_discovery_service.py). -__all__ = [ - "ADMIN_MENU_REGISTRY", - "VENDOR_MENU_REGISTRY", - "AdminMenuItem", - "VendorMenuItem", - "get_all_menu_item_ids", -] +__all__ = [] diff --git a/app/config/menu_registry.py b/app/config/menu_registry.py deleted file mode 100644 index fcb1359f..00000000 --- a/app/config/menu_registry.py +++ /dev/null @@ -1,546 +0,0 @@ -# app/config/menu_registry.py -""" -Menu registry for Admin and Vendor frontends. - -This module defines the complete menu structure for both frontends. -Menu items are identified by unique IDs that are used for: -- Storing visibility configuration in AdminMenuConfig -- Checking access in require_menu_access() dependency -- Rendering the sidebar dynamically - -The registry is the single source of truth for menu structure. -Database only stores visibility overrides (is_visible=False). -""" - -from enum import Enum - -from app.modules.enums import FrontendType - - -class AdminMenuItem(str, Enum): - """Admin frontend menu item identifiers.""" - - # Dashboard (always visible section) - DASHBOARD = "dashboard" - - # Super Admin section - ADMIN_USERS = "admin-users" - - # Platform Administration section - COMPANIES = "companies" - VENDORS = "vendors" - MESSAGES = "messages" - - # Vendor Operations section - VENDOR_PRODUCTS = "vendor-products" - CUSTOMERS = "customers" - INVENTORY = "inventory" - ORDERS = "orders" - - # Marketplace section - MARKETPLACE_LETZSHOP = "marketplace-letzshop" - - # Billing & Subscriptions section - SUBSCRIPTION_TIERS = "subscription-tiers" - SUBSCRIPTIONS = "subscriptions" - BILLING_HISTORY = "billing-history" - - # Content Management section - PLATFORMS = "platforms" - CONTENT_PAGES = "content-pages" - VENDOR_THEMES = "vendor-themes" - - # Developer Tools section - COMPONENTS = "components" - ICONS = "icons" - - # Platform Health section - PLATFORM_HEALTH = "platform-health" - TESTING = "testing" - CODE_QUALITY = "code-quality" - - # Platform Monitoring section - IMPORTS = "imports" - BACKGROUND_TASKS = "background-tasks" - LOGS = "logs" - NOTIFICATIONS = "notifications" - - # Platform Settings section - SETTINGS = "settings" - EMAIL_TEMPLATES = "email-templates" - MY_MENU = "my-menu" # Super admin only - personal menu configuration - - -class VendorMenuItem(str, Enum): - """Vendor frontend menu item identifiers.""" - - # Main section (always visible) - DASHBOARD = "dashboard" - ANALYTICS = "analytics" - - # Products & Inventory section - PRODUCTS = "products" - INVENTORY = "inventory" - MARKETPLACE = "marketplace" - - # Sales & Orders section - ORDERS = "orders" - LETZSHOP = "letzshop" - INVOICES = "invoices" - - # Customers section - CUSTOMERS = "customers" - MESSAGES = "messages" - NOTIFICATIONS = "notifications" - - # Shop & Content section - CONTENT_PAGES = "content-pages" - MEDIA = "media" - - # Account & Settings section - TEAM = "team" - PROFILE = "profile" - BILLING = "billing" - EMAIL_TEMPLATES = "email-templates" - SETTINGS = "settings" - - -# ============================================================================= -# Admin Menu Registry -# ============================================================================= - -ADMIN_MENU_REGISTRY = { - "frontend_type": FrontendType.ADMIN, - "sections": [ - { - "id": "main", - "label": None, # No header, always at top - "items": [ - { - "id": AdminMenuItem.DASHBOARD.value, - "label": "Dashboard", - "icon": "home", - "url": "/admin/dashboard", - }, - ], - }, - { - "id": "superAdmin", - "label": "Super Admin", - "super_admin_only": True, - "items": [ - { - "id": AdminMenuItem.ADMIN_USERS.value, - "label": "Admin Users", - "icon": "shield", - "url": "/admin/admin-users", - }, - ], - }, - { - "id": "platformAdmin", - "label": "Platform Administration", - "items": [ - { - "id": AdminMenuItem.COMPANIES.value, - "label": "Companies", - "icon": "office-building", - "url": "/admin/companies", - }, - { - "id": AdminMenuItem.VENDORS.value, - "label": "Vendors", - "icon": "shopping-bag", - "url": "/admin/vendors", - }, - { - "id": AdminMenuItem.MESSAGES.value, - "label": "Messages", - "icon": "chat-bubble-left-right", - "url": "/admin/messages", - }, - ], - }, - { - "id": "vendorOps", - "label": "Vendor Operations", - "items": [ - { - "id": AdminMenuItem.VENDOR_PRODUCTS.value, - "label": "Products", - "icon": "cube", - "url": "/admin/vendor-products", - }, - { - "id": AdminMenuItem.CUSTOMERS.value, - "label": "Customers", - "icon": "user-group", - "url": "/admin/customers", - }, - { - "id": AdminMenuItem.INVENTORY.value, - "label": "Inventory", - "icon": "archive", - "url": "/admin/inventory", - }, - { - "id": AdminMenuItem.ORDERS.value, - "label": "Orders", - "icon": "clipboard-list", - "url": "/admin/orders", - }, - ], - }, - { - "id": "marketplace", - "label": "Marketplace", - "items": [ - { - "id": AdminMenuItem.MARKETPLACE_LETZSHOP.value, - "label": "Letzshop", - "icon": "shopping-cart", - "url": "/admin/marketplace/letzshop", - }, - ], - }, - { - "id": "billing", - "label": "Billing & Subscriptions", - "items": [ - { - "id": AdminMenuItem.SUBSCRIPTION_TIERS.value, - "label": "Subscription Tiers", - "icon": "tag", - "url": "/admin/subscription-tiers", - }, - { - "id": AdminMenuItem.SUBSCRIPTIONS.value, - "label": "Vendor Subscriptions", - "icon": "credit-card", - "url": "/admin/subscriptions", - }, - { - "id": AdminMenuItem.BILLING_HISTORY.value, - "label": "Billing History", - "icon": "document-text", - "url": "/admin/billing-history", - }, - ], - }, - { - "id": "contentMgmt", - "label": "Content Management", - "items": [ - { - "id": AdminMenuItem.PLATFORMS.value, - "label": "Platforms", - "icon": "globe-alt", - "url": "/admin/platforms", - }, - { - "id": AdminMenuItem.CONTENT_PAGES.value, - "label": "Content Pages", - "icon": "document-text", - "url": "/admin/content-pages", - }, - { - "id": AdminMenuItem.VENDOR_THEMES.value, - "label": "Vendor Themes", - "icon": "color-swatch", - "url": "/admin/vendor-themes", - }, - ], - }, - { - "id": "devTools", - "label": "Developer Tools", - "items": [ - { - "id": AdminMenuItem.COMPONENTS.value, - "label": "Components", - "icon": "view-grid", - "url": "/admin/components", - }, - { - "id": AdminMenuItem.ICONS.value, - "label": "Icons", - "icon": "photograph", - "url": "/admin/icons", - }, - ], - }, - { - "id": "platformHealth", - "label": "Platform Health", - "items": [ - { - "id": AdminMenuItem.PLATFORM_HEALTH.value, - "label": "Capacity Monitor", - "icon": "chart-bar", - "url": "/admin/platform-health", - }, - { - "id": AdminMenuItem.TESTING.value, - "label": "Testing Hub", - "icon": "beaker", - "url": "/admin/testing", - }, - { - "id": AdminMenuItem.CODE_QUALITY.value, - "label": "Code Quality", - "icon": "shield-check", - "url": "/admin/code-quality", - }, - ], - }, - { - "id": "monitoring", - "label": "Platform Monitoring", - "items": [ - { - "id": AdminMenuItem.IMPORTS.value, - "label": "Import Jobs", - "icon": "cube", - "url": "/admin/imports", - }, - { - "id": AdminMenuItem.BACKGROUND_TASKS.value, - "label": "Background Tasks", - "icon": "collection", - "url": "/admin/background-tasks", - }, - { - "id": AdminMenuItem.LOGS.value, - "label": "Application Logs", - "icon": "document-text", - "url": "/admin/logs", - }, - { - "id": AdminMenuItem.NOTIFICATIONS.value, - "label": "Notifications", - "icon": "bell", - "url": "/admin/notifications", - }, - ], - }, - { - "id": "settingsSection", - "label": "Platform Settings", - "items": [ - { - "id": AdminMenuItem.SETTINGS.value, - "label": "General", - "icon": "cog", - "url": "/admin/settings", - }, - { - "id": AdminMenuItem.EMAIL_TEMPLATES.value, - "label": "Email Templates", - "icon": "mail", - "url": "/admin/email-templates", - }, - { - "id": AdminMenuItem.MY_MENU.value, - "label": "My Menu", - "icon": "view-grid", - "url": "/admin/my-menu", - "super_admin_only": True, # Only super admins can customize their menu - }, - ], - }, - ], -} - - -# ============================================================================= -# Vendor Menu Registry -# ============================================================================= - -VENDOR_MENU_REGISTRY = { - "frontend_type": FrontendType.VENDOR, - "sections": [ - { - "id": "main", - "label": None, # No header, always at top - "items": [ - { - "id": VendorMenuItem.DASHBOARD.value, - "label": "Dashboard", - "icon": "home", - "url": "/dashboard", # Relative to /vendor/{code}/ - }, - { - "id": VendorMenuItem.ANALYTICS.value, - "label": "Analytics", - "icon": "chart-bar", - "url": "/analytics", - }, - ], - }, - { - "id": "products", - "label": "Products & Inventory", - "items": [ - { - "id": VendorMenuItem.PRODUCTS.value, - "label": "All Products", - "icon": "shopping-bag", - "url": "/products", - }, - { - "id": VendorMenuItem.INVENTORY.value, - "label": "Inventory", - "icon": "clipboard-list", - "url": "/inventory", - }, - { - "id": VendorMenuItem.MARKETPLACE.value, - "label": "Marketplace Import", - "icon": "download", - "url": "/marketplace", - }, - ], - }, - { - "id": "sales", - "label": "Sales & Orders", - "items": [ - { - "id": VendorMenuItem.ORDERS.value, - "label": "Orders", - "icon": "document-text", - "url": "/orders", - }, - { - "id": VendorMenuItem.LETZSHOP.value, - "label": "Letzshop Orders", - "icon": "external-link", - "url": "/letzshop", - }, - { - "id": VendorMenuItem.INVOICES.value, - "label": "Invoices", - "icon": "currency-euro", - "url": "/invoices", - }, - ], - }, - { - "id": "customers", - "label": "Customers", - "items": [ - { - "id": VendorMenuItem.CUSTOMERS.value, - "label": "All Customers", - "icon": "user-group", - "url": "/customers", - }, - { - "id": VendorMenuItem.MESSAGES.value, - "label": "Messages", - "icon": "chat-bubble-left-right", - "url": "/messages", - }, - { - "id": VendorMenuItem.NOTIFICATIONS.value, - "label": "Notifications", - "icon": "bell", - "url": "/notifications", - }, - ], - }, - { - "id": "shop", - "label": "Shop & Content", - "items": [ - { - "id": VendorMenuItem.CONTENT_PAGES.value, - "label": "Content Pages", - "icon": "document-text", - "url": "/content-pages", - }, - { - "id": VendorMenuItem.MEDIA.value, - "label": "Media Library", - "icon": "photograph", - "url": "/media", - }, - ], - }, - { - "id": "account", - "label": "Account & Settings", - "items": [ - { - "id": VendorMenuItem.TEAM.value, - "label": "Team", - "icon": "user-group", - "url": "/team", - }, - { - "id": VendorMenuItem.PROFILE.value, - "label": "Profile", - "icon": "user", - "url": "/profile", - }, - { - "id": VendorMenuItem.BILLING.value, - "label": "Billing", - "icon": "credit-card", - "url": "/billing", - }, - { - "id": VendorMenuItem.EMAIL_TEMPLATES.value, - "label": "Email Templates", - "icon": "mail", - "url": "/email-templates", - }, - { - "id": VendorMenuItem.SETTINGS.value, - "label": "Settings", - "icon": "adjustments", - "url": "/settings", - }, - ], - }, - ], -} - - -# ============================================================================= -# Helper Functions -# ============================================================================= - - -def get_all_menu_item_ids(frontend_type: FrontendType) -> set[str]: - """Get all menu item IDs for a frontend type.""" - registry = ( - ADMIN_MENU_REGISTRY if frontend_type == FrontendType.ADMIN else VENDOR_MENU_REGISTRY - ) - items = set() - for section in registry["sections"]: - for item in section["items"]: - items.add(item["id"]) - return items - - -def get_menu_item(frontend_type: FrontendType, menu_item_id: str) -> dict | None: - """Get a menu item definition by ID.""" - registry = ( - ADMIN_MENU_REGISTRY if frontend_type == FrontendType.ADMIN else VENDOR_MENU_REGISTRY - ) - for section in registry["sections"]: - for item in section["items"]: - if item["id"] == menu_item_id: - return {**item, "section_id": section["id"], "section_label": section.get("label")} - return None - - -def is_super_admin_only_item(menu_item_id: str) -> bool: - """Check if a menu item is in a super_admin_only section.""" - for section in ADMIN_MENU_REGISTRY["sections"]: - if section.get("super_admin_only"): - for item in section["items"]: - if item["id"] == menu_item_id: - return True - return False diff --git a/app/modules/core/services/menu_discovery_service.py b/app/modules/core/services/menu_discovery_service.py index e3118e09..490bb665 100644 --- a/app/modules/core/services/menu_discovery_service.py +++ b/app/modules/core/services/menu_discovery_service.py @@ -372,6 +372,101 @@ class MenuDiscoveryService: return mandatory_ids + def get_all_menu_item_ids( + self, + frontend_type: FrontendType, + ) -> set[str]: + """ + Get set of all menu item IDs for a frontend type. + + Args: + frontend_type: Frontend type to get item IDs for + + Returns: + Set of all menu item IDs from all modules + """ + from app.modules.registry import MODULES + + item_ids = set() + + for module_def in MODULES.values(): + for section in module_def.menus.get(frontend_type, []): + for item in section.items: + item_ids.add(item.id) + + return item_ids + + def get_menu_item( + self, + frontend_type: FrontendType, + menu_item_id: str, + ) -> DiscoveredMenuItem | None: + """ + Get a specific menu item by ID. + + Args: + frontend_type: Frontend type to search in + menu_item_id: Menu item ID to look up + + Returns: + DiscoveredMenuItem if found, None otherwise + """ + from app.modules.registry import MODULES + + for module_code, module_def in MODULES.items(): + for section in module_def.menus.get(frontend_type, []): + for item in section.items: + if item.id == menu_item_id: + return DiscoveredMenuItem( + id=item.id, + label_key=item.label_key, + icon=item.icon, + route=item.route, + order=item.order, + is_mandatory=item.is_mandatory, + requires_permission=item.requires_permission, + badge_source=item.badge_source, + is_super_admin_only=item.is_super_admin_only, + module_code=module_code, + section_id=section.id, + section_label_key=section.label_key, + section_order=section.order, + ) + + return None + + def is_super_admin_only_item( + self, + menu_item_id: str, + frontend_type: FrontendType = FrontendType.ADMIN, + ) -> bool: + """ + Check if a menu item is super-admin only. + + An item is super-admin only if either: + - The item itself has is_super_admin_only=True + - The section containing the item has is_super_admin_only=True + + Args: + menu_item_id: Menu item ID to check + frontend_type: Frontend type to search in + + Returns: + True if the item is super-admin only + """ + from app.modules.registry import MODULES + + for module_def in MODULES.values(): + for section in module_def.menus.get(frontend_type, []): + # Check if section is super-admin only + section_is_super_admin = section.is_super_admin_only + + for item in section.items: + if item.id == menu_item_id: + return section_is_super_admin or item.is_super_admin_only + + return False + def get_menu_item_module( self, menu_item_id: str, diff --git a/app/modules/core/services/menu_service.py b/app/modules/core/services/menu_service.py index d7bee972..a50dd724 100644 --- a/app/modules/core/services/menu_service.py +++ b/app/modules/core/services/menu_service.py @@ -34,15 +34,8 @@ from dataclasses import dataclass from sqlalchemy.orm import Session -from app.config.menu_registry import ( - ADMIN_MENU_REGISTRY, - VENDOR_MENU_REGISTRY, - get_all_menu_item_ids, - get_menu_item, - is_super_admin_only_item, -) from app.modules.service import module_service -from app.modules.core.models import AdminMenuConfig, MANDATORY_MENU_ITEMS +from app.modules.core.models import AdminMenuConfig from app.modules.core.services.menu_discovery_service import menu_discovery_service from app.modules.enums import FrontendType @@ -108,7 +101,7 @@ class MenuService: True if menu item is visible/accessible """ # Validate menu item exists in registry - all_items = get_all_menu_item_ids(frontend_type) + all_items = menu_discovery_service.get_all_menu_item_ids(frontend_type) if menu_item_id not in all_items: logger.warning(f"Unknown menu item: {menu_item_id} for {frontend_type.value}") return False @@ -121,7 +114,8 @@ class MenuService: return False # Mandatory items are always accessible (if module is enabled) - if menu_item_id in MANDATORY_MENU_ITEMS.get(frontend_type, set()): + mandatory_items = menu_discovery_service.get_mandatory_item_ids(frontend_type) + if menu_item_id in mandatory_items: return True # No scope specified - show all by default (fallback for unconfigured) @@ -161,8 +155,8 @@ class MenuService: Returns: Set of visible menu item IDs """ - all_items = get_all_menu_item_ids(frontend_type) - mandatory_items = MANDATORY_MENU_ITEMS.get(frontend_type, set()) + all_items = menu_discovery_service.get_all_menu_item_ids(frontend_type) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(frontend_type) # Filter by module enablement if platform is specified if platform_id: @@ -294,60 +288,47 @@ class MenuService: Returns: List of MenuItemConfig with current visibility state and module info """ - from app.modules.registry import get_menu_item_module - - registry = ( - ADMIN_MENU_REGISTRY if frontend_type == FrontendType.ADMIN else VENDOR_MENU_REGISTRY - ) - shown_items = self._get_shown_items(db, frontend_type, platform_id=platform_id) - mandatory_items = MANDATORY_MENU_ITEMS.get(frontend_type, set()) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(frontend_type) # Get module-available items + all_item_ids = menu_discovery_service.get_all_menu_item_ids(frontend_type) module_available_items = module_service.filter_menu_items_by_modules( - db, platform_id, get_all_menu_item_ids(frontend_type), frontend_type + db, platform_id, all_item_ids, frontend_type ) + # Get all menu items from discovery service + all_items = menu_discovery_service.get_all_menu_items(frontend_type) + result = [] - for section in registry["sections"]: - section_id = section["id"] - section_label = section.get("label") - is_super_admin_section = section.get("super_admin_only", False) + for item in all_items: + # Check if module is enabled for this item + is_module_enabled = item.id in module_available_items - for item in section["items"]: - item_id = item["id"] + # If no config exists (shown_items is None), show all by default + # Otherwise, item is visible if in shown_items or mandatory + # Note: visibility config is independent of module enablement + is_visible = ( + shown_items is None + or item.id in shown_items + or item.id in mandatory_items + ) - # Check if module is enabled for this item - is_module_enabled = item_id in module_available_items - module_code = get_menu_item_module(item_id, frontend_type) - - # If no config exists (shown_items is None), show all by default - # Otherwise, item is visible if in shown_items or mandatory - # Note: visibility config is independent of module enablement - is_visible = ( - shown_items is None - or item_id in shown_items - or item_id in mandatory_items - ) - - # Item is super admin only if section or item is marked as such - is_item_super_admin_only = is_super_admin_section or item.get("super_admin_only", False) - - result.append( - MenuItemConfig( - id=item_id, - label=item["label"], - icon=item["icon"], - url=item["url"], - section_id=section_id, - section_label=section_label, - is_visible=is_visible, - is_mandatory=item_id in mandatory_items, - is_super_admin_only=is_item_super_admin_only, - is_module_enabled=is_module_enabled, - module_code=module_code, - ) + result.append( + MenuItemConfig( + id=item.id, + label=item.label_key, + icon=item.icon, + url=item.route, + section_id=item.section_id, + section_label=item.section_label_key, + is_visible=is_visible, + is_mandatory=item.id in mandatory_items, + is_super_admin_only=item.is_super_admin_only, + is_module_enabled=is_module_enabled, + module_code=item.module_code, ) + ) return result @@ -369,47 +350,39 @@ class MenuService: Returns: List of MenuItemConfig with current visibility state """ - from app.modules.registry import get_menu_item_module - shown_items = self._get_shown_items( db, FrontendType.ADMIN, user_id=user_id ) - mandatory_items = MANDATORY_MENU_ITEMS.get(FrontendType.ADMIN, set()) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(FrontendType.ADMIN) + + # Get all menu items from discovery service + all_items = menu_discovery_service.get_all_menu_items(FrontendType.ADMIN) result = [] - for section in ADMIN_MENU_REGISTRY["sections"]: - section_id = section["id"] - section_label = section.get("label") - is_super_admin_section = section.get("super_admin_only", False) + for item in all_items: + # If no config exists (shown_items is None), show all by default + # Otherwise, item is visible if in shown_items or mandatory + is_visible = ( + shown_items is None + or item.id in shown_items + or item.id in mandatory_items + ) - for item in section["items"]: - item_id = item["id"] - module_code = get_menu_item_module(item_id, FrontendType.ADMIN) - - # If no config exists (shown_items is None), show all by default - # Otherwise, item is visible if in shown_items or mandatory - is_visible = ( - shown_items is None - or item_id in shown_items - or item_id in mandatory_items - ) - # Item is super admin only if section or item is marked as such - is_item_super_admin_only = is_super_admin_section or item.get("super_admin_only", False) - result.append( - MenuItemConfig( - id=item_id, - label=item["label"], - icon=item["icon"], - url=item["url"], - section_id=section_id, - section_label=section_label, - is_visible=is_visible, - is_mandatory=item_id in mandatory_items, - is_super_admin_only=is_item_super_admin_only, - is_module_enabled=True, # Super admins see all modules - module_code=module_code, - ) + result.append( + MenuItemConfig( + id=item.id, + label=item.label_key, + icon=item.icon, + url=item.route, + section_id=item.section_id, + section_label=item.section_label_key, + is_visible=is_visible, + is_mandatory=item.id in mandatory_items, + is_super_admin_only=item.is_super_admin_only, + is_module_enabled=True, # Super admins see all modules + module_code=item.module_code, ) + ) return result @@ -443,12 +416,12 @@ class MenuService: ValueError: If user_id is provided for vendor frontend """ # Validate menu item exists - all_items = get_all_menu_item_ids(frontend_type) + all_items = menu_discovery_service.get_all_menu_item_ids(frontend_type) if menu_item_id not in all_items: raise ValueError(f"Unknown menu item: {menu_item_id}") # Check if mandatory - mandatory items are always visible, no need to store - mandatory = MANDATORY_MENU_ITEMS.get(frontend_type, set()) + mandatory = menu_discovery_service.get_mandatory_item_ids(frontend_type) if menu_item_id in mandatory: if not is_visible: raise ValueError(f"Cannot hide mandatory menu item: {menu_item_id}") @@ -559,8 +532,8 @@ class MenuService: # Create records with is_visible=False for all non-mandatory items # This makes "reset" mean "hide everything except mandatory" - all_items = get_all_menu_item_ids(frontend_type) - mandatory_items = MANDATORY_MENU_ITEMS.get(frontend_type, set()) + all_items = menu_discovery_service.get_all_menu_item_ids(frontend_type) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(frontend_type) for item_id in all_items: if item_id not in mandatory_items: @@ -603,8 +576,8 @@ class MenuService: logger.info(f"Reset menu config for user {user_id}: deleted {deleted} rows") # Create records with is_visible=False for all non-mandatory items - all_items = get_all_menu_item_ids(FrontendType.ADMIN) - mandatory_items = MANDATORY_MENU_ITEMS.get(FrontendType.ADMIN, set()) + all_items = menu_discovery_service.get_all_menu_item_ids(FrontendType.ADMIN) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(FrontendType.ADMIN) for item_id in all_items: if item_id not in mandatory_items: @@ -650,8 +623,8 @@ class MenuService: ) # Create records with is_visible=True for all non-mandatory items - all_items = get_all_menu_item_ids(frontend_type) - mandatory_items = MANDATORY_MENU_ITEMS.get(frontend_type, set()) + all_items = menu_discovery_service.get_all_menu_item_ids(frontend_type) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(frontend_type) for item_id in all_items: if item_id not in mandatory_items: @@ -692,8 +665,8 @@ class MenuService: logger.info(f"Show all menu config for user {user_id}: deleted {deleted} rows") # Create records with is_visible=True for all non-mandatory items - all_items = get_all_menu_item_ids(FrontendType.ADMIN) - mandatory_items = MANDATORY_MENU_ITEMS.get(FrontendType.ADMIN, set()) + all_items = menu_discovery_service.get_all_menu_item_ids(FrontendType.ADMIN) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(FrontendType.ADMIN) for item_id in all_items: if item_id not in mandatory_items: @@ -762,8 +735,8 @@ class MenuService: logger.info(f"Cleaned up {deleted} old menu config records before initialization") # Get all menu items for this frontend - all_items = get_all_menu_item_ids(frontend_type) - mandatory_items = MANDATORY_MENU_ITEMS.get(frontend_type, set()) + all_items = menu_discovery_service.get_all_menu_item_ids(frontend_type) + mandatory_items = menu_discovery_service.get_mandatory_item_ids(frontend_type) # Create visible records for all non-mandatory items for item_id in all_items: