""" Tenant Model - ServiceManagerWeb Modelo para organizaciones cliente (multi-tenancy) """ from sqlalchemy import String, Integer, Text, Boolean, ARRAY from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import UUID, ENUM from typing import List, Optional import enum import uuid from app.core.database import Base class TenantStatus(str, enum.Enum): """Estados de un tenant.""" ACTIVE = "active" SUSPENDED = "suspended" INACTIVE = "inactive" class Tenant(Base): """Modelo de Tenant (Organización cliente).""" __tablename__ = "tenants" # Información básica name: Mapped[str] = mapped_column(String(255), nullable=False) slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) domain: Mapped[Optional[str]] = mapped_column(String(255)) logo_url: Mapped[Optional[str]] = mapped_column(String(500)) # Contacto contact_email: Mapped[Optional[str]] = mapped_column(String(320)) contact_phone: Mapped[Optional[str]] = mapped_column(String(20)) address: Mapped[Optional[str]] = mapped_column(Text) # Configuración regional timezone: Mapped[str] = mapped_column(String(50), default="UTC") locale: Mapped[str] = mapped_column(String(10), default="es-ES") # Límites y configuración max_users: Mapped[int] = mapped_column(Integer, default=50) max_storage_mb: Mapped[int] = mapped_column(Integer, default=1024) allowed_file_types: Mapped[List[str]] = mapped_column( ARRAY(String), default=["pdf", "jpg", "jpeg", "png", "doc", "docx", "xls", "xlsx", "txt"] ) # Estado status: Mapped[TenantStatus] = mapped_column( String(20), default=TenantStatus.ACTIVE ) is_active: Mapped[bool] = mapped_column(Boolean, default=True) # Relaciones users: Mapped[List["User"]] = relationship("User", back_populates="tenant") tickets: Mapped[List["Ticket"]] = relationship("Ticket", back_populates="tenant") categories: Mapped[List["Category"]] = relationship("Category", back_populates="tenant") def __repr__(self) -> str: return f""