from __future__ import annotations from datetime import datetime from sqlalchemy import Boolean, DateTime, ForeignKey, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.session import Base class ClientAccount(Base): __tablename__ = "client_accounts" id: Mapped[int] = mapped_column(primary_key=True) tenant_id: Mapped[str] = mapped_column(String(64), default="default") name: Mapped[str] = mapped_column(String(255), unique=True, index=True) client_code: Mapped[str] = mapped_column(String(64), unique=True, index=True) status: Mapped[str] = mapped_column(String(32), default="active") powerbi_workspace: Mapped[str | None] = mapped_column(String(128), nullable=True) notes: Mapped[str | None] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) users: Mapped[list["ClientUser"]] = relationship( back_populates="client_account", cascade="all, delete-orphan", order_by="ClientUser.created_at.desc()", ) features: Mapped[list["ClientFeatureAccess"]] = relationship( back_populates="client_account", cascade="all, delete-orphan", order_by="ClientFeatureAccess.feature_group, ClientFeatureAccess.feature_name", ) class ClientUser(Base): __tablename__ = "client_users" __table_args__ = (UniqueConstraint("client_account_id", "email", name="uq_client_user_email"),) id: Mapped[int] = mapped_column(primary_key=True) tenant_id: Mapped[str] = mapped_column(String(64), default="default") client_account_id: Mapped[int] = mapped_column(ForeignKey("client_accounts.id"), index=True) full_name: Mapped[str] = mapped_column(String(255)) email: Mapped[str] = mapped_column(String(255)) role: Mapped[str] = mapped_column(String(64), default="viewer") status: Mapped[str] = mapped_column(String(32), default="invited") is_new_user: Mapped[bool] = mapped_column(Boolean, default=True) last_login_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) client_account: Mapped[ClientAccount] = relationship(back_populates="users") class ClientFeatureAccess(Base): __tablename__ = "client_feature_access" __table_args__ = (UniqueConstraint("client_account_id", "feature_key", name="uq_client_feature"),) id: Mapped[int] = mapped_column(primary_key=True) tenant_id: Mapped[str] = mapped_column(String(64), default="default") client_account_id: Mapped[int] = mapped_column(ForeignKey("client_accounts.id"), index=True) feature_key: Mapped[str] = mapped_column(String(64)) feature_name: Mapped[str] = mapped_column(String(255)) feature_group: Mapped[str] = mapped_column(String(64), default="operations") description: Mapped[str | None] = mapped_column(Text, nullable=True) enabled: Mapped[bool] = mapped_column(Boolean, default=False) updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) client_account: Mapped[ClientAccount] = relationship(back_populates="features")