add backend source code
This commit is contained in:
309
backend/app/api/v1/performance_plans.py
Normal file
309
backend/app/api/v1/performance_plans.py
Normal file
@@ -0,0 +1,309 @@
|
||||
"""
|
||||
绩效计划管理 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": "删除成功"
|
||||
}
|
||||
Reference in New Issue
Block a user