Files
orion/docs/architecture/cross-module-migration-plan.md
Samir Boulahtit f95db7c0b1
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
feat(roles): add admin store roles page, permission i18n, and menu integration
- Add admin store roles page with merchant→store cascading for superadmin
  and store-only selection for platform admin
- Add permission catalog API with translated labels/descriptions (en/fr/de/lb)
- Add permission translations to all 15 module locale files (60 files total)
- Add info icon tooltips for permission descriptions in role editor
- Add store roles menu item and admin menu item in module definition
- Fix store-selector.js URL construction bug when apiEndpoint has query params
- Add admin store roles API (CRUD + platform scoping)
- Add integration tests for admin store roles and permission catalog

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:31:27 +01:00

18 KiB

Cross-Module Import Migration Plan

Created: 2026-02-26 Status: In Progress Rules: MOD-025, MOD-026

This document tracks the migration of all cross-module model imports to proper service-based access patterns.

Overview

Category Description Files Priority Status
Cat 5 UserContext legacy import path 74 URGENT Pending
Cat 1 Direct queries on another module's models ~47 URGENT Pending
Cat 2 Creating instances across module boundaries ~15 URGENT Pending
Cat 3 Aggregation/count queries across boundaries ~11 URGENT Pending
Cat 4 Join queries involving another module's models ~4 URGENT Pending
P5 Provider pattern gaps (widgets, metrics) ~8 modules Incremental Pending
P6 Route variable naming standardization ~109 files Low Deferred

Cat 5: Move UserContext to Tenancy Module (74 files)

Priority: URGENT — mechanical, low risk, high impact Approach: Move definition, update all imports in one batch

What

UserContext is defined in models/schema/auth.py (legacy location). Per MOD-019, schemas belong in their module. UserContext is a tenancy concern (user identity, platform/store context).

Steps

  1. Move UserContext class from models/schema/auth.py to app/modules/tenancy/schemas/auth.py

    • Keep all properties and methods intact
    • Also move related schemas used alongside it: UserLogin, LogoutResponse, StoreUserResponse
  2. Add re-export in legacy location (temporary backwards compat):

    # models/schema/auth.py
    from app.modules.tenancy.schemas.auth import UserContext  # noqa: F401
    
  3. Update all 74 import sites from:

    from models.schema.auth import UserContext
    

    to:

    from app.modules.tenancy.schemas.auth import UserContext
    
  4. Remove legacy re-export once all imports are updated

Files to Update (by module)

app/api/ (1 file)

  • app/api/deps.py

app/modules/tenancy/ (15 files)

  • routes/api/admin_merchants.py
  • routes/api/admin_module_config.py
  • routes/api/admin_merchant_domains.py
  • routes/api/admin_modules.py
  • routes/api/admin_platforms.py
  • routes/api/admin_store_domains.py
  • routes/api/admin_stores.py
  • routes/api/admin_users.py
  • routes/api/merchant.py
  • routes/api/store_auth.py (also imports LogoutResponse, StoreUserResponse, UserLogin)
  • routes/api/store_profile.py
  • routes/api/store_team.py
  • routes/pages/merchant.py
  • services/admin_platform_service.py
  • tests/integration/test_merchant_routes.py

app/modules/core/ (12 files)

  • routes/api/admin_dashboard.py
  • routes/api/admin_menu_config.py
  • routes/api/admin_settings.py
  • routes/api/merchant_menu.py
  • routes/api/store_dashboard.py
  • routes/api/store_menu.py
  • routes/api/store_settings.py
  • routes/pages/merchant.py
  • tests/integration/test_merchant_dashboard_routes.py
  • tests/integration/test_merchant_menu_routes.py
  • tests/integration/test_store_dashboard_routes.py

app/modules/billing/ (9 files)

  • routes/api/admin.py
  • routes/api/admin_features.py
  • routes/api/store.py
  • routes/api/store_addons.py
  • routes/api/store_checkout.py
  • routes/api/store_features.py
  • routes/api/store_usage.py
  • routes/pages/merchant.py
  • tests/integration/test_merchant_routes.py

