""" 绩效计划管理 API """ from typing import Annotated, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.core.security import get_current_active_user, get_current_manager_user from app.schemas.schemas import ( PerformancePlanCreate, PerformancePlanUpdate, PerformancePlanResponse, PerformancePlanStats, PlanKpiRelationCreate, PlanKpiRelationUpdate, ResponseBase ) from app.services.performance_plan_service import PerformancePlanService from app.models.models import User, PlanStatus router = APIRouter(prefix="/plans", tags=["绩效计划管理"]) @router.get("", summary="获取绩效计划列表") async def get_performance_plans( plan_level: Optional[str] = Query(None, description="计划层级"), plan_year: Optional[int] = Query(None, description="计划年度"), department_id: Optional[int] = Query(None, description="科室 ID"), status: Optional[str] = Query(None, description="状态"), page: int = Query(1, ge=1, description="页码"), page_size: int = Query(20, ge=1, le=100, description="每页数量"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取绩效计划列表""" plans, total = await PerformancePlanService.get_list( db, plan_level, plan_year, department_id, status, page, page_size ) # 构建响应数据 plan_list = [] for plan in plans: plan_dict = { "id": plan.id, "plan_name": plan.plan_name, "plan_code": plan.plan_code, "plan_level": plan.plan_level, "plan_year": plan.plan_year, "plan_month": plan.plan_month, "status": plan.status, "department_id": plan.department_id, "department_name": plan.department.name if plan.department else None, "staff_id": plan.staff_id, "staff_name": plan.staff.name if plan.staff else None, "description": plan.description, "created_at": plan.created_at, "updated_at": plan.updated_at } plan_list.append(plan_dict) return { "code": 200, "message": "success", "data": plan_list, "total": total, "page": page, "page_size": page_size } @router.get("/tree", summary="获取绩效计划树") async def get_performance_plan_tree( plan_year: Optional[int] = Query(None, description="计划年度"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取绩效计划树形结构""" tree = await PerformancePlanService.get_tree(db, plan_year) return { "code": 200, "message": "success", "data": tree } @router.get("/stats", summary="获取绩效计划统计") async def get_performance_plan_stats( plan_year: Optional[int] = Query(None, description="计划年度"), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取绩效计划统计信息""" stats = await PerformancePlanService.get_stats(db, plan_year) return { "code": 200, "message": "success", "data": stats } @router.get("/{plan_id}", summary="获取绩效计划详情") async def get_performance_plan( plan_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """获取绩效计划详情""" plan = await PerformancePlanService.get_by_id(db, plan_id) if not plan: raise HTTPException(status_code=404, detail="绩效计划不存在") # 构建响应数据 kpi_relations = [] for relation in plan.kpi_relations: kpi_relations.append({ "id": relation.id, "indicator_id": relation.indicator_id, "indicator_name": relation.indicator.name if relation.indicator else None, "indicator_code": relation.indicator.code if relation.indicator else None, "target_value": relation.target_value, "target_unit": relation.target_unit, "weight": relation.weight, "scoring_method": relation.scoring_method, "scoring_params": relation.scoring_params, "remark": relation.remark }) plan_data = { "id": plan.id, "plan_name": plan.plan_name, "plan_code": plan.plan_code, "plan_level": plan.plan_level, "plan_year": plan.plan_year, "plan_month": plan.plan_month, "plan_type": plan.plan_type, "department_id": plan.department_id, "department_name": plan.department.name if plan.department else None, "staff_id": plan.staff_id, "staff_name": plan.staff.name if plan.staff else None, "parent_plan_id": plan.parent_plan_id, "description": plan.description, "strategic_goals": plan.strategic_goals, "key_initiatives": plan.key_initiatives, "status": plan.status, "submitter_id": plan.submitter_id, "submit_time": plan.submit_time, "approver_id": plan.approver_id, "approve_time": plan.approve_time, "approve_remark": plan.approve_remark, "version": plan.version, "is_active": plan.is_active, "created_at": plan.created_at, "updated_at": plan.updated_at, "kpi_relations": kpi_relations } return { "code": 200, "message": "success", "data": plan_data } @router.post("", summary="创建绩效计划") async def create_performance_plan( plan_data: PerformancePlanCreate, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """创建绩效计划""" plan = await PerformancePlanService.create(db, plan_data, current_user.id) return { "code": 200, "message": "创建成功", "data": {"id": plan.id} } @router.put("/{plan_id}", summary="更新绩效计划") async def update_performance_plan( plan_id: int, plan_data: PerformancePlanUpdate, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """更新绩效计划""" plan = await PerformancePlanService.update(db, plan_id, plan_data) if not plan: raise HTTPException(status_code=404, detail="绩效计划不存在") return { "code": 200, "message": "更新成功", "data": {"id": plan.id} } @router.post("/{plan_id}/submit", summary="提交绩效计划") async def submit_performance_plan( plan_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_active_user) ): """提交绩效计划""" plan = await PerformancePlanService.submit(db, plan_id) if not plan: raise HTTPException(status_code=400, detail="无法提交,计划不存在或状态不允许") return { "code": 200, "message": "提交成功" } @router.post("/{plan_id}/approve", summary="审批绩效计划") async def approve_performance_plan( plan_id: int, approved: bool = Query(..., description="是否通过"), remark: Optional[str] = Query(None, description="审批意见"), db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """审批绩效计划(需要管理员或经理权限)""" plan = await PerformancePlanService.approve(db, plan_id, current_user.id, approved, remark) if not plan: raise HTTPException(status_code=400, detail="无法审批,计划不存在或状态不允许") return { "code": 200, "message": "审核通过" if approved else "已驳回" } @router.post("/{plan_id}/activate", summary="激活绩效计划") async def activate_performance_plan( plan_id: int, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """激活绩效计划(需要管理员或经理权限)""" plan = await PerformancePlanService.activate(db, plan_id) if not plan: raise HTTPException(status_code=400, detail="无法激活,计划不存在或状态不允许") return { "code": 200, "message": "激活成功" } @router.delete("/{plan_id}", summary="删除绩效计划") async def delete_performance_plan( plan_id: int, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """删除绩效计划(需要管理员或经理权限)""" success = await PerformancePlanService.delete(db, plan_id) if not success: raise HTTPException(status_code=404, detail="绩效计划不存在") return { "code": 200, "message": "删除成功" } @router.post("/{plan_id}/kpi-relations", summary="添加计划指标关联") async def add_kpi_relation( plan_id: int, kpi_data: PlanKpiRelationCreate, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """添加计划指标关联(需要管理员或经理权限)""" relation = await PerformancePlanService.add_kpi_relation(db, plan_id, kpi_data) if not relation: raise HTTPException(status_code=404, detail="绩效计划不存在") return { "code": 200, "message": "添加成功", "data": {"id": relation.id} } @router.put("/kpi-relations/{relation_id}", summary="更新计划指标关联") async def update_kpi_relation( relation_id: int, kpi_data: PlanKpiRelationUpdate, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """更新计划指标关联(需要管理员或经理权限)""" relation = await PerformancePlanService.update_kpi_relation(db, relation_id, kpi_data.model_dump()) if not relation: raise HTTPException(status_code=404, detail="指标关联不存在") return { "code": 200, "message": "更新成功", "data": {"id": relation.id} } @router.delete("/kpi-relations/{relation_id}", summary="删除计划指标关联") async def delete_kpi_relation( relation_id: int, db: AsyncSession = Depends(get_db), current_user: Annotated[User, Depends(get_current_manager_user)] = None ): """删除计划指标关联(需要管理员或经理权限)""" success = await PerformancePlanService.delete_kpi_relation(db, relation_id) if not success: raise HTTPException(status_code=404, detail="指标关联不存在") return { "code": 200, "message": "删除成功" }