feat(subscriptions): migrate subscription management to merchant level and seed tiers
Move subscription create/edit from store detail (broken endpoint) to merchant detail page with proper modal UI. Seed 4 subscription tiers (Essential, Professional, Business, Enterprise) in init_production.py. Also includes cross-module dependency declarations, store domain platform_id migration, platform context middleware, CMS route fixes, and migration backups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,25 @@ store_content_pages_router = APIRouter(prefix="/content-pages")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _resolve_platform_id(db: Session, store_id: int) -> int | None:
|
||||
"""Resolve platform_id from store's primary StorePlatform. Returns None if not found."""
|
||||
from app.modules.tenancy.models import StorePlatform
|
||||
primary_sp = (
|
||||
db.query(StorePlatform)
|
||||
.filter(StorePlatform.store_id == store_id, StorePlatform.is_primary.is_(True))
|
||||
.first()
|
||||
)
|
||||
if primary_sp:
|
||||
return primary_sp.platform_id
|
||||
# Fallback: any active store_platform
|
||||
any_sp = (
|
||||
db.query(StorePlatform)
|
||||
.filter(StorePlatform.store_id == store_id, StorePlatform.is_active.is_(True))
|
||||
.first()
|
||||
)
|
||||
return any_sp.platform_id if any_sp else None
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# STORE CONTENT PAGES
|
||||
# ============================================================================
|
||||
@@ -50,8 +69,9 @@ def list_store_pages(
|
||||
|
||||
Returns store-specific overrides + platform defaults (store overrides take precedence).
|
||||
"""
|
||||
platform_id = _resolve_platform_id(db, current_user.token_store_id)
|
||||
pages = content_page_service.list_pages_for_store(
|
||||
db, store_id=current_user.token_store_id, include_unpublished=include_unpublished
|
||||
db, platform_id=platform_id, store_id=current_user.token_store_id, include_unpublished=include_unpublished
|
||||
)
|
||||
|
||||
return [page.to_dict() for page in pages]
|
||||
@@ -148,11 +168,10 @@ def get_platform_default(
|
||||
Useful for stores to view the original before/after overriding.
|
||||
"""
|
||||
# Get store's platform
|
||||
store = store_service.get_store_by_id_optional(db, current_user.token_store_id)
|
||||
platform_id = 1 # Default to OMS
|
||||
|
||||
if store and store.platforms:
|
||||
platform_id = store.platforms[0].id
|
||||
platform_id = _resolve_platform_id(db, current_user.token_store_id)
|
||||
if platform_id is None:
|
||||
from fastapi import HTTPException
|
||||
raise HTTPException(status_code=400, detail="Store is not subscribed to any platform")
|
||||
|
||||
# Get platform default (store_id=None)
|
||||
page = content_page_service.get_store_default_page(
|
||||
@@ -177,8 +196,10 @@ def get_page(
|
||||
|
||||
Returns store override if exists, otherwise platform default.
|
||||
"""
|
||||
platform_id = _resolve_platform_id(db, current_user.token_store_id)
|
||||
page = content_page_service.get_page_for_store_or_raise(
|
||||
db,
|
||||
platform_id=platform_id,
|
||||
slug=slug,
|
||||
store_id=current_user.token_store_id,
|
||||
include_unpublished=include_unpublished,
|
||||
|
||||
@@ -36,11 +36,13 @@ def get_navigation_pages(request: Request, db: Session = Depends(get_db)):
|
||||
Returns store overrides + platform defaults.
|
||||
"""
|
||||
store = getattr(request.state, "store", None)
|
||||
platform = getattr(request.state, "platform", None)
|
||||
store_id = store.id if store else None
|
||||
platform_id = platform.id if platform else 1
|
||||
|
||||
# Get all published pages for this store
|
||||
pages = content_page_service.list_pages_for_store(
|
||||
db, store_id=store_id, include_unpublished=False
|
||||
db, platform_id=platform_id, store_id=store_id, include_unpublished=False
|
||||
)
|
||||
|
||||
return [
|
||||
@@ -64,10 +66,13 @@ def get_content_page(slug: str, request: Request, db: Session = Depends(get_db))
|
||||
Returns store override if exists, otherwise platform default.
|
||||
"""
|
||||
store = getattr(request.state, "store", None)
|
||||
platform = getattr(request.state, "platform", None)
|
||||
store_id = store.id if store else None
|
||||
platform_id = platform.id if platform else 1
|
||||
|
||||
page = content_page_service.get_page_for_store_or_raise(
|
||||
db,
|
||||
platform_id=platform_id,
|
||||
slug=slug,
|
||||
store_id=store_id,
|
||||
include_unpublished=False, # Only show published pages
|
||||
|
||||
Reference in New Issue
Block a user