app/modules/marketplace/ (8 files)

  • routes/api/admin_letzshop.py
  • routes/api/admin_marketplace.py
  • routes/api/admin_products.py
  • routes/api/store_letzshop.py
  • routes/api/store_marketplace.py
  • routes/api/store_onboarding.py
  • tests/integration/test_store_page_routes.py
  • tests/unit/test_store_page_routes.py

app/modules/messaging/ (7 files)

  • routes/api/admin_email_templates.py
  • routes/api/admin_messages.py
  • routes/api/admin_notifications.py
  • routes/api/store_email_settings.py
  • routes/api/store_email_templates.py
  • routes/api/store_messages.py
  • routes/api/store_notifications.py

app/modules/orders/ (6 files)

  • routes/api/admin.py
  • routes/api/admin_exceptions.py
  • routes/api/store.py
  • routes/api/store_customer_orders.py
  • routes/api/store_exceptions.py
  • routes/api/store_invoices.py

app/modules/monitoring/ (6 files)

  • routes/api/admin_audit.py
  • routes/api/admin_code_quality.py
  • routes/api/admin_logs.py
  • routes/api/admin_platform_health.py
  • routes/api/admin_tasks.py
  • routes/api/admin_tests.py

app/modules/cms/ (4 files)

  • routes/api/admin_images.py
  • routes/api/admin_media.py
  • routes/api/admin_store_themes.py
  • routes/api/store_media.py

app/modules/catalog/ (2 files)

  • routes/api/admin.py
  • routes/api/store.py

app/modules/customers/ (2 files)

  • routes/api/admin.py
  • routes/api/store.py

app/modules/inventory/ (2 files)

  • routes/api/admin.py
  • routes/api/store.py

app/modules/loyalty/ (2 files)

  • routes/pages/merchant.py
  • tests/conftest.py

app/modules/payments/ (1 file)

  • routes/api/store.py

tests/ (1 file)

  • tests/unit/api/test_deps.py

docs/ (2 files — update code examples)

  • docs/architecture/user-context-pattern.md
  • docs/proposals/decouple-modules.md

Cat 1: Direct Queries → Service Methods (~47 violations)

Priority: URGENT — requires creating new service methods first Approach: Per-module, add service methods then migrate consumers

Required New Service Methods

Tenancy Module (most consumed)

The tenancy module needs these public service methods for cross-module consumers:

# app/modules/tenancy/services/merchant_service.py (new or extend existing)
class MerchantService:
    def get_merchant_by_id(self, db, merchant_id) -> Merchant | None
    def get_merchant_by_owner_id(self, db, owner_user_id) -> Merchant | None
    def get_merchants_for_platform(self, db, platform_id, **filters) -> list[Merchant]
    def get_merchant_count(self, db, platform_id=None) -> int
    def search_merchants(self, db, query, platform_id=None) -> list[Merchant]

# app/modules/tenancy/services/store_service.py (extend existing)
class StoreService:
    def get_store_by_id(self, db, store_id) -> Store | None
    def get_stores_for_merchant(self, db, merchant_id) -> list[Store]
    def get_stores_for_platform(self, db, platform_id, **filters) -> list[Store]
    def get_store_count(self, db, merchant_id=None, platform_id=None) -> int
    def get_active_store_count(self, db, platform_id) -> int

# app/modules/tenancy/services/platform_service.py (extend existing)
class PlatformService:
    def get_platform_by_id(self, db, platform_id) -> Platform | None
    def list_platforms(self, db) -> list[Platform]

# app/modules/tenancy/services/user_service.py (extend existing)
class UserService:
    def get_user_by_id(self, db, user_id) -> User | None
    def get_user_by_email(self, db, email) -> User | None
    def get_store_users(self, db, store_id) -> list[StoreUser]

Catalog Module

# app/modules/catalog/services/product_service.py (extend existing)
class ProductService:
    def get_product_by_id(self, db, product_id) -> Product | None
    def get_products_by_ids(self, db, product_ids) -> list[Product]
    def get_product_count(self, db, store_id=None) -> int

Orders Module

# app/modules/orders/services/order_service.py (extend existing)
class OrderService:
    def get_order_by_id(self, db, order_id) -> Order | None
    def get_order_count(self, db, store_id=None, **filters) -> int
    def get_orders_for_store(self, db, store_id, **filters) -> list[Order]

