"""审批管理接口(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="已提交", )