""" 員工身份 Model 一個員工可以在多個事業部任職,每個事業部對應一個身份 """ from datetime import datetime, date from sqlalchemy import Column, Integer, String, Boolean, Date, DateTime, ForeignKey, UniqueConstraint from sqlalchemy.orm import relationship from app.db.base import Base class EmployeeIdentity(Base): """員工身份表""" __tablename__ = "employee_identities" __table_args__ = ( UniqueConstraint("tenant_id", "employee_id", "business_unit_id", name="uq_tenant_emp_bu"), ) id = Column(Integer, primary_key=True, index=True) tenant_id = Column(Integer, ForeignKey("organizes.id", ondelete="CASCADE"), nullable=False, index=True, comment="租戶 ID") employee_id = Column(Integer, ForeignKey("employees.id", ondelete="CASCADE"), nullable=False, index=True) # SSO 帳號 (= 郵件地址) username = Column(String(100), unique=True, nullable=False, index=True, comment="SSO 帳號 (porsche.chen@lab.taipei)") keycloak_id = Column(String(100), unique=True, nullable=False, index=True, comment="Keycloak UUID") # 組織與職務 business_unit_id = Column(Integer, ForeignKey("business_units.id"), nullable=False, index=True) department_id = Column(Integer, ForeignKey("departments.id"), nullable=True, index=True) job_title = Column(String(100), nullable=False, comment="職稱") job_level = Column(String(20), nullable=False, comment="職級 (Junior/Mid/Senior/Manager)") is_primary = Column(Boolean, default=False, nullable=False, comment="是否為主要身份") # 郵件配額 email_quota_mb = Column(Integer, nullable=False, comment="郵件配額 (MB)") # 時間記錄 started_at = Column(Date, nullable=False, comment="開始日期") ended_at = Column(Date, nullable=True, comment="結束日期") is_active = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # 關聯 tenant = relationship("Tenant") employee = relationship("Employee", back_populates="identities") business_unit = relationship("BusinessUnit", back_populates="employee_identities") department = relationship("Department") # back_populates 已移除 (employee_identities 廢棄) def __repr__(self): return f"" @property def email(self) -> str: """郵件地址 (= SSO 帳號)""" return self.username @property def is_cross_department(self) -> bool: """是否跨部門任職 (檢查同一員工是否有其他身份)""" return len(self.employee.identities) > 1 def generate_username(self, username_base: str, email_domain: str) -> str: """生成 SSO 帳號""" return f"{username_base}@{email_domain}"