Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart with Orion/orion/ORION across 184 files. This includes database identifiers, email addresses, domain references, R2 bucket names, DNS prefixes, encryption salt, Celery app name, config defaults, Docker configs, CI configs, documentation, seed data, and templates. Renames homepage-wizamart.html template to homepage-orion.html. Fixes duplicate file_pattern key in api.yaml architecture rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
243 lines
6.5 KiB
Python
243 lines
6.5 KiB
Python
# app/modules/tenancy/models/platform.py
|
|
"""
|
|
Platform model representing a business offering/product line.
|
|
|
|
Platforms are independent business products (e.g., OMS, Loyalty Program, Site Builder)
|
|
that can have their own:
|
|
- Marketing pages (homepage, pricing, about)
|
|
- Store default pages (fallback storefront pages)
|
|
- Subscription tiers with platform-specific features
|
|
- Branding and configuration
|
|
|
|
Each store can belong to multiple platforms via the StorePlatform junction table.
|
|
"""
|
|
|
|
from sqlalchemy import (
|
|
JSON,
|
|
Boolean,
|
|
Column,
|
|
Index,
|
|
Integer,
|
|
String,
|
|
Text,
|
|
)
|
|
from sqlalchemy.orm import relationship
|
|
|
|
from app.core.database import Base
|
|
from models.database.base import TimestampMixin
|
|
|
|
|
|
class Platform(Base, TimestampMixin):
|
|
"""
|
|
Represents a business offering/product line.
|
|
|
|
Examples:
|
|
- Orion OMS (Order Management System)
|
|
- Loyalty+ (Loyalty Program Platform)
|
|
- Site Builder (Website Builder for Local Businesses)
|
|
|
|
Each platform has:
|
|
- Its own domain (production) or path prefix (development)
|
|
- Independent CMS pages (marketing pages + store defaults)
|
|
- Platform-specific subscription tiers
|
|
- Custom branding and theme
|
|
"""
|
|
|
|
__tablename__ = "platforms"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
|
|
# ========================================================================
|
|
# Identity
|
|
# ========================================================================
|
|
|
|
code = Column(
|
|
String(50),
|
|
unique=True,
|
|
nullable=False,
|
|
index=True,
|
|
comment="Unique platform identifier (e.g., 'oms', 'loyalty', 'sites')",
|
|
)
|
|
|
|
name = Column(
|
|
String(100),
|
|
nullable=False,
|
|
comment="Display name (e.g., 'Orion OMS')",
|
|
)
|
|
|
|
description = Column(
|
|
Text,
|
|
nullable=True,
|
|
comment="Platform description for admin/marketing purposes",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Domain Routing
|
|
# ========================================================================
|
|
|
|
domain = Column(
|
|
String(255),
|
|
unique=True,
|
|
nullable=True,
|
|
index=True,
|
|
comment="Production domain (e.g., 'oms.lu', 'loyalty.lu')",
|
|
)
|
|
|
|
path_prefix = Column(
|
|
String(50),
|
|
unique=True,
|
|
nullable=True,
|
|
index=True,
|
|
comment="Development path prefix (e.g., 'oms' for localhost:9999/oms/*)",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Branding
|
|
# ========================================================================
|
|
|
|
logo = Column(
|
|
String(500),
|
|
nullable=True,
|
|
comment="Logo URL for light mode",
|
|
)
|
|
|
|
logo_dark = Column(
|
|
String(500),
|
|
nullable=True,
|
|
comment="Logo URL for dark mode",
|
|
)
|
|
|
|
favicon = Column(
|
|
String(500),
|
|
nullable=True,
|
|
comment="Favicon URL",
|
|
)
|
|
|
|
theme_config = Column(
|
|
JSON,
|
|
nullable=True,
|
|
default=dict,
|
|
comment="Theme configuration (colors, fonts, etc.)",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Localization
|
|
# ========================================================================
|
|
|
|
default_language = Column(
|
|
String(5),
|
|
default="fr",
|
|
nullable=False,
|
|
comment="Default language code (e.g., 'fr', 'en', 'de')",
|
|
)
|
|
|
|
supported_languages = Column(
|
|
JSON,
|
|
default=["fr", "de", "en"],
|
|
nullable=False,
|
|
comment="List of supported language codes",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Status
|
|
# ========================================================================
|
|
|
|
is_active = Column(
|
|
Boolean,
|
|
default=True,
|
|
nullable=False,
|
|
comment="Whether the platform is active and accessible",
|
|
)
|
|
|
|
is_public = Column(
|
|
Boolean,
|
|
default=True,
|
|
nullable=False,
|
|
comment="Whether the platform is visible in public listings",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Configuration
|
|
# ========================================================================
|
|
|
|
settings = Column(
|
|
JSON,
|
|
nullable=True,
|
|
default=dict,
|
|
comment="Platform-specific settings and feature flags",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Relationships
|
|
# ========================================================================
|
|
|
|
# Content pages belonging to this platform
|
|
content_pages = relationship(
|
|
"ContentPage",
|
|
back_populates="platform",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
# Stores on this platform (via junction table)
|
|
store_platforms = relationship(
|
|
"StorePlatform",
|
|
back_populates="platform",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
# Subscription tiers for this platform
|
|
subscription_tiers = relationship(
|
|
"SubscriptionTier",
|
|
back_populates="platform",
|
|
foreign_keys="SubscriptionTier.platform_id",
|
|
)
|
|
|
|
# Admin assignments for this platform
|
|
admin_platforms = relationship(
|
|
"AdminPlatform",
|
|
back_populates="platform",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
# Menu visibility configuration for platform admins
|
|
menu_configs = relationship(
|
|
"AdminMenuConfig",
|
|
back_populates="platform",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
# Module enablement configuration
|
|
modules = relationship(
|
|
"PlatformModule",
|
|
back_populates="platform",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
# ========================================================================
|
|
# Indexes
|
|
# ========================================================================
|
|
|
|
__table_args__ = (
|
|
Index("idx_platform_active", "is_active"),
|
|
Index("idx_platform_public", "is_public", "is_active"),
|
|
)
|
|
|
|
# ========================================================================
|
|
# Properties
|
|
# ========================================================================
|
|
|
|
@property
|
|
def base_url(self) -> str:
|
|
"""Get the base URL for this platform (for link generation)."""
|
|
if self.domain:
|
|
return f"https://{self.domain}"
|
|
if self.path_prefix:
|
|
return f"/{self.path_prefix}"
|
|
return "/"
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Platform(code='{self.code}', name='{self.name}')>"
|
|
|
|
|
|
__all__ = ["Platform"]
|