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>
This commit is contained in:
391
app/modules/registry.py
Normal file
391
app/modules/registry.py
Normal file
@@ -0,0 +1,391 @@
|
||||
# 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",
|
||||
]
|
||||
Reference in New Issue
Block a user