2026-09-08-export-pallet-data-identifier-design.md 5.8 KB

export_pallet_data 号码筛选调整设计

日期: 2026-09-08
范围: mcp Gateway、fmsoperate MCP 业务链路、settlement_tests 合同测试及集中项目文档

1. 背景与目标

当前 export_pallet_data 使用“入仓单号数组”或“海外仓入库时间起止”二选一。此次调整移除入仓单号,增加两类明确的物流号码筛选:

  • 柜号数组 container_codes
  • 提单号数组 bl_numbers

入库时间筛选继续保留。调用方必须明确号码类型;只给出号码但未说明是柜号还是提单号时,Gateway 的工具说明必须引导用户先确认,不能按格式猜测、并行试查或跨字段重试。

2. 输入合同

export_pallet_data 的输入为以下三种筛选方式严格三选一:

  1. container_codes
  2. bl_numbers
  3. inbound_time_start + inbound_time_end

号码数组先去除首尾空白、空值和重复值,再校验:

  • 至少 1 个,最多 200 个;
  • 每项必须是字符串;
  • 每项长度不超过 100 个字符。

时间边界继续接受 YYYY-MM-DDYYYY-MM-DD HH:MM:SS。只填日期时,开始边界展开为当天 00:00:00,结束边界展开为当天 23:59:59;起止日期部分差不超过 30 天,即最多 31 个日历日。

以下输入必须拒绝:

  • container_codesbl_numbers 同时非空;
  • 任一号码数组与时间范围混用;
  • 只提供一侧时间边界;
  • 三种筛选方式均未提供;
  • 使用 inbound_numbers、内部 ID、订单号或打托批次号。

参数错误沿用 MCP_1401 安全错误,不创建下载任务。

3. 调用链与数据范围

Gateway

  • 工具 Schema 只暴露 container_codesbl_numbersinbound_time_startinbound_time_end
  • 保持 additionalProperties=false,不保留 inbound_numbers 兼容别名。
  • CLI 增加柜号和提单号数组参数,移除入仓单号 CLI 参数。
  • 工具描述明确“柜号 / 提单号 / 入库时间三选一”,并写明号码类型不明确时必须先询问。
  • 本地与公网工具注册、路由、异步任务展示合同不变。

fmsoperate

McpPalletDataExportLogic 负责归一化、三选一校验、权限检查和任务提交;McpPalletDataExportModel 只负责取数:

  • 柜号筛选只按当前公司的海外仓关联排舱记录匹配 fms_outbound.container_code
  • 提单号筛选只按当前公司的海外仓关联排舱记录匹配 fms_booking_detail.bl_number
  • 时间筛选继续按当前公司、未删除的海外仓入库明细 inbound_time 闭区间匹配;
  • 所有路径最终都沿用“海外仓入库记录 ID → 订单 ID → 打托批次 ID”的批量解析链路;
  • 结果只允许当前 company_id 的打托批次,原有海外仓菜单和导出菜单权限不变。

柜号和提单号必须在不同的查询分支中使用索引友好的 IN 条件,不能合并成跨字段 OR。不按号码逐个查询,不增加无必要的总数查询。

队列任务中的筛选白名单、消费者参数校验和导出 Service 入参同步改为新合同;新接口不再接受或重新解释 inbound_numbers

4. 输出与异步行为

以下行为保持不变:

  • 仍只提交异步任务并立即返回签名 task_ref
  • 仍投递 fmsoperate:inside 的独立 McpPalletDataExport 消费者;
  • 仍生成后台同口径的 15 列 Excel;
  • 有成功下载的附件时按 pallet_batch 分目录生成 zip;
  • 单个 OSS 附件失败时跳过该附件,全部附件失败时仍只上传 Excel;
  • 通过 query_export_task 查询任务状态和下载链接;
  • 没有匹配的打托批次返回 MCP_1601,不创建空任务。

5. 性能与安全约束

  • 200 个号码一次性批量传入并在数据库层 IN 处理,禁止 PHP 循环逐号查库。
  • 柜号和提单号使用独立查询分支,防止跨字段 OR 造成不可控扫描。
  • 保留当前的分阶段 ID 查询和批量补齐,不回退到逐订单查询。
  • 查询和队列消费均重新绑定公司、员工和任务来源身份,不信任请求传入的身份字段。
  • 不在公共响应、工具说明或日志中暴露 SQL、内部 ID、异常栈或任务内部信息。

6. 测试计划

Gateway Python

  • Schema 只包含新字段,拒绝 inbound_numbers、内部 ID 和分页字段;
  • 柜号数组、提单号数组可正常去重并转发;
  • 柜号与提单号混用、号码与时间混用、空筛选、单侧时间、超过 200 个或单项超长均拒绝;
  • 时间最多 31 个日历日,日期边界展开保持现有行为;
  • 工具描述覆盖明确导出、号码类型询问、禁止猜测和异步查询;
  • CLI 新参数正确转发,本地/公网注册仍一致。

fmsoperate PHP

  • Validate、Logic、Model 和队列消费者全部使用新筛选字段;
  • 覆盖三选一、200 上限、每项长度、时间范围和禁止旧参数;
  • 覆盖权限失败、无可导出数据不建任务、可信公司/员工身份和异步任务引用;
  • 覆盖柜号/提单号查询只使用对应字段,不产生跨字段 OR 或逐号查询;
  • 保留公司隔离、15 列产物、独立消费者和任务终态安全合同。

文档与交付验证

  • 运行 Python 全量单测及严格覆盖率检查;
  • 运行 settlement_tests 的 fmsoperate 定向合同测试和 PHP 语法检查;
  • 运行受影响仓库的 git diff --check、Markdown 链接检查和最终状态检查;
  • 不执行注册 SQL,不重启 Gateway 或 Worker,不据代码变更推断目标环境已上线。

7. 非目标

  • 不修改后台海外仓页面、原有后台导出路由或打托文件列定义。
  • 不改变任务签名、任务去重、权限菜单、公司隔离和附件处理策略。
  • 不增加柜号/提单号模糊匹配、格式推断或自动试查。