""" 部門 Schemas (統一樹狀結構) """ from datetime import datetime from typing import Optional, List, Any from pydantic import Field, ConfigDict from app.schemas.base import BaseSchema class DepartmentBase(BaseSchema): """部門基礎 Schema""" name: str = Field(..., min_length=2, max_length=100, description="部門名稱") name_en: Optional[str] = Field(None, max_length=100, description="英文名稱") code: str = Field(..., min_length=1, max_length=20, description="部門代碼") description: Optional[str] = Field(None, description="說明") class DepartmentCreate(DepartmentBase): """創建部門 Schema - parent_id=NULL: 建立第一層部門,可設定 email_domain - parent_id=有值: 建立子部門,不可設定 email_domain (繼承) """ parent_id: Optional[int] = Field(None, description="上層部門 ID (NULL=第一層)") email_domain: Optional[str] = Field(None, max_length=100, description="郵件網域 (只有第一層可設定,例如 ease.taipei)") email_address: Optional[str] = Field(None, max_length=255, description="部門信箱") email_quota_mb: Optional[int] = Field(5120, description="部門信箱配額 (MB)") model_config = ConfigDict( json_schema_extra={ "example": { "parent_id": None, "name": "業務發展部", "name_en": "Business Development", "code": "BD", "email_domain": "ease.taipei", "description": "業務發展相關部門" } } ) class DepartmentUpdate(BaseSchema): """更新部門 Schema 注意: code 和 parent_id 建立後不可修改 email_domain 只有第一層 (depth=0) 可更新 """ name: Optional[str] = Field(None, min_length=2, max_length=100) name_en: Optional[str] = Field(None, max_length=100) description: Optional[str] = None email_domain: Optional[str] = Field(None, max_length=100, description="只有第一層部門可更新") email_address: Optional[str] = Field(None, max_length=255) email_quota_mb: Optional[int] = None is_active: Optional[bool] = None class DepartmentResponse(BaseSchema): """部門響應 Schema""" id: int tenant_id: int parent_id: Optional[int] = None code: str name: str name_en: Optional[str] = None depth: int email_domain: Optional[str] = None effective_email_domain: Optional[str] = None email_address: Optional[str] = None email_quota_mb: int description: Optional[str] = None is_active: bool is_top_level: bool = False created_at: datetime parent_name: Optional[str] = None member_count: Optional[int] = None model_config = ConfigDict(from_attributes=True) class DepartmentListItem(BaseSchema): """部門列表項 Schema""" id: int tenant_id: int parent_id: Optional[int] = None code: str name: str depth: int email_domain: Optional[str] = None effective_email_domain: Optional[str] = None email_address: Optional[str] = None is_active: bool member_count: Optional[int] = None model_config = ConfigDict(from_attributes=True) class DepartmentTreeNode(BaseSchema): """部門樹狀節點 Schema (遞迴)""" id: int code: str name: str name_en: Optional[str] = None depth: int parent_id: Optional[int] = None email_domain: Optional[str] = None effective_email_domain: Optional[str] = None email_address: Optional[str] = None email_quota_mb: int description: Optional[str] = None is_active: bool is_top_level: bool member_count: int = 0 children: List[Any] = [] model_config = ConfigDict(from_attributes=True)