docs: update routing docs and seed script for production routing changes
Some checks failed
Some checks failed
Reflect the production routing refactor (ce5b54f): document store dashboard
double-mounting, per-platform subdomain overrides via StorePlatform.custom_subdomain,
get_resolved_store_code dependency, and /merchants/ reserved path. Update seed
script to populate custom_subdomain and StoreDomain.platform_id for demo data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -152,6 +152,10 @@ DEMO_STORES = [
|
||||
"description": "Premium electronics and gadgets marketplace",
|
||||
"theme_preset": "modern",
|
||||
"custom_domain": "wizatech.shop",
|
||||
"custom_domain_platform": "oms", # Link domain to OMS platform
|
||||
"platform_subdomains": { # Per-platform subdomain overrides
|
||||
"loyalty": "wizatech-rewards", # wizatech-rewards.rewardflow.lu
|
||||
},
|
||||
},
|
||||
{
|
||||
"merchant_index": 0, # WizaCorp
|
||||
@@ -179,6 +183,7 @@ DEMO_STORES = [
|
||||
"description": "Trendy clothing and accessories",
|
||||
"theme_preset": "vibrant",
|
||||
"custom_domain": "fashionhub.store",
|
||||
"custom_domain_platform": "loyalty", # Link domain to Loyalty platform
|
||||
},
|
||||
{
|
||||
"merchant_index": 1, # Fashion Group
|
||||
@@ -799,12 +804,28 @@ def create_demo_stores(
|
||||
)
|
||||
).all()
|
||||
|
||||
# Build platform code→id lookup for this store's custom subdomain config
|
||||
from app.modules.tenancy.models import Platform
|
||||
|
||||
platform_code_map = {}
|
||||
if store_data.get("platform_subdomains") or store_data.get("custom_domain_platform"):
|
||||
platform_rows = db.execute(select(Platform.id, Platform.code)).all()
|
||||
platform_code_map = {code: pid for pid, code in platform_rows}
|
||||
|
||||
for i, (platform_id,) in enumerate(merchant_subs):
|
||||
# Per-platform subdomain override for multi-platform stores
|
||||
# Config uses platform codes; resolve to IDs
|
||||
custom_sub = None
|
||||
for pcode, subdomain_val in store_data.get("platform_subdomains", {}).items():
|
||||
if platform_code_map.get(pcode) == platform_id:
|
||||
custom_sub = subdomain_val
|
||||
break
|
||||
sp = StorePlatform(
|
||||
store_id=store.id,
|
||||
platform_id=platform_id,
|
||||
is_active=True,
|
||||
is_primary=(i == 0),
|
||||
custom_subdomain=custom_sub,
|
||||
)
|
||||
db.add(sp)
|
||||
|
||||
@@ -814,6 +835,9 @@ def create_demo_stores(
|
||||
f" Linked to {len(merchant_subs)} platform(s): "
|
||||
f"{[pid for (pid,) in merchant_subs]}"
|
||||
)
|
||||
# Report custom subdomains if any
|
||||
for pcode, subdomain_val in store_data.get("platform_subdomains", {}).items():
|
||||
print_success(f" Custom subdomain on {pcode}: {subdomain_val}")
|
||||
|
||||
# Owner relationship is via Merchant.owner_user_id — no StoreUser needed
|
||||
|
||||
@@ -839,11 +863,15 @@ def create_demo_stores(
|
||||
|
||||
# Create custom domain if specified
|
||||
if store_data.get("custom_domain"):
|
||||
# Resolve platform_id from platform code (if specified)
|
||||
domain_platform_code = store_data.get("custom_domain_platform")
|
||||
domain_platform_id = platform_code_map.get(domain_platform_code) if domain_platform_code else None
|
||||
domain = StoreDomain(
|
||||
store_id=store.id,
|
||||
domain=store_data[
|
||||
"custom_domain"
|
||||
], # ✅ Field is 'domain', not 'domain_name'
|
||||
platform_id=domain_platform_id,
|
||||
is_verified=True, # Auto-verified for demo
|
||||
is_primary=True,
|
||||
verification_token=None,
|
||||
@@ -1290,6 +1318,20 @@ def print_summary(db: Session):
|
||||
print(f"\n {store.name} ({store.store_code})")
|
||||
print(f" Subdomain: {store.subdomain}.{settings.platform_domain}")
|
||||
|
||||
# Show per-platform custom subdomains
|
||||
from app.modules.tenancy.models import Platform
|
||||
|
||||
store_platforms = (
|
||||
db.query(StorePlatform, Platform)
|
||||
.join(Platform, Platform.id == StorePlatform.platform_id)
|
||||
.filter(StorePlatform.store_id == store.id)
|
||||
.all()
|
||||
)
|
||||
for sp, platform in store_platforms:
|
||||
if sp.custom_subdomain:
|
||||
pdomain = getattr(platform, "domain", platform.code)
|
||||
print(f" [{platform.code}] Custom subdomain: {sp.custom_subdomain}.{pdomain}")
|
||||
|
||||
# Query custom domains separately
|
||||
custom_domain = (
|
||||
db.query(StoreDomain)
|
||||
@@ -1305,7 +1347,12 @@ def print_summary(db: Session):
|
||||
or getattr(custom_domain, "name", None)
|
||||
)
|
||||
if domain_value:
|
||||
print(f" Custom: {domain_value}")
|
||||
platform_note = ""
|
||||
if custom_domain.platform_id:
|
||||
dp = db.query(Platform).filter(Platform.id == custom_domain.platform_id).first()
|
||||
if dp:
|
||||
platform_note = f" (linked to {dp.code})"
|
||||
print(f" Custom: {domain_value}{platform_note}")
|
||||
|
||||
print(f" Status: {'✓ Active' if store.is_active else '✗ Inactive'}")
|
||||
|
||||
@@ -1375,6 +1422,25 @@ def print_summary(db: Session):
|
||||
port = settings.api_port
|
||||
base = f"http://localhost:{port}"
|
||||
|
||||
# Build store→platform details (including custom subdomains) for production URLs
|
||||
from app.modules.tenancy.models import Platform
|
||||
|
||||
store_platform_details: dict[int, list[dict]] = {}
|
||||
sp_detail_rows = db.execute(
|
||||
select(
|
||||
StorePlatform.store_id,
|
||||
Platform.code,
|
||||
Platform.domain,
|
||||
StorePlatform.custom_subdomain,
|
||||
).join(Platform, Platform.id == StorePlatform.platform_id)
|
||||
.where(StorePlatform.is_active == True) # noqa: E712
|
||||
.order_by(StorePlatform.store_id, StorePlatform.is_primary.desc())
|
||||
).all()
|
||||
for store_id, pcode, pdomain, custom_sub in sp_detail_rows:
|
||||
store_platform_details.setdefault(store_id, []).append({
|
||||
"code": pcode, "domain": pdomain, "custom_subdomain": custom_sub,
|
||||
})
|
||||
|
||||
print("\n🏪 Store Access (Development):")
|
||||
print("─" * 70)
|
||||
for store in stores:
|
||||
@@ -1388,6 +1454,28 @@ def print_summary(db: Session):
|
||||
print(f" [{pc}] Staff login: {base}/platforms/{pc}/store/{store.store_code}/login")
|
||||
else:
|
||||
print(" (!) No platform assigned")
|
||||
|
||||
print("\n🌐 Store Access (Production-style):")
|
||||
print("─" * 70)
|
||||
for store in stores:
|
||||
details = store_platform_details.get(store.id, [])
|
||||
print(f" {store.name} ({store.store_code}):")
|
||||
for d in details:
|
||||
subdomain = d["custom_subdomain"] or store.subdomain
|
||||
pdomain = d["domain"] or f"{d['code']}.example.com"
|
||||
suffix = " (custom subdomain)" if d["custom_subdomain"] else ""
|
||||
print(f" [{d['code']}] Storefront: https://{subdomain}.{pdomain}/{suffix}")
|
||||
print(f" [{d['code']}] Dashboard: https://{subdomain}.{pdomain}/store/dashboard")
|
||||
# Show custom domain if any
|
||||
custom_domain = (
|
||||
db.query(StoreDomain)
|
||||
.filter(StoreDomain.store_id == store.id, StoreDomain.is_active == True)
|
||||
.first()
|
||||
)
|
||||
if custom_domain:
|
||||
dv = getattr(custom_domain, "domain", None)
|
||||
if dv:
|
||||
print(f" [custom] Storefront: https://{dv}/")
|
||||
print()
|
||||
|
||||
print("⚠️ ALL DEMO CREDENTIALS ARE INSECURE - For development only!")
|
||||
|
||||
Reference in New Issue
Block a user