Files
xiaoqu_mcp_service/xiaoqu-agent-service/doc/warehouse-todo-mcp-tool-design.md
T
my_local_kimi_dev2 78e319c2f9 feat(mcp): add warehouse todo unified query tool
Merge outbound/inbound/allocation process views into warehouse.todo.list.query,
filtered by task assignee (user_id) matching legacy todo semantics (REQ-20260915-0008)
2026-09-15 17:32:59 +08:00

5.8 KiB
Raw Blame History

仓库待办 MCP 工具设计(REQ-20260915-0008)

1. 范围与评审结论

老系统有 4 个"待办"接口,本需求统一为一个工具:

老系统接口 数据来源
POST /myWarehouseOut/needToBeDealtWith m2 视图 warehouse_out_process
POST /myWarehouseIn/needToBeDealtWith m2 视图 warehouse_in_process
POST /warehouseAllocation/warehouseAllocationProcessListByPage(调拨/划转/采购共用) m2 视图 warehouse_allocation_process

新增工具:warehouse.todo.list.query(warehouse/read),统一查询当前登录人的仓库待办。

2. 待办语义(以老系统为准)

流程视图一行 = 单据 × 处理人 × 待办环节。待办判定:

user_id = 当前登录人 AND soft_delete = 0 AND operation_type IN (0, 1, 2)
  • operation_type=3 为"驳回或修改记录",纯日志不需要待办,排除(出入库视图); 调拨视图 operation_type=4(撤销)同为纯日志,也被 IN (0,1,2) 排除。
  • 不按代理商过滤:待办是"人"的语义,不是代理商数据权限语义。 老系统出入库待办同样只按 user_id 过滤(input.setUserId(user.getId())), 只有调拨待办显式 eq("user_id", user.getId()) 且代理行级过滤被注释掉, 与本实现一致。

operation_type 枚举(老系统视图字段注释,xiaoqu-publicbeanandmap beans/b2):

值 出库/入库视图 调拨视图
0 审批流操作 审批流操作
1 确认出库 / 确认入库 确认入库操作
2 本人修改(需申请人待办) 确认出库操作
3 驳回或修改操作(纯日志,排除) 本人修改
4 — 撤销(纯日志,排除)

schedule_state:0=无需待办,1=待办,2=已办。

order_state:出库/入库单 0=待审核 1=被驳回 2=待出库/待入库 3=已完成 4=已撤销 5=作废; 调拨类 0=待审核 1=被驳回 2=待出库 3=待入库 4=已完成 5=已撤销 6=作废。调拨视图 op_type: 0=调拨(调拨单),1=采购(采购单),2=划转(划转单)。

3. 单据类型与调拨三视角

  • 出库单(24 开头单号)、入库单(23 开头)是独立表。
  • 调拨/采购/划转是同一张 warehouse_allocation 表,op_type 区分。
  • 调拨/划转审批通过后由 WarehouseServiceImpl.procAfterAllocation 生成真实入库单 + 出库单并回填 allocation_order_no,同一笔调拨最多以 3 个视角出现在待办里 (调拨审批/确认、出库执行、入库执行)。这是正常业务,不去重; 派生出入库单带 derivedFrom="allocation" 标记,客户端可按 allocationOrderNo 归并。

4. 工具契约

入参全部可选:

参数 说明
docType out / in / allocation / all,默认 all;allocation 涵盖调拨/采购/划转
todoOnly 默认 true 只返回 schedule_state=1 真待办;false 返回当前用户参与过的全部单据
orderState 按单据状态过滤(枚举值见上,写入 description)
orderNo 单据主单号模糊匹配(出库/入库/调拨单号)
page / rows 默认 1 / 20,rows >100 截断为 100 并在 notice 提示

出参:total/page/rows/records。每条 record 统一结构:docType/docTypeText (出库单/入库单/调拨单/采购单/划转单)、docId/docNo、orderState/orderStateText、 scheduleState/scheduleStateText、operationType/operationTypeText(当前待办环节)、 仓库名(allocation 为 warehouseOutName/warehouseInName)、agentId/agentName、 申请人/申请时间、allocationOrderNo 等关联单号(out/in 另含 mallOrderNo, in 另含关联 outOrderNo)、派生单 derivedFrom="allocation"; allocation 记录另含 opType/opTypeText/allocationCount/allocationDate/nextUserName/inUserName/outUserName。

排序:申请时间倒序(null 在后),同时间按单据 id 倒序。

5. 实现要点

  • 两阶段分页:阶段一按过滤条件全量查流程行(只 select 单据 id + 申请时间), 内存按单据 id 去重;内存分页;阶段二按页内 id 批量查视图整行组装。 避开老系统 GROUP BY 下 selectCount 不可靠的坑,天然防 N+1。 (注意:阶段一只取 id 列时若同一单据多行需内存去重,本实现用 putIfAbsent。)
  • 多环节取行:一个单据对同一用户可能有多行(已办 + 待办),todoOnly=false 时 优先取 schedule_state=1 的行作为"当前待办环节";todoOnly=true 时全部行均为待办,取首行。
  • 权限:只用 AuthContextHolder 当前用户 id 做 user_id 过滤, 不叠加 PermissionService 行级过滤。

6. 与老系统的已知差异

  • 老系统出入库待办接口按 GROUP BY (单据id, schedule_state, operation_type) 分页, 同一单据可能按环节拆成多行返回;本实现按单据聚合为一条记录, operationType/scheduleState 取当前待办环节。更符合"待办列表"语义。
  • 老系统调拨待办不过滤 operation_type(会带入撤销日志行);本实现按统一语义 IN (0,1,2) 排除,同时把调拨视图被驳回后"本人修改"(type=3)一并排除 (与出入库视图 type=3 语义对齐的取舍)。如需申请人修改待办可再评估。
  • 老系统出入库待办前端可传 schedule_state 筛选"已办";本实现用 todoOnly=false 表达。

7. 验收

  • 三类型合并排序分页、rows 截断 notice、派生单 derivedFrom 标记;
  • todoOnly=true/false 两态、orderState/orderNo/docType 过滤、非法 docType 拒绝;
  • Spring AI schema 发布(@Tool + @XqTool 自动注册,ToolSyncService 同步 tool 表);
  • 固定 TZ=Asia/Shanghai 执行全量后端测试,不连接生产数据库、不执行部署。