Files
xiaoqu_mcp_service/xiaoqu-agent-service/doc/warehouse-order-handler-update-mcp-design.md
T
my_local_kimi_dev2 52ffe8eac2 feat(mcp): 新增仓库单据处理人改派写工具 warehouse.order.handler.update(REQ-20261107-0002)
- 平台首个 kind=write 工具,研发/运维专用 scope 门禁,无行级权限
- 按单号改派出库/入库/调拨/划转单当前待办处理人:UPDATE 流程物理表
  warehouse_out_audit_process / warehouse_in_audit_process / warehouse_allocati_process
  的 schedule_state=1 待办行 user_id/user_name,补 modify_id/modify_time
- 调拨/划转按 warehouse_allocation.op_type(0/2) 一致性校验;并行待办行全部改派
- 新处理人按手机号查 m0 user(soft_delete=0 精确匹配);服务身份 Token 拒绝
- 新增 WarehouseAllocatiProcess 实体+Mapper,WarehouseAllocation 补 orderState 列
- 525 tests 全绿(+10)
2026-11-07 16:28:22 +08:00

8.0 KiB
Raw Blame History

仓库单据处理人改派 MCP 工具设计(warehouse.order.handler.update)

  • 需求:REQ-20261107-0002(ai-proj id 6442)
  • 状态:已评审通过(2026-11-07 王恒拍板:入参=单号+手机号,手机号查 m0 user 表带 soft_delete=0 条件,其余按建议)
  • 日期:2026-11-07

1. 背景

运维/研发场景需要把"卡"在某个处理人名下的仓库单据待办改派给他人(人员离职、调岗、账号停用等)。 老系统(xiaoqu-franchisee)没有"修改处理人"接口(已全仓检索确认),目前只能靠人工改库。 本需求提供 MCP 写工具完成改派,访问控制完全靠专用作用域(scope)门禁,不做行级权限。

这是 agent-service 的首个 kind=write 工具(ToolKindRegistry 已预留 write 注解: readOnlyHint=false / idempotentHint=false / destructiveHint=true)。

2. 调研结论(行号级依据)

2.1 四类单据的表结构

单据 主表(m2) 单号列 流程物理表 流程视图
出库单 warehouse_out out_order_no warehouse_out_audit_process warehouse_out_process
入库单 warehouse_in in_order_no warehouse_in_audit_process warehouse_in_process
调拨单 warehouse_allocation(op_type=0) allocation_order_no warehouse_allocati_process warehouse_allocation_process
划转单 warehouse_allocation(op_type=2) allocation_order_no 同上 同上

注意:

  • 调拨/划转是同一张表,靠 op_type 区分(0调拨/1采购/2划转, 见 beans/b2/WarehouseAllocation.java:86)。
  • 流程物理表名是 warehouse_allocati_process(少一个 on,历史拼写,勿写错), 视图 warehouse_allocation_process 才是全名。
  • 视图 *_process 只读展示用;写必须落物理表 *_audit_process / warehouse_allocati_process。

2.2 "当前处理人"的存储语义

  • 流程表中 schedule_state=1(待办)且 soft_delete=0 的行,其 user_id/user_name 即为当前处理人(beans/b2/WarehouseOutProcess.java:54、WarehouseAllocationProcess.java:80; agent-service 的 WarehouseTodoTools 也是按 user_id = 当前登录人 AND schedule_state=1 认定待办归属)。
  • 老系统审批/确认动作均校验操作人 == 待办行 user_id (如 WarehouseAllocationController.java:403-409 先按 schedule_state=1 取当前用户待办行再办理)。
  • 因此改派 = UPDATE 待办行的 user_id / user_name(并按仓库规范补 modify_id/modify_time)。
  • 一张单同一时刻可能有多条并行待办行(多人会审),也可能为 0 条(已完成/已撤销/作废/无需待办)。

