# app/modules/registry.py """ Module registry defining all available platform modules. The module system uses a three-tier classification: 1. CORE MODULES (4) - Always enabled, cannot be disabled - core: Dashboard, settings, profile - tenancy: Platform, company, vendor, admin user management - cms: Content pages, media library, themes - customers: Customer database, profiles, segmentation 2. OPTIONAL MODULES (7) - Can be enabled/disabled per platform - payments: Payment gateway integrations (Stripe, PayPal, etc.) - billing: Platform subscriptions, vendor invoices (requires: payments) - inventory: Stock management, locations - orders: Order management, customer checkout (requires: payments) - marketplace: Letzshop integration (requires: inventory) - analytics: Reports, dashboards - messaging: Messages, notifications 3. INTERNAL MODULES (2) - Admin-only tools, not customer-facing - dev-tools: Component library, icons - monitoring: Logs, background tasks, Flower link, Grafana dashboards Module Structure: - Inline modules: Defined directly in this file (core, tenancy) - Extracted modules: Imported from app/modules/{module}/ (billing, etc.) As modules are extracted to their own directories, they are imported here and their inline definitions are replaced. """ from app.modules.base import ModuleDefinition from models.database.admin_menu_config import FrontendType # Import extracted modules from app.modules.billing.definition import billing_module from app.modules.payments.definition import payments_module from app.modules.inventory.definition import inventory_module from app.modules.marketplace.definition import marketplace_module from app.modules.orders.definition import orders_module from app.modules.customers.definition import customers_module from app.modules.cms.definition import cms_module from app.modules.analytics.definition import analytics_module from app.modules.messaging.definition import messaging_module from app.modules.dev_tools.definition import dev_tools_module from app.modules.monitoring.definition import monitoring_module # ============================================================================= # Core Modules (Always Enabled, Cannot Be Disabled) # ============================================================================= CORE_MODULES: dict[str, ModuleDefinition] = { "core": ModuleDefinition( code="core", name="Core Platform", description="Dashboard, settings, and profile management. Required for basic operation.", is_core=True, features=[ "dashboard", "settings", "profile", ], menu_items={ FrontendType.ADMIN: [ "dashboard", "settings", "email-templates", "my-menu", ], FrontendType.VENDOR: [ "dashboard", "profile", "settings", "email-templates", ], }, ), "tenancy": ModuleDefinition( code="tenancy", name="Tenancy Management", description="Platform, company, vendor, and admin user management. Required for multi-tenant operation.", is_core=True, features=[ "platform_management", "company_management", "vendor_management", "admin_user_management", ], menu_items={ FrontendType.ADMIN: [ "platforms", "companies", "vendors", "admin-users", ], FrontendType.VENDOR: [ "team", ], }, ), # CMS module - imported from app/modules/cms/ "cms": cms_module, # Customers module - imported from app/modules/customers/ "customers": customers_module, } # ============================================================================= # Optional Modules (Can Be Enabled/Disabled Per Platform) # ============================================================================= OPTIONAL_MODULES: dict[str, ModuleDefinition] = { # Payments module - imported from app/modules/payments/ # Gateway integrations (Stripe, PayPal, etc.) "payments": payments_module, # Billing module - imported from app/modules/billing/ # Platform subscriptions, vendor invoices (requires: payments) "billing": billing_module, # Inventory module - imported from app/modules/inventory/ "inventory": inventory_module, # Orders module - imported from app/modules/orders/ # Order management, customer checkout (requires: payments) "orders": orders_module, # Marketplace module - imported from app/modules/marketplace/ # Letzshop integration (requires: inventory) "marketplace": marketplace_module, # Analytics module - imported from app/modules/analytics/ "analytics": analytics_module, # Messaging module - imported from app/modules/messaging/ "messaging": messaging_module, } # ============================================================================= # Internal Modules (Admin-Only, Not Customer-Facing) # ============================================================================= INTERNAL_MODULES: dict[str, ModuleDefinition] = { # Dev-Tools module - imported from app/modules/dev_tools/ "dev-tools": dev_tools_module, # Monitoring module - imported from app/modules/monitoring/ "monitoring": monitoring_module, } # ============================================================================= # Combined Module Registry # ============================================================================= MODULES: dict[str, ModuleDefinition] = { **CORE_MODULES, **OPTIONAL_MODULES, **INTERNAL_MODULES, } # ============================================================================= # Helper Functions # ============================================================================= def get_module(code: str) -> ModuleDefinition | None: """Get a module definition by code.""" return MODULES.get(code) def get_core_modules() -> list[ModuleDefinition]: """Get all core modules (cannot be disabled).""" return list(CORE_MODULES.values()) def get_core_module_codes() -> set[str]: """Get codes of all core modules.""" return set(CORE_MODULES.keys()) def get_optional_modules() -> list[ModuleDefinition]: """Get all optional modules (can be enabled/disabled).""" return list(OPTIONAL_MODULES.values()) def get_optional_module_codes() -> set[str]: """Get codes of all optional modules.""" return set(OPTIONAL_MODULES.keys()) def get_internal_modules() -> list[ModuleDefinition]: """Get all internal modules (admin-only tools).""" return list(INTERNAL_MODULES.values()) def get_internal_module_codes() -> set[str]: """Get codes of all internal modules.""" return set(INTERNAL_MODULES.keys()) def get_all_module_codes() -> set[str]: """Get all module codes.""" return set(MODULES.keys()) def is_core_module(code: str) -> bool: """Check if a module is a core module.""" return code in CORE_MODULES def is_internal_module(code: str) -> bool: """Check if a module is an internal module.""" return code in INTERNAL_MODULES def get_menu_item_module(menu_item_id: str, frontend_type: FrontendType) -> str | None: """ Find which module provides a specific menu item. Args: menu_item_id: The menu item ID to find frontend_type: The frontend type to search in Returns: Module code if found, None otherwise """ for module in MODULES.values(): if menu_item_id in module.get_menu_items(frontend_type): return module.code return None def get_feature_module(feature_code: str) -> str | None: """ Find which module provides a specific feature. Args: feature_code: The feature code to find Returns: Module code if found, None otherwise """ for module in MODULES.values(): if module.has_feature(feature_code): return module.code return None def validate_module_dependencies() -> list[str]: """ Validate that all module dependencies are valid. Returns: List of error messages for invalid dependencies """ errors = [] all_codes = get_all_module_codes() for module in MODULES.values(): for required in module.requires: if required not in all_codes: errors.append( f"Module '{module.code}' requires unknown module '{required}'" ) # Core modules should not depend on optional modules if module.is_core and required not in get_core_module_codes(): errors.append( f"Core module '{module.code}' depends on optional module '{required}'" ) return errors def get_modules_by_tier() -> dict[str, list[ModuleDefinition]]: """ Get modules organized by tier. Returns: Dict with keys 'core', 'optional', 'internal' mapping to module lists """ return { "core": list(CORE_MODULES.values()), "optional": list(OPTIONAL_MODULES.values()), "internal": list(INTERNAL_MODULES.values()), } def get_module_tier(code: str) -> str | None: """ Get the tier classification of a module. Args: code: Module code Returns: 'core', 'optional', 'internal', or None if not found """ if code in CORE_MODULES: return "core" elif code in OPTIONAL_MODULES: return "optional" elif code in INTERNAL_MODULES: return "internal" return None # Validate dependencies on import (development check) _validation_errors = validate_module_dependencies() if _validation_errors: import warnings for error in _validation_errors: warnings.warn(f"Module registry validation: {error}", stacklevel=2) __all__ = [ # Module dictionaries "MODULES", "CORE_MODULES", "OPTIONAL_MODULES", "INTERNAL_MODULES", # Module retrieval "get_module", "get_core_modules", "get_core_module_codes", "get_optional_modules", "get_optional_module_codes", "get_internal_modules", "get_internal_module_codes", "get_all_module_codes", # Module classification "is_core_module", "is_internal_module", "get_modules_by_tier", "get_module_tier", # Menu and feature lookup "get_menu_item_module", "get_feature_module", # Validation "validate_module_dependencies", ]