# app/modules/tenancy/models/platform_module.py """ PlatformModule model for tracking module enablement per platform. This junction table provides: - Auditability: Track when modules were enabled/disabled and by whom - Configuration: Per-module settings specific to each platform - State tracking: Explicit enabled/disabled states with timestamps """ from sqlalchemy import ( JSON, Boolean, Column, DateTime, ForeignKey, Index, Integer, String, UniqueConstraint, ) from sqlalchemy.orm import relationship from app.core.database import Base from models.database.base import TimestampMixin class PlatformModule(Base, TimestampMixin): """ Junction table tracking module enablement per platform. This provides a normalized, auditable way to track which modules are enabled for each platform, with configuration options. Example: PlatformModule( platform_id=1, module_code="billing", is_enabled=True, enabled_at=datetime.now(), enabled_by_user_id=42, config={"stripe_mode": "live", "default_trial_days": 14} ) """ __tablename__ = "platform_modules" id = Column(Integer, primary_key=True, index=True) # ======================================================================== # Identity # ======================================================================== platform_id = Column( Integer, ForeignKey("platforms.id", ondelete="CASCADE"), nullable=False, comment="Platform this module configuration belongs to", ) module_code = Column( String(50), nullable=False, comment="Module code (e.g., 'billing', 'inventory', 'orders')", ) # ======================================================================== # State # ======================================================================== is_enabled = Column( Boolean, nullable=False, default=True, comment="Whether this module is currently enabled for the platform", ) # ======================================================================== # Audit Trail - Enable # ======================================================================== enabled_at = Column( DateTime(timezone=True), nullable=True, comment="When the module was last enabled", ) enabled_by_user_id = Column( Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True, comment="User who enabled the module", ) # ======================================================================== # Audit Trail - Disable # ======================================================================== disabled_at = Column( DateTime(timezone=True), nullable=True, comment="When the module was last disabled", ) disabled_by_user_id = Column( Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True, comment="User who disabled the module", ) # ======================================================================== # Configuration # ======================================================================== config = Column( JSON, nullable=False, default=dict, comment="Module-specific configuration for this platform", ) # ======================================================================== # Relationships # ======================================================================== platform = relationship( "Platform", back_populates="modules", ) enabled_by = relationship( "User", foreign_keys=[enabled_by_user_id], ) disabled_by = relationship( "User", foreign_keys=[disabled_by_user_id], ) # ======================================================================== # Constraints & Indexes # ======================================================================== __table_args__ = ( # Each platform can only have one configuration per module UniqueConstraint("platform_id", "module_code", name="uq_platform_module"), # Index for querying by platform Index("idx_platform_module_platform_id", "platform_id"), # Index for querying by module code Index("idx_platform_module_code", "module_code"), # Index for querying enabled modules Index("idx_platform_module_enabled", "platform_id", "is_enabled"), ) def __repr__(self) -> str: status = "enabled" if self.is_enabled else "disabled" return f"" __all__ = ["PlatformModule"]