""" 測試資料工廠 """ from datetime import date from typing import Optional from sqlalchemy.orm import Session from app.core.security import get_password_hash from app.models.department import Department from app.models.employee import Employee from app.models.kpi_period import KPIPeriod from app.models.kpi_template import KPITemplate from app.models.kpi_sheet import KPISheet from app.models.kpi_item import KPIItem class DepartmentFactory: """部門工廠""" _counter = 0 @classmethod def create( cls, db: Session, code: Optional[str] = None, name: Optional[str] = None, level: str = "DEPT", parent_id: Optional[int] = None, ) -> Department: cls._counter += 1 dept = Department( code=code or f"DEPT{cls._counter:03d}", name=name or f"測試部門{cls._counter}", level=level, parent_id=parent_id, is_active=True, ) db.add(dept) db.flush() return dept class EmployeeFactory: """員工工廠""" _counter = 0 @classmethod def create( cls, db: Session, employee_no: Optional[str] = None, name: Optional[str] = None, department_id: Optional[int] = None, manager_id: Optional[int] = None, role: str = "employee", status: str = "active", ) -> Employee: cls._counter += 1 # 如果沒有指定部門,建立一個 if not department_id: dept = DepartmentFactory.create(db) department_id = dept.id employee = Employee( employee_no=employee_no or f"EMP{cls._counter:05d}", name=name or f"測試員工{cls._counter}", email=f"test{cls._counter}@example.com", password_hash=get_password_hash("password123"), department_id=department_id, manager_id=manager_id, job_title="工程師", status=status, role=role, ) db.add(employee) db.flush() return employee class KPIPeriodFactory: """KPI 期間工廠""" _counter = 0 @classmethod def create( cls, db: Session, code: Optional[str] = None, status: str = "setting", year: int = 2024, half: int = 2, ) -> KPIPeriod: cls._counter += 1 if half == 1: start = date(year, 1, 1) end = date(year, 6, 30) setting_end = date(year, 1, 14) else: start = date(year, 7, 1) end = date(year, 12, 31) setting_end = date(year, 7, 14) period = KPIPeriod( code=code or f"{year}H{half}_{cls._counter}", name=f"{year}年{'上' if half == 1 else '下'}半年", start_date=start, end_date=end, setting_start=start, setting_end=setting_end, status=status, ) db.add(period) db.flush() return period class KPITemplateFactory: """KPI 範本工廠""" _counter = 0 @classmethod def create( cls, db: Session, code: Optional[str] = None, name: Optional[str] = None, category: str = "financial", ) -> KPITemplate: cls._counter += 1 template = KPITemplate( code=code or f"TPL{cls._counter:03d}", name=name or f"測試 KPI 範本 {cls._counter}", category=category, default_weight=20, level0_desc="未達標", level1_desc="基本達成", level2_desc="達成目標", level3_desc="挑戰目標", level4_desc="超越目標", is_active=True, ) db.add(template) db.flush() return template class KPISheetFactory: """KPI 表單工廠""" @classmethod def create( cls, db: Session, employee: Optional[Employee] = None, period: Optional[KPIPeriod] = None, status: str = "draft", with_items: bool = True, ) -> KPISheet: if not employee: employee = EmployeeFactory.create(db) if not period: period = KPIPeriodFactory.create(db) sheet = KPISheet( employee_id=employee.id, period_id=period.id, department_id=employee.department_id, status=status, ) db.add(sheet) db.flush() # 建立 KPI 項目(權重總和 100%) if with_items: weights = [30, 25, 25, 20] categories = ["financial", "customer", "internal", "learning"] for i, (weight, category) in enumerate(zip(weights, categories)): template = KPITemplateFactory.create(db, category=category) item = KPIItem( sheet_id=sheet.id, template_id=template.id, sort_order=i, name=f"KPI 項目 {i + 1}", category=category, weight=weight, level0_criteria="未達標", level1_criteria="基本達成", level2_criteria="達成目標", level3_criteria="挑戰目標", level4_criteria="超越目標", ) db.add(item) db.flush() return sheet