Merge outbound/inbound/allocation process views into warehouse.todo.list.query, filtered by task assignee (user_id) matching legacy todo semantics (REQ-20260915-0008)
5.8 KiB
仓库待办 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执行全量后端测试,不连接生产数据库、不执行部署。