feat: module-driven onboarding system + simplified 3-step signup
Add OnboardingProviderProtocol so modules declare their own post-signup onboarding steps. The core OnboardingAggregator discovers enabled providers and exposes a dashboard API (GET /dashboard/onboarding). A session-scoped banner on the store dashboard shows a checklist that guides merchants through setup without blocking signup. Signup is simplified from 4 steps to 3 (Plan → Account → Payment): store creation is merged into account creation, store language is captured from the user's browsing language, and platform-specific template branching is removed. Includes 47 unit and integration tests covering all new providers, the aggregator, the API endpoint, and the signup service changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,7 @@ if TYPE_CHECKING:
|
||||
from app.modules.contracts.cms import MediaUsageProviderProtocol
|
||||
from app.modules.contracts.features import FeatureProviderProtocol
|
||||
from app.modules.contracts.metrics import MetricsProviderProtocol
|
||||
from app.modules.contracts.onboarding import OnboardingProviderProtocol
|
||||
from app.modules.contracts.widgets import DashboardWidgetProviderProtocol
|
||||
|
||||
from app.modules.enums import FrontendType
|
||||
@@ -486,6 +487,29 @@ class ModuleDefinition:
|
||||
# to report where media is being used.
|
||||
media_usage_provider: "Callable[[], MediaUsageProviderProtocol] | None" = None
|
||||
|
||||
# =========================================================================
|
||||
# Onboarding Provider (Module-Driven Post-Signup Onboarding)
|
||||
# =========================================================================
|
||||
# Callable that returns an OnboardingProviderProtocol implementation.
|
||||
# Modules declare onboarding steps (what needs to be configured after signup)
|
||||
# and provide completion checks. The core module's OnboardingAggregator
|
||||
# discovers and aggregates all providers into a dashboard checklist banner.
|
||||
#
|
||||
# Example:
|
||||
# def _get_onboarding_provider():
|
||||
# from app.modules.marketplace.services.marketplace_onboarding import (
|
||||
# marketplace_onboarding_provider,
|
||||
# )
|
||||
# return marketplace_onboarding_provider
|
||||
#
|
||||
# marketplace_module = ModuleDefinition(
|
||||
# code="marketplace",
|
||||
# onboarding_provider=_get_onboarding_provider,
|
||||
# )
|
||||
#
|
||||
# The provider will be discovered by core's OnboardingAggregator service.
|
||||
onboarding_provider: "Callable[[], OnboardingProviderProtocol] | None" = None
|
||||
|
||||
# =========================================================================
|
||||
# Menu Item Methods (Legacy - uses menu_items dict of IDs)
|
||||
# =========================================================================
|
||||
@@ -955,6 +979,24 @@ class ModuleDefinition:
|
||||
return None
|
||||
return self.media_usage_provider()
|
||||
|
||||
# =========================================================================
|
||||
# Onboarding Provider Methods
|
||||
# =========================================================================
|
||||
|
||||
def has_onboarding_provider(self) -> bool:
|
||||
"""Check if this module has an onboarding provider."""
|
||||
return self.onboarding_provider is not None
|
||||
|
||||
def get_onboarding_provider_instance(self) -> "OnboardingProviderProtocol | None":
|
||||
"""Get the onboarding provider instance for this module.
|
||||
|
||||
Returns:
|
||||
OnboardingProviderProtocol instance, or None
|
||||
"""
|
||||
if self.onboarding_provider is None:
|
||||
return None
|
||||
return self.onboarding_provider()
|
||||
|
||||
# =========================================================================
|
||||
# Magic Methods
|
||||
# =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user