Files
KPI-management/tests/factories.py
DonaldFang 方士碩 f810ddc2ea Initial commit: KPI Management System Backend
Features:
- FastAPI backend with JWT authentication
- MySQL database with SQLAlchemy ORM
- KPI workflow: draft → pending → approved → evaluation → completed
- Ollama LLM API integration for AI features
- Gitea API integration for version control
- Complete API endpoints for KPI, dashboard, notifications

Tables: KPI_D_* prefix naming convention

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 16:20:57 +08:00

205 lines
5.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
測試資料工廠
"""
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