refactor: remove all backward compatibility code across 70 files
Some checks failed
Some checks failed
Clean up 28 backward compatibility instances identified in the codebase. The app is not live, so all shims are replaced with the target architecture: - Remove legacy Inventory.location column (use bin_location exclusively) - Remove dashboard _extract_metric_value helper (use flat metrics dict) - Remove legacy stat field duplicates (total_stores, total_imports, etc.) - Remove 13 re-export shims and class aliases across modules - Remove module-enabling JSON fallback (use PlatformModule junction table) - Remove menu_to_legacy_format() conversion (return dataclasses directly) - Remove title/description from MarketplaceProductBase schema - Clean billing convenience method docstrings - Clean test fixtures and backward-compat comments - Add PlatformModule seeding to init_production.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,11 +5,8 @@ Module service for platform module operations.
|
||||
Provides methods to check module enablement, get enabled modules,
|
||||
and filter menu items based on module configuration.
|
||||
|
||||
Module configuration can be stored in two places:
|
||||
1. PlatformModule junction table (preferred, auditable)
|
||||
2. Platform.settings["enabled_modules"] (fallback, legacy)
|
||||
|
||||
If neither is configured, all modules are enabled (backwards compatibility).
|
||||
Module configuration is stored in the PlatformModule junction table,
|
||||
which provides auditability, per-module config, and explicit state tracking.
|
||||
"""
|
||||
|
||||
import logging
|
||||
@@ -37,27 +34,16 @@ class ModuleService:
|
||||
Handles module enablement checking, module listing, and menu item filtering
|
||||
based on enabled modules.
|
||||
|
||||
Module configuration is stored in two places (with fallback):
|
||||
1. PlatformModule junction table (preferred, auditable)
|
||||
2. Platform.settings["enabled_modules"] (legacy fallback)
|
||||
Module configuration is stored in the PlatformModule junction table,
|
||||
which provides auditability, per-module config, and explicit state tracking.
|
||||
|
||||
The service checks the junction table first. If no records exist,
|
||||
it falls back to the JSON settings for backwards compatibility.
|
||||
|
||||
If neither is configured, all modules are enabled (backwards compatibility).
|
||||
If no PlatformModule records exist for a platform, no optional modules are
|
||||
enabled (only core modules). Use seed scripts or the admin API to configure
|
||||
module enablement for each platform.
|
||||
|
||||
Example PlatformModule records:
|
||||
PlatformModule(platform_id=1, module_code="billing", is_enabled=True, config={"stripe_mode": "live"})
|
||||
PlatformModule(platform_id=1, module_code="inventory", is_enabled=True, config={"low_stock_threshold": 10})
|
||||
|
||||
Legacy Platform.settings (fallback):
|
||||
{
|
||||
"enabled_modules": ["core", "billing", "inventory", "orders"],
|
||||
"module_config": {
|
||||
"billing": {"stripe_mode": "live"},
|
||||
"inventory": {"low_stock_threshold": 10}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
# =========================================================================
|
||||
@@ -133,11 +119,8 @@ class ModuleService:
|
||||
"""
|
||||
Get enabled module codes for a platform.
|
||||
|
||||
Checks two sources with fallback:
|
||||
1. PlatformModule junction table (preferred, auditable)
|
||||
2. Platform.settings["enabled_modules"] (legacy fallback)
|
||||
|
||||
If neither is configured, returns all module codes (backwards compatibility).
|
||||
Uses the PlatformModule junction table exclusively. If no records exist,
|
||||
returns only core modules (empty set of optional modules).
|
||||
Always includes core modules.
|
||||
|
||||
Args:
|
||||
@@ -149,29 +132,17 @@ class ModuleService:
|
||||
"""
|
||||
platform = db.query(Platform).filter(Platform.id == platform_id).first()
|
||||
if not platform:
|
||||
logger.warning(f"Platform {platform_id} not found, returning all modules")
|
||||
return set(MODULES.keys())
|
||||
logger.warning(f"Platform {platform_id} not found, returning core modules only")
|
||||
return get_core_module_codes()
|
||||
|
||||
# Try junction table first (preferred)
|
||||
# Query junction table for enabled modules
|
||||
platform_modules = (
|
||||
db.query(PlatformModule)
|
||||
.filter(PlatformModule.platform_id == platform_id)
|
||||
.all()
|
||||
)
|
||||
|
||||
if platform_modules:
|
||||
# Use junction table data
|
||||
enabled_set = {pm.module_code for pm in platform_modules if pm.is_enabled}
|
||||
else:
|
||||
# Fallback to JSON settings (legacy)
|
||||
settings = platform.settings or {}
|
||||
enabled_modules = settings.get("enabled_modules")
|
||||
|
||||
# If not configured, enable all modules (backwards compatibility)
|
||||
if enabled_modules is None:
|
||||
return set(MODULES.keys())
|
||||
|
||||
enabled_set = set(enabled_modules)
|
||||
enabled_set = {pm.module_code for pm in platform_modules if pm.is_enabled}
|
||||
|
||||
# Always include core modules
|
||||
core_codes = get_core_module_codes()
|
||||
@@ -187,72 +158,6 @@ class ModuleService:
|
||||
|
||||
return enabled_set
|
||||
|
||||
def _migrate_json_to_junction_table(
|
||||
self,
|
||||
db: Session,
|
||||
platform_id: int,
|
||||
user_id: int | None = None,
|
||||
) -> None:
|
||||
"""
|
||||
Migrate JSON settings to junction table records.
|
||||
|
||||
Called when first creating a junction table record for a platform
|
||||
that previously used JSON settings. This ensures consistency when
|
||||
mixing junction table and JSON approaches.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
platform_id: Platform ID
|
||||
user_id: ID of user performing the migration (for audit)
|
||||
"""
|
||||
# Check if any junction table records exist
|
||||
existing_count = (
|
||||
db.query(PlatformModule)
|
||||
.filter(PlatformModule.platform_id == platform_id)
|
||||
.count()
|
||||
)
|
||||
|
||||
if existing_count > 0:
|
||||
# Already using junction table
|
||||
return
|
||||
|
||||
platform = db.query(Platform).filter(Platform.id == platform_id).first()
|
||||
if not platform:
|
||||
return
|
||||
|
||||
settings = platform.settings or {}
|
||||
enabled_modules = settings.get("enabled_modules")
|
||||
|
||||
if enabled_modules is None:
|
||||
# No JSON settings, start fresh with all modules enabled
|
||||
enabled_codes = set(MODULES.keys())
|
||||
else:
|
||||
enabled_codes = set(enabled_modules) | get_core_module_codes()
|
||||
|
||||
now = datetime.now(UTC)
|
||||
|
||||
# Create junction table records for all known modules
|
||||
for code in MODULES:
|
||||
is_enabled = code in enabled_codes
|
||||
pm = PlatformModule(
|
||||
platform_id=platform_id,
|
||||
module_code=code,
|
||||
is_enabled=is_enabled,
|
||||
enabled_at=now if is_enabled else None,
|
||||
enabled_by_user_id=user_id if is_enabled else None,
|
||||
disabled_at=None if is_enabled else now,
|
||||
disabled_by_user_id=None if is_enabled else user_id,
|
||||
config={},
|
||||
)
|
||||
db.add(pm)
|
||||
|
||||
# Flush to ensure records are visible to subsequent queries
|
||||
db.flush()
|
||||
|
||||
logger.info(
|
||||
f"Migrated platform {platform_id} from JSON settings to junction table"
|
||||
)
|
||||
|
||||
def _resolve_dependencies(self, enabled_codes: set[str]) -> set[str]:
|
||||
"""
|
||||
Resolve module dependencies by adding required modules.
|
||||
@@ -383,9 +288,7 @@ class ModuleService:
|
||||
"""
|
||||
Get module-specific configuration for a platform.
|
||||
|
||||
Checks two sources with fallback:
|
||||
1. PlatformModule.config (preferred, auditable)
|
||||
2. Platform.settings["module_config"] (legacy fallback)
|
||||
Uses the PlatformModule junction table for configuration storage.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
@@ -395,7 +298,6 @@ class ModuleService:
|
||||
Returns:
|
||||
Module configuration dict (empty if not configured)
|
||||
"""
|
||||
# Try junction table first (preferred)
|
||||
platform_module = (
|
||||
db.query(PlatformModule)
|
||||
.filter(
|
||||
@@ -408,14 +310,7 @@ class ModuleService:
|
||||
if platform_module:
|
||||
return platform_module.config or {}
|
||||
|
||||
# Fallback to JSON settings (legacy)
|
||||
platform = db.query(Platform).filter(Platform.id == platform_id).first()
|
||||
if not platform:
|
||||
return {}
|
||||
|
||||
settings = platform.settings or {}
|
||||
module_configs = settings.get("module_config", {})
|
||||
return module_configs.get(module_code, {})
|
||||
return {}
|
||||
|
||||
def set_module_config(
|
||||
self,
|
||||
@@ -569,7 +464,7 @@ class ModuleService:
|
||||
Enable a single module for a platform.
|
||||
|
||||
Also enables required dependencies.
|
||||
Uses junction table for auditability when available.
|
||||
Uses the PlatformModule junction table for auditability.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
@@ -589,9 +484,6 @@ class ModuleService:
|
||||
logger.error(f"Platform {platform_id} not found")
|
||||
return False
|
||||
|
||||
# Migrate JSON settings to junction table if needed
|
||||
self._migrate_json_to_junction_table(db, platform_id, user_id)
|
||||
|
||||
now = datetime.now(UTC)
|
||||
|
||||
# Enable this module and its dependencies
|
||||
@@ -644,7 +536,7 @@ class ModuleService:
|
||||
|
||||
Core modules cannot be disabled.
|
||||
Also disables modules that depend on this one.
|
||||
Uses junction table for auditability when available.
|
||||
Uses the PlatformModule junction table for auditability.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
@@ -669,9 +561,6 @@ class ModuleService:
|
||||
logger.error(f"Platform {platform_id} not found")
|
||||
return False
|
||||
|
||||
# Migrate JSON settings to junction table if needed
|
||||
self._migrate_json_to_junction_table(db, platform_id, user_id)
|
||||
|
||||
now = datetime.now(UTC)
|
||||
|
||||
# Get modules to disable (this one + dependents)
|
||||
@@ -754,8 +643,9 @@ class ModuleService:
|
||||
"""
|
||||
platform = db.query(Platform).filter(Platform.code == platform_code).first()
|
||||
if not platform:
|
||||
logger.warning(f"Platform '{platform_code}' not found, returning all modules")
|
||||
return list(MODULES.values())
|
||||
logger.warning(f"Platform '{platform_code}' not found, returning core modules only")
|
||||
core_codes = get_core_module_codes()
|
||||
return [MODULES[code] for code in core_codes if code in MODULES]
|
||||
|
||||
return self.get_platform_modules(db, platform.id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user