"""用户模型""" from __future__ import annotations from .base import Base from .enums import UserRole, UserStatus from .types import JSONB from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy import BigInteger, VARCHAR, TEXT, Integer, Boolean, TIMESTAMP from typing import List, Optional, TYPE_CHECKING, Any if TYPE_CHECKING: from .user_skill_binding import UserSkillBinding from .user_project import UserProject from .user_workload import UserWorkload class User(Base): __tablename__ = "users" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) username: Mapped[str] = mapped_column(VARCHAR(100), nullable=False, unique=True) email: Mapped[str] = mapped_column(VARCHAR(255), nullable=False, unique=True) phone_country_code: Mapped[Optional[str]] = mapped_column(VARCHAR(8), nullable=True) phone_number: Mapped[Optional[str]] = mapped_column(VARCHAR(32), nullable=True) phone_e164: Mapped[Optional[str]] = mapped_column(VARCHAR(32), nullable=True, unique=True, index=True) phone_verified_at: Mapped[Optional[TIMESTAMP]] = mapped_column(TIMESTAMP, nullable=True) last_login_at: Mapped[Optional[TIMESTAMP]] = mapped_column(TIMESTAMP, nullable=True) login_method: Mapped[Optional[str]] = mapped_column(VARCHAR(32), nullable=True) password_hash: Mapped[str] = mapped_column(VARCHAR(255), nullable=False) name: Mapped[str] = mapped_column(VARCHAR(100), nullable=False) role: Mapped[str] = mapped_column(VARCHAR(50), nullable=False) assigned_domains: Mapped[Any] = mapped_column(JSONB, nullable=True, default=list) workload: Mapped[int] = mapped_column(Integer, nullable=False, default=0) status: Mapped[str] = mapped_column(VARCHAR(50), nullable=False, default="active") is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) avatar_url: Mapped[Optional[str]] = mapped_column(VARCHAR(500), nullable=True) bio: Mapped[Optional[str]] = mapped_column(TEXT, nullable=True) skill_bindings: Mapped[List["UserSkillBinding"]] = relationship( "UserSkillBinding", back_populates="user", cascade="all, delete-orphan" ) workload_rel: Mapped[Optional["UserWorkload"]] = relationship( "UserWorkload", back_populates="user", uselist=False, cascade="all, delete-orphan" ) project_links: Mapped[List["UserProject"]] = relationship( "UserProject", back_populates="user", cascade="all, delete-orphan" ) def to_dict(self) -> dict: return { "id": str(self.id), "tenant_id": str(self.tenant_id), "username": self.username, "name": self.name, "email": self.email, "phone_country_code": self.phone_country_code, "phone_number": self.phone_number, "phone_e164": self.phone_e164, "phone_verified_at": self.phone_verified_at.isoformat() if self.phone_verified_at else None, "last_login_at": self.last_login_at.isoformat() if self.last_login_at else None, "login_method": self.login_method, "role": self.role, "assigned_domains": self.assigned_domains or [], "workload": self.workload, "status": self.status, "is_active": self.is_active, "created_at": self.created_at.isoformat() if self.created_at else None, "updated_at": self.updated_at.isoformat() if self.updated_at else None, }