feat: add OMS platform admin and align "Store panel" naming
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

Add create_oms_admin (admin@omsflow.lu) alongside existing loyalty admin,
both using a shared create_platform_admin helper. Rename "Dashboard" and
"Staff login" labels to "Store panel" and "Store login" across seed output.
Add customer login URLs to production-style access section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 12:12:23 +01:00
parent e7f8e61717
commit 79a88b0a36
2 changed files with 58 additions and 20 deletions

View File

@@ -131,23 +131,29 @@ def create_admin_user(db: Session, auth_manager: AuthManager) -> User:
return admin
def create_loyalty_admin(db: Session, auth_manager: AuthManager, loyalty_platform: Platform) -> User | None:
"""Create a platform admin for the Loyalty+ platform."""
def create_platform_admin(
db: Session,
auth_manager: AuthManager,
platform: Platform,
username: str,
email: str,
first_name: str,
) -> User | None:
"""Create a platform admin for a specific platform."""
from app.modules.tenancy.models.admin_platform import AdminPlatform
email = "admin@rewardflow.lu"
existing = db.execute(select(User).where(User.email == email)).scalar_one_or_none()
if existing:
print_warning(f"Loyalty admin already exists: {email}")
print_warning(f"{platform.name} admin already exists: {email}")
return existing
password = "admin123" # noqa: SEC001 Dev default, change in production
admin = User(
username="loyalty_admin",
username=username,
email=email,
hashed_password=auth_manager.hash_password(password),
role="platform_admin",
first_name="Loyalty",
first_name=first_name,
last_name="Administrator",
is_active=True,
is_email_verified=True,
@@ -155,19 +161,39 @@ def create_loyalty_admin(db: Session, auth_manager: AuthManager, loyalty_platfor
db.add(admin)
db.flush()
# Assign to loyalty platform
# Assign to platform
assignment = AdminPlatform(
user_id=admin.id,
platform_id=loyalty_platform.id,
platform_id=platform.id,
is_active=True,
)
db.add(assignment)
db.flush()
print_success(f"Created loyalty admin: {email} (password: {password})") # noqa: SEC021
print_success(f"Created {platform.name} admin: {email} (password: {password})") # noqa: SEC021
return admin
def create_loyalty_admin(db: Session, auth_manager: AuthManager, loyalty_platform: Platform) -> User | None:
"""Create a platform admin for the Loyalty+ platform."""
return create_platform_admin(
db, auth_manager, loyalty_platform,
username="loyalty_admin",
email="admin@rewardflow.lu",
first_name="Loyalty",
)
def create_oms_admin(db: Session, auth_manager: AuthManager, oms_platform: Platform) -> User | None:
"""Create a platform admin for the OMS platform."""
return create_platform_admin(
db, auth_manager, oms_platform,
username="oms_admin",
email="admin@omsflow.lu",
first_name="OMS",
)
def create_default_platforms(db: Session) -> list[Platform]:
"""Create all default platforms (OMS, Main, Loyalty+)."""
@@ -607,8 +633,14 @@ def initialize_production(db: Session, auth_manager: AuthManager):
print_step(3, "Creating default platforms...")
platforms = create_default_platforms(db)
# Step 3b: Create loyalty platform admin
print_step("3b", "Creating loyalty platform admin...")
# Step 3b: Create platform admins
print_step("3b", "Creating platform admins...")
oms_platform = next((p for p in platforms if p.code == "oms"), None)
if oms_platform:
create_oms_admin(db, auth_manager, oms_platform)
else:
print_warning("OMS platform not found, skipping OMS admin creation")
loyalty_platform = next((p for p in platforms if p.code == "loyalty"), None)
if loyalty_platform:
create_loyalty_admin(db, auth_manager, loyalty_platform)
@@ -688,6 +720,11 @@ def print_summary(db: Session):
print(f" Username: {settings.admin_username}")
print(f" Password: {settings.admin_password}") # noqa: SEC021
print()
print(" OMS Platform Admin (oms only):")
print(f" URL: {admin_url}")
print(" Username: oms_admin")
print(" Password: admin123") # noqa: SEC021
print()
print(" Loyalty Platform Admin (loyalty only):")
print(f" URL: {admin_url}")
print(" Username: loyalty_admin")

View File

@@ -1369,6 +1369,9 @@ def print_summary(db: Session):
role_name = su.role.name if su.role else "owner"
print(f" Team: {user.email} ({role_name})")
port = settings.api_port
base = f"http://localhost:{port}"
print("\n🔐 Demo Merchant Owner Credentials:")
print("" * 70)
for i, merchant_data in enumerate(DEMO_COMPANIES[:merchant_count], 1):
@@ -1379,10 +1382,10 @@ def print_summary(db: Session):
if merchant and merchant.stores:
for store in merchant.stores:
print(
f" Store: http://localhost:8000/store/{store.store_code}/login"
f" Store panel: {base}/store/{store.store_code}/login"
)
print(
f" or http://{store.subdomain}.localhost:8000/store/login" # noqa: SEC034
f" or http://{store.subdomain}.localhost:{port}/store/login" # noqa: SEC034
)
print()
@@ -1419,9 +1422,6 @@ def print_summary(db: Session):
for store_id, platform_code in store_platform_rows:
store_platform_map.setdefault(store_id, []).append(platform_code)
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
@@ -1450,8 +1450,8 @@ def print_summary(db: Session):
for pc in platform_codes:
print(f" [{pc}] Storefront: {base}/platforms/{pc}/storefront/{store.store_code}/")
print(f" [{pc}] Customer login: {base}/platforms/{pc}/storefront/{store.store_code}/account/login")
print(f" [{pc}] Store dashboard: {base}/platforms/{pc}/store/{store.store_code}/")
print(f" [{pc}] Staff login: {base}/platforms/{pc}/store/{store.store_code}/login")
print(f" [{pc}] Store panel: {base}/platforms/{pc}/store/{store.store_code}/")
print(f" [{pc}] Store login: {base}/platforms/{pc}/store/{store.store_code}/login")
else:
print(" (!) No platform assigned")
@@ -1464,8 +1464,9 @@ def print_summary(db: Session):
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")
print(f" [{d['code']}] Storefront: https://{subdomain}.{pdomain}/{suffix}")
print(f" [{d['code']}] Customer login: https://{subdomain}.{pdomain}/account/login")
print(f" [{d['code']}] Store panel: https://{subdomain}.{pdomain}/store/")
# Show custom domain if any
custom_domain = (
db.query(StoreDomain)