- 四层实现:仓储(FOR UPDATE 锁行 + 引用计数钩子预留)/ schemas / service / api 共 7 个端点 - 保护规则:内置岗位禁删禁停、编码创建后不可改、模板须在注册表内(未注册 400) - 写操作全走审计上下文;冒烟验证 7 项(含成功/失败双路径落日志) - 端点:列表/新增/详情/编辑/删除/启停 + meta/templates 模板下拉 Co-Authored-By: Claude Code <noreply@anthropic.com>
123 lines
4.2 KiB
Python
123 lines
4.2 KiB
Python
"""业务岗位角色管理接口(需求 #28:岗位可扩展 + 绑定公式模板)。
|
||
|
||
保护规则(内置岗位禁删禁停、编码不可改、模板须在注册表内)见
|
||
`business_role_service` 模块 docstring。前端会禁用相应按钮,但**后端校验是唯一防线**。
|
||
|
||
全部要求管理员权限;写操作经 `RequestMetaDep` 带入请求元信息由 service
|
||
层写入操作日志。
|
||
"""
|
||
|
||
from typing import Annotated
|
||
|
||
from fastapi import APIRouter, Path, Query
|
||
|
||
from app.api.deps import AdminUser, DbSession, RequestMetaDep
|
||
from app.core.response import ApiResponse, PageResult, ok
|
||
from app.schemas.business_role import (
|
||
BusinessRoleCreateIn,
|
||
BusinessRoleOut,
|
||
BusinessRoleQuery,
|
||
BusinessRoleStatusIn,
|
||
BusinessRoleUpdateIn,
|
||
TemplateOptionOut,
|
||
)
|
||
from app.services import business_role_service
|
||
|
||
router = APIRouter(prefix="/business-roles", tags=["系统管理 · 岗位角色"])
|
||
|
||
|
||
@router.get("", response_model=ApiResponse[PageResult[BusinessRoleOut]], summary="岗位列表")
|
||
def list_roles(
|
||
session: DbSession,
|
||
_: AdminUser,
|
||
query: Annotated[BusinessRoleQuery, Query()],
|
||
) -> ApiResponse[PageResult[BusinessRoleOut]]:
|
||
"""分页查询业务岗位角色(含停用)。"""
|
||
return ok(business_role_service.list_roles(session, query))
|
||
|
||
|
||
@router.post("", response_model=ApiResponse[BusinessRoleOut], summary="新增岗位")
|
||
def create_role(
|
||
session: DbSession,
|
||
current_user: AdminUser,
|
||
payload: BusinessRoleCreateIn,
|
||
meta: RequestMetaDep,
|
||
) -> ApiResponse[BusinessRoleOut]:
|
||
"""新增岗位。编码全局唯一、创建后不可修改;模板须在注册表内;新岗位默认启用。"""
|
||
return ok(
|
||
business_role_service.create_role(session, payload, operator=current_user, meta=meta),
|
||
message="岗位已创建",
|
||
)
|
||
|
||
|
||
@router.get(
|
||
"/meta/templates",
|
||
response_model=ApiResponse[list[TemplateOptionOut]],
|
||
summary="公式模板下拉",
|
||
)
|
||
def list_template_options(session: DbSession, _: AdminUser) -> ApiResponse[list[TemplateOptionOut]]:
|
||
"""取公式模板下拉(含声明参数,供岗位表单展示)。
|
||
|
||
定义在 `/{role_id}` 之前:静态路径优先,避免 "meta" 被当作路径参数解析。
|
||
"""
|
||
return ok(business_role_service.list_template_options())
|
||
|
||
|
||
@router.get("/{role_id}", response_model=ApiResponse[BusinessRoleOut], summary="岗位详情")
|
||
def get_role(
|
||
session: DbSession,
|
||
_: AdminUser,
|
||
role_id: Annotated[int, Path(ge=1)],
|
||
) -> ApiResponse[BusinessRoleOut]:
|
||
"""按主键查询岗位详情。"""
|
||
return ok(business_role_service.get_role(session, role_id))
|
||
|
||
|
||
@router.put("/{role_id}", response_model=ApiResponse[BusinessRoleOut], summary="编辑岗位")
|
||
def update_role(
|
||
session: DbSession,
|
||
current_user: AdminUser,
|
||
role_id: Annotated[int, Path(ge=1)],
|
||
payload: BusinessRoleUpdateIn,
|
||
meta: RequestMetaDep,
|
||
) -> ApiResponse[BusinessRoleOut]:
|
||
"""编辑岗位名称/模板/说明/排序。
|
||
|
||
**不含 role_code** —— 编码是参数维度值与模板绑定的锚点。
|
||
"""
|
||
return ok(
|
||
business_role_service.update_role(
|
||
session, role_id, payload, operator=current_user, meta=meta
|
||
),
|
||
message="已保存",
|
||
)
|
||
|
||
|
||
@router.put(
|
||
"/{role_id}/status", response_model=ApiResponse[BusinessRoleOut], summary="启用/禁用岗位"
|
||
)
|
||
def set_status(
|
||
session: DbSession,
|
||
current_user: AdminUser,
|
||
role_id: Annotated[int, Path(ge=1)],
|
||
payload: BusinessRoleStatusIn,
|
||
meta: RequestMetaDep,
|
||
) -> ApiResponse[BusinessRoleOut]:
|
||
"""启用或禁用岗位。内置岗位不可停用。"""
|
||
result = business_role_service.set_status(
|
||
session, role_id, payload.status, operator=current_user, meta=meta
|
||
)
|
||
return ok(result, message="已启用" if payload.status == 1 else "已禁用")
|
||
|
||
|
||
@router.delete("/{role_id}", response_model=ApiResponse[None], summary="删除岗位")
|
||
def delete_role(
|
||
session: DbSession,
|
||
current_user: AdminUser,
|
||
role_id: Annotated[int, Path(ge=1)],
|
||
meta: RequestMetaDep,
|
||
) -> ApiResponse[None]:
|
||
"""删除岗位。内置岗位不可删除;有人员引用的岗位不可删除。"""
|
||
business_role_service.delete_role(session, role_id, operator=current_user, meta=meta)
|
||
return ok(message="岗位已删除")
|