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>
80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
# app/modules/marketplace/services/marketplace_onboarding.py
|
|
"""
|
|
Onboarding provider for the marketplace module.
|
|
|
|
Provides two onboarding steps:
|
|
1. Connect Letzshop API - completed when StoreLetzshopCredentials exists with api_key
|
|
2. Import products - completed when at least 1 product exists in catalog
|
|
"""
|
|
|
|
import logging
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.modules.contracts.onboarding import OnboardingStepDefinition
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MarketplaceOnboardingProvider:
|
|
"""Onboarding provider for marketplace module."""
|
|
|
|
@property
|
|
def onboarding_category(self) -> str:
|
|
return "marketplace"
|
|
|
|
def get_onboarding_steps(self) -> list[OnboardingStepDefinition]:
|
|
return [
|
|
OnboardingStepDefinition(
|
|
key="marketplace.connect_api",
|
|
title_key="onboarding.marketplace.connect_api.title",
|
|
description_key="onboarding.marketplace.connect_api.description",
|
|
icon="plug",
|
|
route_template="/store/{store_code}/letzshop",
|
|
order=200,
|
|
category="marketplace",
|
|
),
|
|
OnboardingStepDefinition(
|
|
key="marketplace.import_products",
|
|
title_key="onboarding.marketplace.import_products.title",
|
|
description_key="onboarding.marketplace.import_products.description",
|
|
icon="package",
|
|
route_template="/store/{store_code}/marketplace",
|
|
order=210,
|
|
category="marketplace",
|
|
),
|
|
]
|
|
|
|
def is_step_completed(
|
|
self, db: Session, store_id: int, step_key: str
|
|
) -> bool:
|
|
if step_key == "marketplace.connect_api":
|
|
return self._has_letzshop_credentials(db, store_id)
|
|
if step_key == "marketplace.import_products":
|
|
return self._has_products(db, store_id)
|
|
return False
|
|
|
|
def _has_letzshop_credentials(self, db: Session, store_id: int) -> bool:
|
|
from app.modules.marketplace.models.letzshop import StoreLetzshopCredentials
|
|
|
|
creds = (
|
|
db.query(StoreLetzshopCredentials)
|
|
.filter(StoreLetzshopCredentials.store_id == store_id)
|
|
.first()
|
|
)
|
|
return bool(creds and creds.api_key_encrypted)
|
|
|
|
def _has_products(self, db: Session, store_id: int) -> bool:
|
|
from app.modules.catalog.models.product import Product
|
|
|
|
count = (
|
|
db.query(Product)
|
|
.filter(Product.store_id == store_id)
|
|
.limit(1)
|
|
.count()
|
|
)
|
|
return count > 0
|
|
|
|
|
|
marketplace_onboarding_provider = MarketplaceOnboardingProvider()
|