2.3 agent-service 现状

  • 本地已有实体/Mapper:WarehouseOut / WarehouseIn / WarehouseAllocation / WarehouseOutAuditProcess / WarehouseInAuditProcess(含 Mapper)。
  • 缺:warehouse_allocati_process 的本地实体与 Mapper(需新增, 参照 beans/b2/WarehouseAllocatiProcess.java 全列复制——PR #30/#31 教训: publicbeanandmap 不是 Maven 依赖,必须本地拷贝且列要全)。
  • 新处理人校验用 m0 user 表(本地实体 me.iiv.agent.entity.m0.User 已存在)。
  • 审计写 svc 库 audit_log(实体 me.iiv.agent.entity.svc.AuditLog 已存在, 字段含 userId/tokenId/toolName/paramsDigest/requestId 等)。

3. 工具设计

3.1 工具定义(1 个工具)

warehouse.order.handler.update   kind=write   category=admin

参数:

参数 必填 说明
orderType 是 枚举:out 出库单 / in 入库单 / allocation 调拨单 / transfer 划转单
orderNo 是 单据编号(精确匹配,去空格)
newHandlerMobile 是 新处理人手机号(m0 user.mobile 精确匹配,拍板定案:只认手机号)
memo 否 改派原因,写入审计日志

行为:

  1. 按 orderType 路由到对应主表,按单号精确查询(soft_delete=0),不存在 → NOT_FOUND。
  2. 一致性校验:allocation 要求 op_type=0,transfer 要求 op_type=2,不符 → INVALID_ARGUMENT (防止把调拨单号当划转单改)。
  3. 查该单流程物理表中 schedule_state=1 AND soft_delete=0 的待办行;0 条 → NOT_FOUND「该单据当前无待办处理人(已完成/已撤销/作废)」,并返回 orderStateText。
  4. 新处理人校验:m0 user 存在且 soft_delete=0,否则 INVALID_ARGUMENT。
  5. UPDATE 所有待办行:user_id、user_name(取 user 表真实姓名)、 modify_id=调用方 userId、modify_time=now。
  6. 写 svc audit_log:调用方 userId/tokenId、工具名、参数摘要 (orderType/orderNo/新旧处理人/memo)、request_id。
  7. 返回 before/after。

返回结构:

{
  "orderType": "out",
  "orderNo": "OUT20261001001",
  "orderId": 12345,
  "orderState": 2,
  "orderStateText": "待出库",
  "changedRows": [
    {"processId": 9001, "oldUserId": 101, "oldUserName": "张三",
     "newUserId": 205, "newUserName": "李四"}
  ],
  "changedCount": 1,
  "requestId": "..."
}

报错沿用 ToolCallException 透出风格(INVALID_ARGUMENT / NOT_FOUND_OR_FORBIDDEN / DATA_INTEGRITY_ERROR)。

审计说明:GuardedToolCallback 已对每次调用自动写 svc audit_log(操作人 userId/tokenId、 参数摘要、结果状态),工具内再以 request_id 打一条 before/after 服务端日志,两者合一可追溯。

3.2 权限与作用域(核心拍板点已按用户口径定)

  • 不做任何行级权限,不调用 PermissionService 行过滤;任何单据都可改。
  • 访问控制 = scope 绑定:工具上线后只绑用户新建的"研发专用" scope (不绑 1/2/3/5,seed-dev.sql 也不预绑任何 scope)。
  • 服务 Token(principalType=service)只能签 SYNC 作用域,天然调不到本工具; 调用方必须是持有该专用 scope 的用户委托 Token。
  • 审计兜底:audit_log 记录每次调用的操作人 token 身份,事后可追溯。

4. 与老系统差异 / 风险说明

  1. 老系统无此功能,MCP 为新增能力,无兼容包袱。
  2. 改派只动流程表待办行,不动主表、不重推审批流、不发消息通知 (老系统审批动作会触发消息,改派属于运维动作,是否通知新处理人见拍板点 5)。
  3. 改派后新处理人在老系统 App/PC 端即可正常看到待办并办理(语义等价于原处理人办理)。
  4. 视图 warehouse_allocation_process.next_user_name 等冗余字段由视图实时计算,无需同步改。

5. 拍板结论(2026-11-07 王恒已拍板)

  1. 1 工具 + orderType 枚举 ✅(不拆 4 个)。
  2. 新处理人入参:只认 mobile 精确匹配(拍板定案,去掉 userId 入参); 手机号查 m0 user 必须带 soft_delete=0 条件。
  3. 并行多条待办行:默认全部改派并逐行返回。
  4. 不加 dryRun(返回已含 before/after,audit_log 可追溯)。
  5. 不发系统消息(运维动作,避免惊动业务消息流)。

6. 改动文件清单

文件 动作
entity/m2/WarehouseAllocatiProcess.java 新增(全列本地拷贝)
mapper/m2/WarehouseAllocatiProcessMapper.java 新增
mcp/tool/WarehouseOrderAdminTools.java 新增(1 个工具方法)
mcp/tool/WarehouseOrderAdminToolsTest.java 新增(参数校验/单号不存在/op_type 不一致/无待办行/并行多行/新处理人不存在/审计写入)
doc/agent-mcp-tools-reference.md 追加工具章节
README.md 工具表登记

装配层零改动(组件扫描自动注册)。seed-dev.sql 不预绑 scope。

7. 上线步骤

  1. 全量 ./mvnw clean package 绿 → push main → remote-deploy。
  2. 王恒已建好"研发专用" scope(2026-11-07 确认)→ 查 scope id 后在 prod svc 库 INSERT IGNORE INTO scope_tool(scope_id, tool_id) 只绑该 scope。
  3. 生产冒烟:用专用 scope 签用户 Token,对一张测试单改派 → 验证老系统待办归属变化 → 改回。