from sqlalchemy import Integer, String, DateTime, ForeignKey, Boolean, Text, JSON, UniqueConstraint from sqlalchemy.orm import relationship, Mapped, mapped_column from datetime import datetime from .database import Base class Tenant(Base): __tablename__ = "tenants" id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True) name: Mapped[str] = mapped_column(String(200), unique=True, nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) users = relationship("User", back_populates="tenant") class User(Base): __tablename__ = "users" id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True) tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id"), nullable=False, index=True) email: Mapped[str] = mapped_column(String(320), unique=True, index=True, nullable=False) password_hash: Mapped[str] = mapped_column(String(255), nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True) is_tenant_admin: Mapped[bool] = mapped_column(Boolean, default=False) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) tenant = relationship("Tenant", back_populates="users") role_bindings = relationship("RoleBinding", back_populates="user") class Role(Base): __tablename__ = "roles" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) description: Mapped[str] = mapped_column(String(255), default="") class Permission(Base): __tablename__ = "permissions" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) description: Mapped[str] = mapped_column(String(255), default="") class RolePermission(Base): __tablename__ = "role_permissions" id: Mapped[int] = mapped_column(Integer, primary_key=True) role_id: Mapped[int] = mapped_column(ForeignKey("roles.id"), nullable=False) permission_id: Mapped[int] = mapped_column(ForeignKey("permissions.id"), nullable=False) __table_args__ = (UniqueConstraint("role_id", "permission_id", name="uq_role_perm"),) class RoleBinding(Base): __tablename__ = "role_bindings" id: Mapped[int] = mapped_column(Integer, primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False) role_id: Mapped[int] = mapped_column(ForeignKey("roles.id"), nullable=False) __table_args__ = (UniqueConstraint("user_id", "role_id", name="uq_user_role"),) user = relationship("User", back_populates="role_bindings") class Plan(Base): __tablename__ = "plans" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) monthly_quota: Mapped[int] = mapped_column(Integer, default=1000) features: Mapped[dict] = mapped_column(JSON, default=dict) class Subscription(Base): __tablename__ = "subscriptions" id: Mapped[int] = mapped_column(Integer, primary_key=True) tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id"), nullable=False, index=True) plan_id: Mapped[int] = mapped_column(ForeignKey("plans.id"), nullable=False) active: Mapped[bool] = mapped_column(Boolean, default=True) started_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) class UsageEvent(Base): __tablename__ = "usage_events" id: Mapped[int] = mapped_column(Integer, primary_key=True) tenant_id: Mapped[int] = mapped_column(Integer, index=True) user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=True) kind: Mapped[str] = mapped_column(String(50)) amount: Mapped[int] = mapped_column(Integer, default=1) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) class App(Base): __tablename__ = "apps" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) description: Mapped[str] = mapped_column(String(255), default="") callback_url: Mapped[str] = mapped_column(String(512), default="") class InstalledApp(Base): __tablename__ = "installed_apps" id: Mapped[int] = mapped_column(Integer, primary_key=True) tenant_id: Mapped[int] = mapped_column(Integer, index=True) app_id: Mapped[int] = mapped_column(Integer, index=True) __table_args__ = (UniqueConstraint("tenant_id", "app_id", name="uq_tenant_app"),) class AuditLog(Base): __tablename__ = "audit_logs" id: Mapped[int] = mapped_column(Integer, primary_key=True) tenant_id: Mapped[int] = mapped_column(Integer, index=True, nullable=True) user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=True) path: Mapped[str] = mapped_column(String(512)) method: Mapped[str] = mapped_column(String(10)) status_code: Mapped[int] = mapped_column(Integer) meta: Mapped[dict] = mapped_column(JSON, default=dict) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) class ErrorLog(Base): __tablename__ = "error_logs" id: Mapped[int] = mapped_column(Integer, primary_key=True) tenant_id: Mapped[int] = mapped_column(Integer, index=True, nullable=True) user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=True) path: Mapped[str] = mapped_column(String(512)) error: Mapped[str] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)