Migration Per Consuming Module

billing → tenancy (13 direct queries)

File What it queries Replace with
services/admin_subscription_service.py:279 db.query(Platform) platform_service.get_platform_by_id()
services/admin_subscription_service.py:285 db.query(Store) store_service.get_store_by_id()
services/admin_subscription_service.py:362 db.query(Store).filter() store_service.get_stores_for_merchant()
services/billing_service.py:158 db.query(Store) store_service.get_store_by_id()
services/billing_service.py:497 db.query(Merchant) merchant_service.get_merchant_by_id()
services/feature_service.py:118,145 db.query(StorePlatform) store_service.get_store_platform()
services/store_platform_sync_service.py:14 db.query(StorePlatform) store_service methods
services/stripe_service.py:26,297,316 db.query(Merchant/Store) merchant_service/store_service
services/subscription_service.py:56,74,178,191 db.query(Platform/Store) service methods
services/usage_service.py:22 db.query(Store) store_service

loyalty → tenancy (10 direct queries)

File What it queries Replace with
services/card_service.py db.query(Store/User) store_service/user_service
services/program_service.py db.query(Merchant) merchant_service
services/admin_loyalty_service.py db.query(Merchant) merchant_service

marketplace → tenancy (5 direct queries)

File What it queries Replace with
services/letzshop/order_service.py:76 db.query(Store) store_service.get_store_by_id()
services/letzshop/order_service.py:100,110 db.query(Order) order_service.get_order_count()
services/marketplace_metrics.py:203 db.query(StorePlatform) store_service.get_store_count()

core → tenancy (3 direct queries)

File What it queries Replace with
services/auth_service.py:156 db.query(Merchant) merchant_service.get_merchant_by_owner_id()
services/auth_service.py:25 db.query(Store) store_service.get_store_by_id()
services/menu_service.py:351 db.query(Store).join() store_service.get_stores_for_merchant()

analytics → tenancy/catalog (4 direct queries)

File What it queries Replace with
services/stats_service.py:69 db.query(Product) product_service.get_product_count()
services/stats_service.py:75 db.query(Product) product_service methods
services/stats_service.py:88-92 db.query(MarketplaceProduct) marketplace service
services/stats_service.py:229 db.query(Product) aggregation product_service

Other modules (various)

Module File Replace with
inventory services/inventory_transaction_service.py:236 order_service.get_order_by_id()
cms services/cms_features.py:160 store_service.get_store_count()
customers services/admin_customer_service.py:16 store_service.get_store_by_id()

Cat 2: Model Creation Across Boundaries (~15 violations)

Priority: URGENT Approach: Add create/factory methods to owning services

Most of these are in test fixtures (acceptable exception) but a few are in production code:

Production Code Violations

File Creates Replace with
contracts/audit.py:117 AdminAuditLog() Use audit provider log_action()
billing/services/store_platform_sync_service.py StorePlatform() store_service.create_store_platform()
marketplace/services/letzshop/order_service.py Order/OrderItem() order_service.create_order()

Test Fixtures (Acceptable — Document as Exception)

Test files creating models from other modules for integration test setup is acceptable but should be documented:

# ACCEPTABLE in tests — document with comment:
# Test fixture: creates tenancy models for integration test setup
merchant = Merchant(name="Test", ...)

Cat 3: Aggregation/Count Queries (~11 violations)

Priority: URGENT Approach: Add count/stats methods to owning services

File Query Replace with
marketplace/services/letzshop/order_service.py:100 func.count(Order.id) order_service.get_order_count()
marketplace/services/letzshop/order_service.py:110 func.count(Order.id) order_service.get_order_count()
catalog/services/catalog_features.py:92 StorePlatform count store_service.get_active_store_count()
cms/services/cms_features.py:160 StorePlatform count store_service.get_active_store_count()
marketplace/services/marketplace_metrics.py:203 StorePlatform count store_service.get_active_store_count()
customers/services/customer_features.py Store count store_service.get_store_count()
inventory/services/inventory_features.py Store count store_service.get_store_count()
orders/services/order_features.py Store count store_service.get_store_count()

