Files
orion/app/modules/registry.py
Samir Boulahtit 5be42c5907 feat: implement modular platform architecture (Phase 1)
Add module system for enabling/disabling feature bundles per platform.

Module System:
- ModuleDefinition dataclass for defining modules
- 12 modules: core, platform-admin, billing, inventory, orders,
  marketplace, customers, cms, analytics, messaging, dev-tools, monitoring
- Core modules (core, platform-admin) cannot be disabled
- Module dependencies (e.g., marketplace requires inventory)

MenuService Integration:
- Menu items filtered by module enablement
- MenuItemConfig includes is_module_enabled and module_code fields
- Module-disabled items hidden from sidebar

Platform Configuration:
- BasePlatformConfig.enabled_modules property
- OMS: all modules enabled (full commerce)
- Loyalty: focused subset (no billing/inventory/orders/marketplace)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 21:42:44 +01:00

392 lines
11 KiB
Python

# app/modules/registry.py
"""
Module registry defining all available platform modules.
Each module bundles related features and menu items that can be
enabled/disabled per platform. Core modules cannot be disabled.
Module Granularity (Medium - ~12 modules):
Matches menu sections for intuitive mapping between modules and UI.
"""
from app.modules.base import ModuleDefinition
from models.database.admin_menu_config import FrontendType
# =============================================================================
# Module Definitions
# =============================================================================
MODULES: dict[str, ModuleDefinition] = {
# =========================================================================
# Core Modules (Always Enabled)
# =========================================================================
"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",
],
},
),
"platform-admin": ModuleDefinition(
code="platform-admin",
name="Platform Administration",
description="Company, vendor, and admin user management. Required for multi-tenant operation.",
is_core=True,
features=[
"company_management",
"vendor_management",
"admin_user_management",
"platform_management",
],
menu_items={
FrontendType.ADMIN: [
"admin-users",
"companies",
"vendors",
"platforms",
],
FrontendType.VENDOR: [
"team",
],
},
),
# =========================================================================
# Optional Modules
# =========================================================================
"billing": ModuleDefinition(
code="billing",
name="Billing & Subscriptions",
description="Subscription tiers, billing history, and payment processing.",
features=[
"subscription_management",
"billing_history",
"stripe_integration",
"invoice_generation",
],
menu_items={
FrontendType.ADMIN: [
"subscription-tiers",
"subscriptions",
"billing-history",
],
FrontendType.VENDOR: [
"billing",
"invoices",
],
},
),
"inventory": ModuleDefinition(
code="inventory",
name="Inventory Management",
description="Stock levels, locations, and low stock alerts.",
features=[
"inventory_basic",
"inventory_locations",
"low_stock_alerts",
"inventory_purchase_orders",
"product_management",
],
menu_items={
FrontendType.ADMIN: [
"inventory",
"vendor-products",
],
FrontendType.VENDOR: [
"products",
"inventory",
],
},
),
"orders": ModuleDefinition(
code="orders",
name="Order Management",
description="Order processing, fulfillment, and tracking.",
features=[
"order_management",
"order_bulk_actions",
"order_export",
"automation_rules",
"fulfillment_tracking",
"shipping_management",
],
menu_items={
FrontendType.ADMIN: [
"orders",
],
FrontendType.VENDOR: [
"orders",
],
},
),
"marketplace": ModuleDefinition(
code="marketplace",
name="Marketplace (Letzshop)",
description="Letzshop integration for product sync and order import.",
requires=["inventory"], # Depends on inventory module
features=[
"letzshop_sync",
"marketplace_import",
"product_sync",
],
menu_items={
FrontendType.ADMIN: [
"marketplace-letzshop",
],
FrontendType.VENDOR: [
"marketplace",
"letzshop",
],
},
),
"customers": ModuleDefinition(
code="customers",
name="Customer Management",
description="Customer database, profiles, and segmentation.",
features=[
"customer_view",
"customer_export",
"customer_profiles",
"customer_segmentation",
],
menu_items={
FrontendType.ADMIN: [
"customers",
],
FrontendType.VENDOR: [
"customers",
],
},
),
"cms": ModuleDefinition(
code="cms",
name="Content Management",
description="Content pages, media library, and vendor themes.",
features=[
"cms_basic",
"cms_custom_pages",
"cms_unlimited_pages",
"cms_templates",
"cms_seo",
"media_library",
],
menu_items={
FrontendType.ADMIN: [
"content-pages",
"vendor-themes",
],
FrontendType.VENDOR: [
"content-pages",
"media",
],
},
),
"analytics": ModuleDefinition(
code="analytics",
name="Analytics & Reporting",
description="Dashboard analytics, custom reports, and data exports.",
features=[
"basic_reports",
"analytics_dashboard",
"custom_reports",
"export_reports",
],
menu_items={
FrontendType.ADMIN: [
# Analytics appears in dashboard for admin
],
FrontendType.VENDOR: [
"analytics",
],
},
),
"messaging": ModuleDefinition(
code="messaging",
name="Messaging & Notifications",
description="Internal messages, customer communication, and notifications.",
features=[
"customer_messaging",
"internal_messages",
"notification_center",
],
menu_items={
FrontendType.ADMIN: [
"messages",
"notifications",
],
FrontendType.VENDOR: [
"messages",
"notifications",
],
},
),
"dev-tools": ModuleDefinition(
code="dev-tools",
name="Developer Tools",
description="Component library and icon browser for development.",
features=[
"component_library",
"icon_browser",
],
menu_items={
FrontendType.ADMIN: [
"components",
"icons",
],
FrontendType.VENDOR: [],
},
),
"monitoring": ModuleDefinition(
code="monitoring",
name="Platform Monitoring",
description="Logs, background tasks, imports, and system health.",
features=[
"application_logs",
"background_tasks",
"import_jobs",
"capacity_monitoring",
"testing_hub",
"code_quality",
],
menu_items={
FrontendType.ADMIN: [
"imports",
"background-tasks",
"logs",
"platform-health",
"testing",
"code-quality",
],
FrontendType.VENDOR: [],
},
),
}
# =============================================================================
# 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 [m for m in MODULES.values() if m.is_core]
def get_core_module_codes() -> set[str]:
"""Get codes of all core modules."""
return {m.code for m in MODULES.values() if m.is_core}
def get_optional_modules() -> list[ModuleDefinition]:
"""Get all optional modules (can be enabled/disabled)."""
return [m for m in MODULES.values() if not m.is_core]
def get_all_module_codes() -> set[str]:
"""Get all module codes."""
return set(MODULES.keys())
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
# 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__ = [
"MODULES",
"get_module",
"get_core_modules",
"get_core_module_codes",
"get_optional_modules",
"get_all_module_codes",
"get_menu_item_module",
"get_feature_module",
"validate_module_dependencies",
]