测试手册仓库配货 / 打包
推荐箱型 / 设箱校验
需求速读、白场与晚场完整测试步骤、供应商设箱校验、测试矩阵及可执行 SQL
Markdown 原文(给 AI 用):https://doc.xfun.fun/box-suggest-test-guide.md
给第一次接触该需求的测试人员。目标不是只在后台看到一个箱型字段,而是把“配置、生成、打包校验、晚场重算”四条链路完整走通。
依据提交 0019b5646c3a98e7c813e0cd14a4ba7561ebf89f,测试场次日期以 2026-10-27 为例,执行时替换为当天。
交付状态
- 白场测试数据 已于 2026-08-08 在测试环境验证
- 供应商设箱 需使用有货区权限的打包账号
- 晚场加单 必须使用 type=2 非自营城市仓数据
- 真实令牌 不写入文档,只在本机临时粘贴
这次到底改了什么
一件花材订单先按箱型容量生成推荐方案;仓库真正设箱时再比较实际箱与推荐箱;城市仓晚场有新单时,还要把未出库包裹按新总量重新规划。
本提交覆盖四条业务链路
- 后台打包配置新增
flowerWeight,单位 kg,0 表示不参与普通推荐。 - 普通物流按箱型容量拆包,中通仍按每 45kg 一件且不推荐普通箱。
- 供应商设箱不符时,小程序先返回
6001,确认后带forceFlag=1重调并留痕。 - 非自营城市仓晚场加单后,type=2 聚合面单按白天加晚场总量重算。
不要把测试缩成一个列表查询:后台列表有推荐值,只能证明生成落库成功。它不能证明 6001 二次确认、强制留痕、PDA 绕过、晚场幂等与部分出库扣重正确。
配置容量:普通箱维护可装花材重量;专用箱容量为 0。
生成推荐:最大箱先装整箱,余数匹配第一个能装下的最小箱。
实际设箱:实际箱与推荐箱比较,生成合规、不符或不可比较状态。
晚场重算:仅城市仓 type=2;已出库不动,其余重排并按需追加。
以当前代码为唯一验收口径。
旧文档有两处已过时:PDA 现在遇到不符不会返回 6001;白天已有蝴蝶兰且晚场再次新增蝴蝶兰时,当前实现会再追加一张蝴蝶兰箱面单。
先记住这些判定规则
下面是执行测试时最容易混淆的口径。建议先用两分钟看完,再开始造数据。
| 规则 | 输入 | 正确结果 |
|---|---|---|
| 普通箱拆分 | 80kg,最大容量 87kg | 1 张 110*60*60 |
| 整箱加余数 | 180kg | 87 + 87 + 6.1,共 3 张 |
| 特殊花材 | 普通45kg + 蝴蝶兰2kg + 蓝色妖姬1kg | 1 张普通箱 + 蝴蝶兰箱 + 蓝妖箱 |
| 中通 | 100kg | ceil(100/45)=3 张,推荐字段为空 |
| 无有效容量 | 所有普通箱 flowerWeight=0 | 回退每 60kg 一件,推荐字段为空 |
| 匹配状态 | 未设箱,或无推荐 | boxMatchStatus=0,尚不可判定合规 |
| 匹配状态 | 实际箱 = 推荐箱 | boxMatchStatus=1 |
| 匹配状态 | 实际箱 ≠ 推荐箱 | boxMatchStatus=2 |
| 晚场状态 0/10 | 未出库 | 一起按新推荐序列覆盖,实际箱不跟随修改 |
| 晚场状态 ≥20 | 已出库 | 任何字段都不改,优先按实际箱容量扣减已带走重量 |
18:05 是当前边界: 白场只取 create_time < 18:05,晚场新增判断只认 create_time > 18:05。主流程请用 17:00 和 21:00,避免恰好 18:05 的边界空档。
环境准备与完整 SQL
下文 cURL 里的场次日期 2026-10-27、API 地址、usertokenxm、wareId 都是占位,执行前替换成实际值。令牌不要写进文档或聊天记录。
执行前置
| 检查项 | 要求 | 不满足时 |
|---|---|---|
| 数据库字段 | flower_weight、suggest_pack_id、suggest_pack_info 已存在 | 停止,先补发布 DDL |
| Admin 服务 | 包含本提交,测试接口可调用 | 确认部署分支和实例版本 |
| Supplier 服务 | 包含本提交,账号有打包货区权限 | 更换账号或调整 SQL 货位 |
| 物流配置 | 供应商脚本的 @express_id 是有效物流且不等于 146 | 改成测试环境真实 id |
| 配置缓存 | 直接 SQL 改箱型后等待约 100 秒,或后台保存任一配置刷新 | 旧缓存会让结果看似错误 |
只读 DDL 自检
SELECT table_name, column_name, column_type
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND ((table_name = 'xm_bulky_pack_config' AND column_name = 'flower_weight')
OR (table_name = 'xm_bulky_wms_express_package'
AND column_name IN ('suggest_pack_id', 'suggest_pack_info')))
ORDER BY table_name, ordinal_position;
-- 预期恰好返回 3 行测试数据文件
SQL 1 测试数据-推荐箱型设箱校验-admin.sql:箱型容量 + TESTADM-A/B/C/D 白场后台数据,可重复执行
SQL 2 测试数据-推荐箱型设箱校验.sql:TESTBOX-A/B/C/D 供应商设箱、筛选、角标和 6001 数据
SQL 3 测试数据-推荐箱型设箱校验-晚场.sql:隔离城市仓的白场 + 21:00 加单,支持 NORMAL / PACKED / PARTIAL / SPECIAL / ZTO
**只在测试库执行。**Admin 脚本会把 DDL 默认残留的 flower_weight=1.00 清零,并按测试名称清理旧数据。先确认当前连接库名,再执行。
白场后台生成
这组用例证明容量拆分、特殊花材、中通和幂等。TESTADM 数据是 ware_id=0 的 type=1 数据,不能拿去测晚场城市仓重算。
步骤 1 · 执行 Admin 测试 SQL
执行 SQL 1。结果区必须看到 template_ready=OK,且 TESTADM-A 到 D 的 generation_ready 都是 OK。
验收:SQL 执行成功,模板和 4 条发货单自检均为 OK
步骤 2 · 触发白场包裹生成
调用一次测试接口。若 SQL 刚修改箱型容量,先等待缓存过期或在后台保存任一箱型。
POST generateWmsExpressPackage
curl --url 'https://api.xunmengvip.cn/xm-bulky-admin/test/generateWmsExpressPackage' \
-H 'accept: */*' \
-H 'channel: admin' \
-H 'content-type: application/json' \
-H 'usertokenxm: <粘贴当前 usertokenxm>' \
--data-raw '{"date":"2026-10-27"}'验收:接口 HTTP 200 且业务响应成功
步骤 3 · 查询全部序号
列表请求不要传 serialNum:1,否则只能看到每组第 1 张,容易误判“没有追加面单”。
POST wmsExpressPackage/list · sceneType=1
curl --url 'https://api.xunmengvip.cn/xm-bulky-admin/order/wmsExpressPackage/list' \
-H 'accept: */*' \
-H 'channel: admin' \
-H 'content-type: application/json' \
-H 'usertokenxm: <粘贴当前 usertokenxm>' \
--data-raw '{"roundNo":"2026-10-27","sceneType":1,"zoneList":[],"index":1,"size":100}'验收:已核对 TESTADM-A/B/C/D 的全部 serialNum
步骤 4 · 对照精确预期
A:1 张 110*60*60。B:110*60*60、110*60*60、小件90*20。C:普通 110*45*45,加蝴蝶兰箱与蓝妖箱各 1 张。D:中通 3 张,推荐 id 全为 0。
验收:数量、推荐名称、容量与 packageNum 全部符合
步骤 5 · 重跑验证幂等
先记录 TESTADM 包裹总行数和 id,再调用同一个白场接口一次。行数与 id 必须不变。
验收:第二次生成没有重复插入
白场数据库断言
SELECT p.send_no, p.serial_num, p.package_num,
p.suggest_pack_id, p.suggest_pack_info,
c.flower_weight AS suggest_capacity,
p.total_weight, p.express_status
FROM xm_bulky_wms_express_package p
LEFT JOIN xm_bulky_pack_config c ON c.id = p.suggest_pack_id
WHERE p.send_no LIKE 'TESTADM%'
AND p.data_status = 0
ORDER BY p.send_no, p.serial_num;
-- 幂等前后记录两次结果,COUNT 与 id 集合都应一致
SELECT COUNT(*) AS row_count,
GROUP_CONCAT(id ORDER BY id) AS id_list
FROM xm_bulky_wms_express_package
WHERE send_no LIKE 'TESTADM%' AND data_status = 0;供应商设箱校验
每次测试会修改包裹状态。建议一个动作验证完就重跑 SQL 2 复位,避免前一个用例影响下一个用例。
执行 SQL 前先改 @shelf_a 到 @shelf_d,确保货位在测试打包员权限范围内;把 @express_id 改成有效物流 id,且不要用 146。成功打包后,同一 userId 测下一包需间隔 10 秒。
步骤 1 · 执行 Supplier 测试 SQL
记录脚本最后输出的包裹 id,扫码内容就是该 id。T-991 待打包;T-992 合规;T-993 含不符;T-994 无推荐。
验收:已保存 T-991 到 T-994 的包裹 id 和箱型 id
步骤 2 · 验证货架列表与筛选
status=0 时验证 T-991。status=1 时应有 T-992/T-993/T-994;T-993 的 boxMismatchFlag=1。筛选 2 仅 T-993;筛选 1 返回 T-992 和 T-994。
验收:全部、合规、不符三个筛选结果正确
步骤 3 · 验证详情状态
T-991 三行均为 0,但前两行仍有推荐字段;T-992 两行均为 1;T-993 序号1为2、序号2为1;T-994为0。
验收:suggestPackId、suggestPackInfo、boxMatchStatus 均符合
步骤 4 · 推荐箱直接成功
重置 SQL 后,对 T-991 序号1传推荐箱,forceFlag=0。预期成功,状态10,匹配状态1,不产生强制不符留痕。
验收:推荐箱设箱成功且无不符留痕
步骤 5 · 不符时 6001,再确认强制使用
重置 SQL 后,对 T-991 序号2选另一个箱。首次 forceFlag=0 必须返回6001且不改状态;立刻用完全相同参数重调,只改 forceFlag=1,应成功并记录一次修改留痕。
验收:6001、取消不请求、强制重调和留痕全部正确
步骤 6 · 无推荐与 PDA 例外
T-991 序号3可用任意合法箱直接成功。PDA /pack/finish/scan 用非推荐箱也应直接成功,不返回6001,但要写“扫码枪打包”不符留痕。PDA 账号必须有物流专员角色。
验收:无推荐不拦截;PDA 不拦截但正确留痕
供应商接口请求体模板
// 货架列表。status=0 查待打包;status=1 查已打包
POST /package/shelf/page
{
"date": "2026-10-27",
"userId": <测试账号ID>,
"userName": "<测试账号名称>",
"status": 1,
"boxMatchFilter": 2,
"current": 1,
"size": 20
}
// 首次设箱。codeContent 填 SQL 输出的包裹 id
POST /package/pack/finish
{
"codeContent": "<包裹ID>",
"userId": <测试账号ID>,
"userName": "<测试账号名称>",
"phone": "13800000000",
"packId": <实际箱ID>,
"packName": "<实际箱名称>",
"url": "",
"shelfPackage": 0,
"forceFlag": 0
}
// 收到 code=6001 后,只把 forceFlag 改成 1,其余参数原样重调强制使用留痕断言
SELECT package_id, origin_pack_id, origin_pack_name,
target_pack_id, target_pack_name,
operate_user_id, operate_user_name, remark, create_time
FROM xm_bulky_package_box_modify_record
WHERE send_no LIKE 'TESTBOX%'
AND data_status = 0
ORDER BY id DESC;
-- 小程序强制使用预期 remark:
-- 实际箱型与推荐箱型不一致,已确认强制使用
-- PDA 不符预期 remark:
-- 扫码枪打包,实际箱型与推荐箱型不一致晚场加单应该这样测
晚场重算只发生在 type=2 非自营城市仓聚合组。TESTADM-A 到 D 都是 type=1,继续用它们触发晚场接口只会得到“没有重算”的正确结果。
查询用 sceneType=2,不要用 sceneType=4。
type=2 聚合包裹的 send_no 为空;sceneType=4 按晚场发货单号查,通常看不到这组包裹。也不要传 serialNum=1,否则看不到追加行。
主流程:NORMAL
步骤 1 · 准备同仓白场与晚场发货单
打开 SQL 3,确认 @case_name='NORMAL' 后执行准备区。脚本会选择当天无真实订单占用的非自营城市仓,插入 17:00 的 45kg 白场单和 21:00 的 50kg 晚场单,并输出 wareId。
验收:late_fixture_ready=OK,已记下输出的 wareId
步骤 2 · 先调用白场生成
虽然数据库已有晚场单,白场入口只会读取 18:05 前的白场单。此时应只有 1 张 110*45*45,总重45kg。
验收:白场基线为 1 张 110*45*45
步骤 3 · 触发晚场重算
调用晚场测试接口。预期总重95kg:原 serial1 改成 110*60*60,追加 serial2 小件100*25,两张未出库行的 packageNum=2。
POST generateWmsExpressPackageNight
curl --url 'https://api.xunmengvip.cn/xm-bulky-admin/test/generateWmsExpressPackageNight' \
-H 'accept: */*' \
-H 'channel: admin' \
-H 'content-type: application/json' \
-H 'usertokenxm: <粘贴当前 usertokenxm>' \
--data-raw '{"date":"2026-10-27"}'验收:推荐被覆盖、追加 1 张、总重量和件数刷新
步骤 4 · 查询全部 type=2 包裹
填写 SQL 输出的 wareId 后复制请求。接口用于页面核对,精确字段仍建议同时跑下方数据库断言。
POST wmsExpressPackage/list · sceneType=2
curl --url 'https://api.xunmengvip.cn/xm-bulky-admin/order/wmsExpressPackage/list' \
-H 'accept: */*' \
-H 'channel: admin' \
-H 'content-type: application/json' \
-H 'usertokenxm: <粘贴当前 usertokenxm>' \
--data-raw '{"roundNo":"2026-10-27","sceneType":2,"zoneList":[],"index":1,"size":100}'验收:sceneType=2 能看到 serial1 与 serial2
步骤 5 · 同一晚场接口再调一次
记录行数和 id,再跑一次。第二次不得继续追加,id、serialNum 与推荐都保持不变。
验收:晚场第二次执行完全幂等
晚场数据库断言,wareId 取 SQL 输出
SELECT id, round_no, ware_id, partner_id, serial_num, package_num,
total_weight, item_num, express_status,
package_id, package_info, suggest_pack_id, suggest_pack_info,
data_status, create_time, update_time
FROM xm_bulky_wms_express_package
WHERE round_no = CURDATE()
AND type = 2
AND ware_id = <SQL输出的wareId>
AND partner_id = 0
ORDER BY serial_num, id;
-- 幂等前后比较
SELECT COUNT(*) AS row_count,
GROUP_CONCAT(id ORDER BY id) AS id_list,
GROUP_CONCAT(serial_num ORDER BY serial_num) AS serial_list
FROM xm_bulky_wms_express_package
WHERE round_no = CURDATE()
AND type = 2
AND ware_id = <SQL输出的wareId>
AND partner_id = 0
AND data_status = 0;晚场扩展场景
PACKED · 已设箱也重排:白场45kg先把 serial1 设为实际 110*45*45、状态10。晚场后推荐改成110*60*60,实际箱不变,因此匹配状态变2。
PARTIAL · 部分出库扣容量:白场80kg的87kg箱设为状态20;晚场再加100kg。剩93kg,追加87kg箱和6.1kg箱;已出库旧行任何字段不变。
SPECIAL / ZTO · 专用箱与中通:同品种跨白晚场要追加专用箱。中通总95kg目标3件,从白场1件追加2件,全部无普通箱推荐。
如何切换晚场扩展场景
重跑 SQL 3 前,把第一段 @case_name 改成 PACKED、PARTIAL、SPECIAL 或 ZTO。执行准备区,调用白场接口;PACKED/PARTIAL 再执行 SQL 文件里的“白场后置”区;最后调用晚场接口并按文件尾部预期核对。每个场景都要再跑一次晚场接口验证幂等。
完整测试矩阵
P0 是本次发布必测;P1 是边界、风险和兼容性。
| 级别 | ID | 场景 | 关键预期 |
|---|---|---|---|
| P0 | CFG-01 | flowerWeight 列表、保存与校验 | 0、87.00 可保存;null、负数、1000.01、3位小数失败 |
| P0 | DAY-01 | 80kg / 180kg 普通箱拆分 | A 为 1 张最大箱;B 为 87+87+6.1 |
| P0 | DAY-02 | 特殊花材独立装箱 | 普通重量先扣特殊重量;专用箱仍有推荐 id |
| P0 | DAY-03 | 中通100kg | 3件,推荐 id=0,推荐容量=null |
| P0 | DAY-04 | 白场重复执行 | 行数和 id 不变 |
| P0 | PACK-01 | 货架筛选与角标 | 不符筛选仅 T-993;合规筛选含无推荐 T-994 |
| P0 | PACK-02 | 推荐箱直接设箱 | 成功,状态1,无强制留痕 |
| P0 | PACK-03 | 非推荐箱 + forceFlag | 首次6001不落库;force=1成功且仅一条留痕 |
| P0 | PACK-04 | 点击“否” | 只关闭弹窗,不发第二次请求 |
| P0 | PACK-05 | PDA 非推荐箱 | 不返回6001,直接成功,写扫码枪不符留痕 |
| P0 | NIGHT-01 | 45kg + 50kg 主流程 | 49.6箱改87箱,追加13kg箱,总2件 |
| P0 | NIGHT-02 | 状态10重排 | 推荐更新,实际箱不变,变为设箱不符 |
| P0 | NIGHT-03 | 部分已出库 | 按实际箱容量优先扣重,状态20整行不改 |
| P0 | NIGHT-04 | 晚场幂等 | 第二次无更新或追加,id 不变 |
| P0 | NIGHT-05 | 特殊花材跨阶段 | 白场蝴蝶兰 + 晚场蝴蝶兰,共2张蝴蝶兰箱 |
| P0 | NIGHT-06 | 中通晚场 | 总95kg目标3件,追加2件,均无推荐 |
| P1 | EDGE-01 | 0.5 / 6 / 174kg | 最小有效箱、6.1箱、两个87箱且无余箱 |
| P1 | EDGE-02 | 中通冷链硬限制 | expressId=146 + packId 12/17,force=1也不能绕过 |
| P1 | EDGE-03 | 重算后需求变少 | 多余面单保留,不删除、不作废、不清旧推荐 |
| P1 | EDGE-04 | 作废行与序号 | 作废行不参与件数,但新序号从历史最大值继续 |
| P1 | RISK-01 | FHH 更小晚场货位 | 观察是否因 key 改变而重复整组生成,属于已知风险 |
| P1 | RISK-02 | 物流电子面单数量 | 仅隔离配置下测试,避免真实第三方面单副作用 |
怎样算测试完成
每条失败必须能回答:输入是什么、接口返回什么、数据库最终是什么、第二次执行是否变化。
保留请求:接口、请求体、场次、wareId、包裹id。令牌打码,禁止贴完整 JWT。
保留响应:HTTP 状态、业务 code、msg、records 中的推荐与匹配字段。
保留前后快照:id、serialNum、status、实际箱、推荐箱、总重、件数及留痕记录。
测试结果回报模板
提交:0019b5646c3a98e7c813e0cd14a4ba7561ebf89f
环境:test1 / API 实例:________
场次:________ 测试账号:________
白场后台:通过 / 不通过 / 未测
供应商设箱:通过 / 不通过 / 未测
晚场 NORMAL:通过 / 不通过 / 未测
晚场 PACKED:通过 / 不通过 / 未测
晚场 PARTIAL:通过 / 不通过 / 未测
晚场 SPECIAL/ZTO:通过 / 不通过 / 未测
失败用例 ID:________
请求与响应:________
数据库前后快照:________
重跑结果:________
日志关键字:________
结论与阻塞:________看不到数据时先查这里
大多数“接口没值”不是算法问题,而是日期、场景、序号、分组或缓存没有对齐。
Admin 列表没有今天的发货单
- 确认请求
roundNo与 SQL 的CURDATE()是同一天,数据库与应用时区均为 Asia/Shanghai。 - SQL 末尾的
template_ready、generation_ready必须为 OK。 - 执行 SQL 只造发货单,不会自动造包裹;必须再调用白场生成接口。
- 查所有包裹时删除
serialNum:1;它会隐藏追加序号。
晚场接口成功,但列表还是没有值
- 主流程必须是
ware_id>0、single_delivery_flag=0、type=2;TESTADM-A 到 D 不满足。 - 使用
sceneType=2并传 wareId,不要用 sceneType=4。 - 白场发货单时间应为17:00,晚场新增应为21:00;恰好18:05不会触发。
- 白场与晚场必须同 wareId、partnerId 和物流分组。
数量对,但推荐箱不对
- 确认箱型配置缓存已刷新,数据库改值后最多等待约100秒。
- 确认普通箱的 flowerWeight 大于0,专用箱名称没有误当普通箱。
- 特殊花材重量会先从普通拆箱重量中扣除。
- 同容量箱按 sort,再按 id 取更靠前的配置。
供应商打包没有返回 6001
- 确认该包裹
suggest_pack_id>0,且请求 packId 与推荐 id 不同。 - 确认走的是
/package/pack/finish或/finish/change,PDA scan 入口本来就不返回6001。 - 确认没有误传
forceFlag=1。 - 中通冷链箱型硬限制是普通失败,不属于6001。
自动化测试为什么没有全绿
Admin 的推荐拆箱 7 条、晚场规划器 10 条目标单测已通过。Supplier 的 PackageLogicFinishTest 当前有 1 失败、1 错误,原因是测试仍断言 PDA 受区域权限限制,并保留了已不再调用的权限 stub;生产代码当前口径是 PDA 必须有物流专员角色,但跳过货区限制。不要把这两个旧断言误判为本需求手工链路失败,手工验收仍需按本页 P0 完整执行。