Files
orion/app/modules/contracts/onboarding.py
Samir Boulahtit 34bf961309 fix: resolve all 19 architecture validator warnings
- API-004: Add noqa for factory-pattern auth in user_account routes and payments admin
- MDL-003: Add from_attributes to MerchantStoreDetailResponse schema
- EXC-003: Suppress broad except in merchant_store_service and admin_subscription_service
  (intentional fallbacks for optional billing module)
- NAM-002: Rename onboarding files to *_service.py suffix and update all imports
- JS-001: Add file-level noqa for dev-toolbar.js (console interceptor by design)
- JS-005: Add init guards to dashboard.js and customer-detail.js
- IMPORT-004: Break circular deps by removing orders from inventory requires and
  marketplace from orders requires; add IMPORT-002 suppression for lazy cross-imports
- MOD-025: Remove unused OnboardingAlreadyCompletedException

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:43:12 +01:00

155 lines
4.6 KiB
Python

# app/modules/contracts/onboarding.py
"""
Onboarding provider protocol for module-driven post-signup onboarding.
Each module defines its own onboarding steps (what needs to be configured)
and provides completion checks. The core module's OnboardingAggregator
discovers and aggregates all providers into a dashboard checklist.
Benefits:
- Modules own their onboarding steps (billing module doesn't need to know)
- Steps appear/disappear based on which modules are enabled
- Easy to add new steps (just implement protocol in your module)
- Dashboard banner guides merchants without blocking signup
Usage:
# 1. Implement the protocol in your module
class MarketplaceOnboardingProvider:
@property
def onboarding_category(self) -> str:
return "marketplace"
def get_onboarding_steps(self) -> list[OnboardingStepDefinition]:
return [
OnboardingStepDefinition(
key="marketplace.connect_api",
title_key="marketplace.onboarding.connect_api.title",
description_key="marketplace.onboarding.connect_api.description",
icon="plug",
route_template="/store/{store_code}/letzshop",
order=200,
)
]
def is_step_completed(self, db, store_id, step_key) -> bool:
...
# 2. Register in module definition
def _get_onboarding_provider():
from app.modules.marketplace.services.marketplace_onboarding_service import (
marketplace_onboarding_provider,
)
return marketplace_onboarding_provider
marketplace_module = ModuleDefinition(
code="marketplace",
onboarding_provider=_get_onboarding_provider,
# ...
)
# 3. Steps appear automatically in dashboard when module is enabled
"""
from dataclasses import dataclass
from typing import TYPE_CHECKING, Protocol, runtime_checkable
if TYPE_CHECKING:
from sqlalchemy.orm import Session
@dataclass
class OnboardingStepDefinition:
"""
Definition of a single onboarding step.
Attributes:
key: Unique identifier (e.g., "marketplace.connect_api")
Format: "{module}.{step_name}" for consistency
title_key: i18n key for display title
description_key: i18n key for description text
icon: Lucide icon name for UI display (e.g., "plug", "package")
route_template: URL template with {store_code} placeholder
order: Display sort order (lower = first). Default 100.
category: Grouping category (typically matches module code)
"""
key: str
title_key: str
description_key: str
icon: str
route_template: str
order: int = 100
category: str = ""
@dataclass
class OnboardingStepStatus:
"""
An onboarding step paired with its completion status.
Attributes:
step: The step definition
completed: Whether the step has been completed
"""
step: OnboardingStepDefinition
completed: bool
@runtime_checkable
class OnboardingProviderProtocol(Protocol):
"""
Protocol for modules that provide onboarding steps.
Each module implements this to declare what setup steps are needed
after signup. The core module's OnboardingAggregator discovers and
aggregates all providers into a dashboard checklist banner.
Implementation Notes:
- Providers should be stateless (all data via db session)
- Return empty list from get_onboarding_steps() if no steps needed
- is_step_completed() should be efficient (called per step per page load)
- Use consistent key format: "{category}.{step_name}"
"""
@property
def onboarding_category(self) -> str:
"""
Category name for this provider's onboarding steps.
Should match the module code (e.g., "marketplace", "tenancy").
"""
...
def get_onboarding_steps(self) -> list[OnboardingStepDefinition]:
"""
Get onboarding step definitions provided by this module.
Returns:
List of OnboardingStepDefinition objects
"""
...
def is_step_completed(
self, db: "Session", store_id: int, step_key: str
) -> bool:
"""
Check if a specific onboarding step is completed for a store.
Args:
db: Database session for queries
store_id: ID of the store to check
step_key: The step key to check (from OnboardingStepDefinition.key)
Returns:
True if the step is completed
"""
...
__all__ = [
"OnboardingStepDefinition",
"OnboardingStepStatus",
"OnboardingProviderProtocol",
]