# 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", ]