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>
56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
# app/modules/tenancy/services/tenancy_onboarding.py
|
|
"""
|
|
Onboarding provider for the tenancy module.
|
|
|
|
Provides the "Customize your store" onboarding step that is always present
|
|
for all platforms. Completed when the store has a description or a logo.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.modules.contracts.onboarding import OnboardingStepDefinition
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TenancyOnboardingProvider:
|
|
"""Onboarding provider for tenancy module (always present)."""
|
|
|
|
@property
|
|
def onboarding_category(self) -> str:
|
|
return "tenancy"
|
|
|
|
def get_onboarding_steps(self) -> list[OnboardingStepDefinition]:
|
|
return [
|
|
OnboardingStepDefinition(
|
|
key="tenancy.customize_store",
|
|
title_key="onboarding.tenancy.customize_store.title",
|
|
description_key="onboarding.tenancy.customize_store.description",
|
|
icon="settings",
|
|
route_template="/store/{store_code}/settings",
|
|
order=100,
|
|
category="tenancy",
|
|
),
|
|
]
|
|
|
|
def is_step_completed(
|
|
self, db: Session, store_id: int, step_key: str
|
|
) -> bool:
|
|
if step_key != "tenancy.customize_store":
|
|
return False
|
|
|
|
from app.modules.tenancy.models.store import Store
|
|
|
|
store = db.query(Store).filter(Store.id == store_id).first()
|
|
if not store:
|
|
return False
|
|
|
|
has_description = bool(store.description and store.description.strip())
|
|
has_logo = bool(store.get_logo_url())
|
|
return has_description or has_logo
|
|
|
|
|
|
tenancy_onboarding_provider = TenancyOnboardingProvider()
|