""" 部門成員 Model 記錄員工與部門的多對多關係 (純粹組織歸屬,與 RBAC 權限無關) """ from datetime import datetime from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import relationship from app.db.base import Base class DepartmentMember(Base): """部門成員表""" __tablename__ = "tenant_dept_members" __table_args__ = ( UniqueConstraint("employee_id", "department_id", name="uq_employee_department"), Index("idx_dept_members_tenant", "tenant_id"), Index("idx_dept_members_employee", "employee_id"), Index("idx_dept_members_department", "department_id"), ) id = Column(Integer, primary_key=True, index=True) tenant_id = Column(Integer, ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, comment="租戶 ID") employee_id = Column(Integer, ForeignKey("tenant_employees.id", ondelete="CASCADE"), nullable=False, comment="員工 ID") department_id = Column(Integer, ForeignKey("tenant_departments.id", ondelete="CASCADE"), nullable=False, comment="部門 ID") position = Column(String(100), nullable=True, comment="在該部門的職稱") membership_type = Column(String(50), default="permanent", nullable=False, comment="成員類型: permanent/temporary/project") # 時間記錄(審計追蹤) joined_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="加入時間") ended_at = Column(DateTime, nullable=True, comment="離開時間(軟刪除)") # 審計欄位 assigned_by = Column(String(36), nullable=True, comment="分配者 keycloak_user_id") removed_by = Column(String(36), nullable=True, comment="移除者 keycloak_user_id") # 通用欄位 is_active = Column(Boolean, default=True, nullable=False, comment="是否啟用") edit_by = Column(String(36), nullable=True, comment="最後編輯者 keycloak_user_id") created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="建立時間") updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False, comment="更新時間") # 關聯 employee = relationship("Employee", back_populates="department_memberships") department = relationship("Department", back_populates="members") def __repr__(self): return f""