# models/database/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) - Vendor default pages (fallback storefront pages) - Subscription tiers with platform-specific features - Branding and configuration Each vendor can belong to multiple platforms via the VendorPlatform 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: - Wizamart 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 + vendor 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., 'Wizamart 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", ) # Vendors on this platform (via junction table) vendor_platforms = relationship( "VendorPlatform", 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""