PayrollManagementSystem/backend/app/api/v1/base/personnel.py

144 lines
5.1 KiB
Python
Raw Normal View History

"""人员管理接口(需求 2.1.1:人员档案 + 辐射区域 + 拓展计划)。
基础数据属业务操作,**登录即可访问**(不要求管理员,对照系统管理模块)。
校验规则(岗位/经理合法性、删除保护、子表全量替换的防御写法)见
`personnel_service` 模块 docstring —— 前端提示之外,后端校验是唯一防线。
写操作经 `RequestMetaDep` 带入请求元信息由 service 层写入操作日志。
"""
from typing import Annotated
from fastapi import APIRouter, Depends, Path, Query
from app.api.deps import DbSession, RequestMetaDep, get_current_user
from app.core.response import ApiResponse, PageResult, ok
from app.models import User
from app.schemas.personnel import (
PersonnelCreateIn,
PersonnelDetailOut,
PersonnelOut,
PersonnelQuery,
PersonnelStatusIn,
PlanReplaceIn,
RegionReplaceIn,
)
from app.services import personnel_service
# 基础数据是业务操作:登录即可,不要求管理员(区别于系统管理的 AdminUser)
CurrentUser = Annotated[User, Depends(get_current_user)]
router = APIRouter(prefix="/personnel", tags=["人员管理"])
@router.get("", response_model=ApiResponse[PageResult[PersonnelOut]], summary="人员列表")
def list_personnel(
session: DbSession,
_: CurrentUser,
query: Annotated[PersonnelQuery, Query()],
) -> ApiResponse[PageResult[PersonnelOut]]:
"""分页查询人员(含离职)。姓名模糊匹配,可按状态与岗位筛选。"""
return ok(personnel_service.list_personnel(session, query))
@router.post("", response_model=ApiResponse[PersonnelOut], summary="新增人员")
def create_personnel(
session: DbSession,
current_user: CurrentUser,
payload: PersonnelCreateIn,
meta: RequestMetaDep,
) -> ApiResponse[PersonnelOut]:
"""新增人员,默认在职。岗位须存在且启用;直属经理不能是自己且须在职。"""
return ok(
personnel_service.create_personnel(session, payload, operator=current_user, meta=meta),
message="人员已创建",
)
@router.get("/{personnel_id}", response_model=ApiResponse[PersonnelDetailOut], summary="人员详情")
def get_personnel(
session: DbSession,
_: CurrentUser,
personnel_id: Annotated[int, Path(ge=1)],
) -> ApiResponse[PersonnelDetailOut]:
"""人员详情,附辐射区域与拓展计划,供编辑抽屉一次回显。"""
return ok(personnel_service.get_detail(session, personnel_id))
@router.put("/{personnel_id}", response_model=ApiResponse[PersonnelOut], summary="编辑人员")
def update_personnel(
session: DbSession,
current_user: CurrentUser,
personnel_id: Annotated[int, Path(ge=1)],
payload: PersonnelCreateIn,
meta: RequestMetaDep,
) -> ApiResponse[PersonnelOut]:
"""编辑人员(全量提交,不含状态)。校验规则同新增。"""
return ok(
personnel_service.update_personnel(
session, personnel_id, payload, operator=current_user, meta=meta
),
message="已保存",
)
@router.delete("/{personnel_id}", response_model=ApiResponse[None], summary="删除人员")
def delete_personnel(
session: DbSession,
current_user: CurrentUser,
personnel_id: Annotated[int, Path(ge=1)],
meta: RequestMetaDep,
) -> ApiResponse[None]:
"""删除人员。被团队成员或客户归属引用时禁删,应改为离职。"""
personnel_service.delete_personnel(session, personnel_id, operator=current_user, meta=meta)
return ok(message="人员已删除")
@router.put(
"/{personnel_id}/status",
response_model=ApiResponse[PersonnelOut],
summary="设为在职/离职",
)
def set_status(
session: DbSession,
current_user: CurrentUser,
personnel_id: Annotated[int, Path(ge=1)],
payload: PersonnelStatusIn,
meta: RequestMetaDep,
) -> ApiResponse[PersonnelOut]:
"""在职/离职切换。离职人员不可再被业务与客户归属引用。"""
result = personnel_service.set_status(
session, personnel_id, payload.status, operator=current_user, meta=meta
)
return ok(result, message="已设为在职" if payload.status == 1 else "已设为离职")
@router.put("/{personnel_id}/regions", response_model=ApiResponse[None], summary="维护辐射区域")
def replace_regions(
session: DbSession,
current_user: CurrentUser,
personnel_id: Annotated[int, Path(ge=1)],
payload: RegionReplaceIn,
meta: RequestMetaDep,
) -> ApiResponse[None]:
"""全量替换辐射区域,空列表即清空。"""
personnel_service.replace_regions(
session, personnel_id, payload, operator=current_user, meta=meta
)
return ok(message="已保存")
@router.put("/{personnel_id}/plans", response_model=ApiResponse[None], summary="维护拓展计划")
def replace_plans(
session: DbSession,
current_user: CurrentUser,
personnel_id: Annotated[int, Path(ge=1)],
payload: PlanReplaceIn,
meta: RequestMetaDep,
) -> ApiResponse[None]:
"""全量替换拓展计划,空列表即清空。"""
personnel_service.replace_plans(
session, personnel_id, payload, operator=current_user, meta=meta
)
return ok(message="已保存")