""" 郵件帳號 Model 支援員工在不同網域擁有多個郵件帳號,並管理配額 符合設計文件規範: HR Portal設計文件.md """ from datetime import datetime from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text, ForeignKey, Index from sqlalchemy.orm import relationship from app.db.base import Base class EmailAccount(Base): """郵件帳號表 (一個員工可以有多個郵件帳號)""" __tablename__ = "tenant_email_accounts" __table_args__ = ( # 郵件地址必須唯一 Index("idx_email_accounts_email", "email_address", unique=True), # 員工索引 Index("idx_email_accounts_employee", "employee_id"), # 租戶索引 Index("idx_email_accounts_tenant", "tenant_id"), # 狀態索引 (快速查詢啟用的帳號) Index("idx_email_accounts_active", "is_active"), ) id = Column(Integer, primary_key=True, index=True) tenant_id = Column( Integer, ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True, comment="租戶 ID" ) # 支援個人/部門信箱 account_type = Column( String(20), default='personal', nullable=False, comment="帳號類型: personal(個人), department(部門)" ) employee_id = Column( Integer, ForeignKey("tenant_employees.id", ondelete="CASCADE"), nullable=True, # 部門信箱不需要 employee_id index=True, comment="員工 ID (僅 personal 類型需要)" ) department_id = Column( Integer, ForeignKey("tenant_departments.id", ondelete="CASCADE"), nullable=True, index=True, comment="部門 ID (僅 department 類型需要)" ) # 郵件設定 email_address = Column( String(255), unique=True, nullable=False, index=True, comment="郵件地址 (例如: porsche.chen@lab.taipei)" ) quota_mb = Column( Integer, default=2048, nullable=False, comment="配額 (MB),依職級: Junior=2048, Mid=3072, Senior=5120, Manager=10240" ) # 進階功能 forward_to = Column( String(255), nullable=True, comment="轉寄地址 (可選,例如外部郵箱)" ) auto_reply = Column( Text, nullable=True, comment="自動回覆內容 (可選,例如休假通知)" ) # 通用欄位 is_active = Column(Boolean, default=True, nullable=False, comment="是否啟用") edit_by = Column(String(100), nullable=True, comment="最後編輯者") created_at = Column(DateTime, default=datetime.utcnow, nullable=False, comment="建立時間") updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # 關聯 employee = relationship("Employee", back_populates="email_accounts") tenant = relationship("Tenant") def __repr__(self): return f"" @property def local_part(self) -> str: """郵件前綴 (@ 之前的部分)""" return self.email_address.split('@')[0] if '@' in self.email_address else self.email_address @property def domain_part(self) -> str: """網域部分 (@ 之後的部分)""" return self.email_address.split('@')[1] if '@' in self.email_address else "" @property def quota_gb(self) -> float: """配額 (GB,用於顯示)""" return round(self.quota_mb / 1024, 2) @classmethod def get_default_quota_by_level(cls, job_level: str) -> int: """根據職級取得預設配額 (MB)""" quota_map = { "Junior": 2048, "Mid": 3072, "Senior": 5120, "Manager": 10240, } return quota_map.get(job_level, 2048)