- approval_orders/approval_steps 服务层:submit_order(不 commit 不嵌套 audit,业务写路径统一收口)+ act 节点动作 + 分页/详情 - 开关关闭=提单即两级「自动通过」留痕(action=3,operator 记系统); 开启=财务→领导流转,一驳全驳,驳回必填意见 - 节点准入严格按角色(status=1 仅财务、status=2 仅领导),admin 不代办; 模块准入 require_roles 依赖工厂(admin/finance/leader,营销后勤待 澄清 #6 后放开) - 业务接入:创建/编辑带方案即提单(空方案不提单);再编辑自动撤回旧 在途单(node=0/action=4 留痕);AP 编号冲突 create 内可重取(外层 重试兜底)、update 直接抛出防静默丢失 - conftest 兜底清理增审批单(AP 前缀)与开关参数种子基线恢复 - 集成 11 例:自动通过/两节点流转/驳回留痕/缺意见 400/节点准入 403/ admin 不代办/重复操作 400/撤旧建新/模块准入 Co-Authored-By: Claude Code <noreply@anthropic.com>
68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
"""审批管理接口(2026-10-15 复核审批补充需求)。
|
||
|
||
准入:admin/财务/领导可见(营销后勤暂不可见——权限清单待澄清 #6,
|
||
答复后放开为「提交人可见本人单据」)。节点级准入由 service 按单据
|
||
状态二次校验(status=1 仅财务、status=2 仅领导,admin 不代办)。
|
||
提单不经本模块:由业务写路径(创建/编辑带二次分配方案)自动触发。
|
||
"""
|
||
|
||
from typing import Annotated
|
||
|
||
from fastapi import APIRouter, Depends, Path, Query
|
||
|
||
from app.api.deps import DbSession, RequestMetaDep, require_roles
|
||
from app.core.constants import ROLE_ADMIN, ROLE_FINANCE, ROLE_LEADER
|
||
from app.core.response import ApiResponse, PageResult, ok
|
||
from app.models import User
|
||
from app.schemas.approval import (
|
||
ApprovalActionIn,
|
||
ApprovalOrderDetailOut,
|
||
ApprovalOrderOut,
|
||
ApprovalQuery,
|
||
)
|
||
from app.services import approval_service
|
||
|
||
router = APIRouter(prefix="/approvals", tags=["系统管理 · 审批管理"])
|
||
|
||
# 模块准入:可见集合(节点准入在 service 层按状态二次判定)
|
||
_ApprovalUser = Annotated[User, Depends(require_roles(ROLE_ADMIN, ROLE_FINANCE, ROLE_LEADER))]
|
||
|
||
|
||
@router.get("", response_model=ApiResponse[PageResult[ApprovalOrderOut]], summary="审批单列表")
|
||
def list_orders(
|
||
session: DbSession,
|
||
_: _ApprovalUser,
|
||
query: Annotated[ApprovalQuery, Query()],
|
||
) -> ApiResponse[PageResult[ApprovalOrderOut]]:
|
||
"""分页查询审批单。"""
|
||
return ok(approval_service.list_orders(session, query))
|
||
|
||
|
||
@router.get("/{order_id}", response_model=ApiResponse[ApprovalOrderDetailOut], summary="审批详情")
|
||
def get_order(
|
||
session: DbSession,
|
||
_: _ApprovalUser,
|
||
order_id: Annotated[int, Path(ge=1)],
|
||
) -> ApiResponse[ApprovalOrderDetailOut]:
|
||
"""审批单详情(含节点时间线)。"""
|
||
return ok(approval_service.get_order(session, order_id))
|
||
|
||
|
||
@router.post(
|
||
"/{order_id}/action",
|
||
response_model=ApiResponse[ApprovalOrderDetailOut],
|
||
summary="节点动作(通过/驳回)",
|
||
)
|
||
def act_on_order(
|
||
payload: ApprovalActionIn,
|
||
session: DbSession,
|
||
current_user: _ApprovalUser,
|
||
meta: RequestMetaDep,
|
||
order_id: Annotated[int, Path(ge=1)],
|
||
) -> ApiResponse[ApprovalOrderDetailOut]:
|
||
"""财务复核 / 领导审核;一驳全驳,驳回须填意见。"""
|
||
return ok(
|
||
approval_service.act(session, order_id, payload, operator=current_user, meta=meta),
|
||
message="已提交",
|
||
)
|