Cat 4: Join Queries (~4 violations)

Priority: URGENT Approach: Decompose into service calls or add service methods

File Join Resolution
catalog/services/store_product_service.py:19 .join(Store) Use store_service.get_store_by_id() + own query
core/services/menu_service.py:351 .join(Store) store_service.get_stores_for_merchant()
customers/services/admin_customer_service.py:16 .join(Store) store_service.get_store_by_id() + own query
messaging/services/messaging_service.py:653 .join(StoreUser) user_service.get_store_users() + filter

P5: Provider Pattern Gaps (Incremental)

Priority: MEDIUM — implement as each module is touched

Widget Providers to Add

Currently only 2 modules (marketplace, tenancy) provide dashboard widgets. These modules have valuable dashboard data:

Module Widget Ideas Implementation
orders Recent orders list, order status breakdown services/order_widgets.py
billing Subscription status, revenue trend services/billing_widgets.py
catalog Product summary, category breakdown services/catalog_widgets.py
inventory Stock summary, low-stock alerts services/inventory_widgets.py
loyalty Program stats, member engagement services/loyalty_widgets.py
customers Customer growth, segments services/customer_widgets.py

Metrics Providers to Add

Module Metric Ideas Implementation
loyalty Active programs, total enrollments, points issued services/loyalty_metrics.py
payments Transaction volume, success rate, gateway stats services/payment_metrics.py
analytics Report count, active dashboards services/analytics_metrics.py

Implementation Template

# app/modules/{module}/services/{module}_widgets.py
from app.modules.contracts.widgets import (
    DashboardWidgetProviderProtocol,
    ListWidget,
    BreakdownWidget,
)

class {Module}WidgetProvider:
    @property
    def widget_category(self) -> str:
        return "{module}"

    def get_store_widgets(self, db, store_id, context=None):
        # Return list of ListWidget/BreakdownWidget
        ...

    def get_platform_widgets(self, db, platform_id, context=None):
        ...

{module}_widget_provider = {Module}WidgetProvider()

Register in definition.py:

def _get_widget_provider():
    from app.modules.{module}.services.{module}_widgets import {module}_widget_provider
    return {module}_widget_provider

{module}_module = ModuleDefinition(
    ...
    widget_provider=_get_widget_provider,
)

P6: Route Variable Naming (Deferred)

Priority: LOW — cosmetic, no functional impact Count: ~109 files use admin_router/store_router instead of router

Per MOD-010, route files should export a router variable. Many files use admin_router or store_router instead. The route discovery system currently handles both patterns.

Decision: Defer to a future cleanup sprint. This is purely naming consistency and has no architectural impact.


Execution Order

Phase 1: Foundation (Do First)

  1. Cat 5: Move UserContext to tenancy.schemas.auth — mechanical, enables clean imports
  2. Add service methods to tenancy — most modules depend on tenancy, need methods first

Phase 2: High-Impact Migrations (URGENT)

  1. Cat 1 - billing→tenancy: 13 violations, highest count
  2. Cat 1 - loyalty→tenancy: 10 violations
  3. Cat 1 - marketplace→tenancy/catalog/orders: 10 violations
  4. Cat 1 - core→tenancy: 3 violations
  5. Cat 1 - analytics→tenancy/catalog: 4 violations

Phase 3: Remaining Migrations (URGENT)

  1. Cat 2: Model creation violations (3 production files)
  2. Cat 3: All aggregation queries (11 files)
  3. Cat 4: All join queries (4 files)
  4. Cat 1: Remaining modules (cms, customers, inventory, messaging, monitoring)

Phase 4: Provider Enrichment (Incremental)

  1. P5: Add widget providers to orders, billing, catalog (highest value)
  2. P5: Add metrics providers to loyalty, payments
  3. P5: Add remaining widget providers as modules are touched

Phase 5: Cleanup (Deferred)

  1. P6: Route variable naming standardization

Testing Strategy

For each migration:

  1. Add/verify service method has a unit test
  2. Run existing integration tests to confirm no regressions
  3. Run python scripts/validate/validate_architecture.py to verify violation count decreases