QA field manual · 2026-08-08

推荐箱型与设箱校验
测试作业手册

给第一次接触该需求的测试人员。目标不是只在后台看到一个箱型字段,而是把“配置、生成、打包校验、晚场重算”四条链路完整走通。

commit 0019b5646c3a98e7c813e0cd14a4ba7561ebf89f
必测进度 0 / 0

01 / REQUIREMENT

这次到底改了什么

一件花材订单先按箱型容量生成推荐方案;仓库真正设箱时再比较实际箱与推荐箱;城市仓晚场有新单时,还要把未出库包裹按新总量重新规划。

本提交覆盖四条业务链路
  • 后台打包配置新增 flowerWeight,单位 kg,0 表示不参与普通推荐。
  • 普通物流按箱型容量拆包,中通仍按每 45kg 一件且不推荐普通箱。
  • 供应商设箱不符时,小程序先返回 6001,确认后带 forceFlag=1 重调并留痕。
  • 非自营城市仓晚场加单后,type=2 聚合面单按白天加晚场总量重算。
不要把测试缩成一个列表查询 后台列表有推荐值,只能证明生成落库成功。它不能证明 6001 二次确认、强制留痕、PDA 绕过、晚场幂等与部分出库扣重正确。
01配置容量

普通箱维护可装花材重量;专用箱容量为 0。

02生成推荐

最大箱先装整箱,余数匹配第一个能装下的最小箱。

03实际设箱

实际箱与推荐箱比较,生成合规、不符或不可比较状态。

04晚场重算

仅城市仓 type=2;已出库不动,其余重排并按需追加。

!

以当前代码为唯一验收口径。

旧文档有两处已过时:PDA 现在遇到不符不会返回 6001;白天已有蝴蝶兰且晚场再次新增蝴蝶兰时,当前实现会再追加一张蝴蝶兰箱面单。

02 / RULES

先记住这些判定规则

下面是执行测试时最容易混淆的口径。建议先用两分钟看完,再开始造数据。

规则输入正确结果
普通箱拆分80kg,最大容量 87kg1 张 110*60*60
整箱加余数180kg87 + 87 + 6.1,共 3 张
特殊花材普通45kg + 蝴蝶兰2kg + 蓝色妖姬1kg1 张普通箱 + 蝴蝶兰箱 + 蓝妖箱
中通100kgceil(100/45)=3 张,推荐字段为空
无有效容量所有普通箱 flowerWeight=0回退每 60kg 一件,推荐字段为空
匹配状态未设箱,或无推荐boxMatchStatus=0,尚不可判定合规
匹配状态实际箱 = 推荐箱boxMatchStatus=1
匹配状态实际箱 ≠ 推荐箱boxMatchStatus=2
晚场状态 0/10未出库一起按新推荐序列覆盖,实际箱不跟随修改
晚场状态 ≥20已出库任何字段都不改,优先按实际箱容量扣减已带走重量
i

18:05 是当前边界:白场只取 create_time < 18:05,晚场新增判断只认 create_time > 18:05。主流程请用 17:00 和 21:00,避免恰好 18:05 的边界空档。

03 / PREPARE

环境准备与完整 SQL

先填测试日期和接口地址,下面的 cURL 会自动更新。令牌只保存在当前输入框中,刷新页面即清空。

页面不会写 localStorage,也不会发送网络请求。复制完成后可立即清空。

执行前置

检查项要求不满足时
数据库字段flower_weightsuggest_pack_idsuggest_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
测试数据-推荐箱型设箱校验.sqlTESTBOX-A/B/C/D 供应商设箱、筛选、角标和 6001 数据
SQL 3
测试数据-推荐箱型设箱校验-晚场.sql隔离城市仓的白场 + 21:00 加单,支持 NORMAL / PACKED / PARTIAL / SPECIAL / ZTO
!

只在测试库执行。Admin 脚本会把 DDL 默认残留的 flower_weight=1.00 清零,并按测试名称清理旧数据。先确认当前连接库名,再执行。

04 / DAY RUN

白场后台生成

这组用例证明容量拆分、特殊花材、中通和幂等。TESTADM 数据是 ware_id=0 的 type=1 数据,不能拿去测晚场城市仓重算。

01

执行 Admin 测试 SQL

执行 SQL 1。结果区必须看到 template_ready=OK,且 TESTADM-A 到 D 的 generation_ready 都是 OK。

02

触发白场包裹生成

调用一次测试接口。若 SQL 刚修改箱型容量,先等待缓存过期或在后台保存任一箱型。

POST generateWmsExpressPackage
03

查询全部序号

列表请求不要传 serialNum:1,否则只能看到每组第 1 张,容易误判“没有追加面单”。

POST wmsExpressPackage/list · sceneType=1
04

对照精确预期

A:1 张 110*60*60。B:110*60*60、110*60*60、小件90*20。C:普通 110*45*45,加蝴蝶兰箱与蓝妖箱各 1 张。D:中通 3 张,推荐 id 全为 0。

05

重跑验证幂等

先记录 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;

05 / PACKING

供应商设箱校验

每次测试会修改包裹状态。建议一个动作验证完就重跑 SQL 2 复位,避免前一个用例影响下一个用例。

!

执行 SQL 前先改 @shelf_a@shelf_d,确保货位在测试打包员权限范围内;把 @express_id 改成有效物流 id,且不要用 146。成功打包后,同一 userId 测下一包需间隔 10 秒。

01

执行 Supplier 测试 SQL

记录脚本最后输出的包裹 id,扫码内容就是该 id。T-991 待打包;T-992 合规;T-993 含不符;T-994 无推荐。

02

验证货架列表与筛选

status=0 时验证 T-991。status=1 时应有 T-992/T-993/T-994;T-993 的 boxMismatchFlag=1。筛选 2 仅 T-993;筛选 1 返回 T-992 和 T-994。

03

验证详情状态

T-991 三行均为 0,但前两行仍有推荐字段;T-992 两行均为 1;T-993 序号1为2、序号2为1;T-994为0。

04

推荐箱直接成功

重置 SQL 后,对 T-991 序号1传推荐箱,forceFlag=0。预期成功,状态10,匹配状态1,不产生强制不符留痕。

05

不符时 6001,再确认强制使用

重置 SQL 后,对 T-991 序号2选另一个箱。首次 forceFlag=0 必须返回6001且不改状态;立刻用完全相同参数重调,只改 forceFlag=1,应成功并记录一次修改留痕。

06

无推荐与 PDA 例外

T-991 序号3可用任意合法箱直接成功。PDA /pack/finish/scan 用非推荐箱也应直接成功,不返回6001,但要写“扫码枪打包”不符留痕。PDA 账号必须有物流专员角色。

供应商接口请求体模板
// 货架列表。status=0 查待打包;status=1 查已打包
POST /package/shelf/page
{
  "date": "<测试日期>",
  "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:
-- 扫码枪打包,实际箱型与推荐箱型不一致

06 / NIGHT REPLAN

晚场加单应该这样测

晚场重算只发生在 type=2 非自营城市仓聚合组。TESTADM-A 到 D 都是 type=1,继续用它们触发晚场接口只会得到“没有重算”的正确结果。

!

查询用 sceneType=2,不要用 sceneType=4。

type=2 聚合包裹的 send_no 为空;sceneType=4 按晚场发货单号查,通常看不到这组包裹。也不要传 serialNum=1,否则看不到追加行。

主流程:NORMAL

01

准备同仓白场与晚场发货单

打开 SQL 3,确认 @case_name='NORMAL' 后执行准备区。脚本会选择当天无真实订单占用的非自营城市仓,插入 17:00 的 45kg 白场单和 21:00 的 50kg 晚场单,并输出 wareId。

02

先调用白场生成

虽然数据库已有晚场单,白场入口只会读取 18:05 前的白场单。此时应只有 1 张 110*45*45,总重45kg。

03

触发晚场重算

调用晚场测试接口。预期总重95kg:原 serial1 改成 110*60*60,追加 serial2 小件100*25,两张未出库行的 packageNum=2

POST generateWmsExpressPackageNight
04

查询全部 type=2 包裹

填写 SQL 输出的 wareId 后复制请求。接口用于页面核对,精确字段仍建议同时跑下方数据库断言。

POST wmsExpressPackage/list · sceneType=2
05

同一晚场接口再调一次

记录行数和 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 改成 PACKEDPARTIALSPECIALZTO。执行准备区,调用白场接口;PACKED/PARTIAL 再执行 SQL 文件里的“白场后置”区;最后调用晚场接口并按文件尾部预期核对。每个场景都要再跑一次晚场接口验证幂等。

07 / COVERAGE

完整测试矩阵

P0 是本次发布必测;P1 是边界、风险和兼容性。可用按钮缩小范围。

级别ID场景关键预期
P0CFG-01flowerWeight 列表、保存与校验0、87.00 可保存;null、负数、1000.01、3位小数失败
P0DAY-0180kg / 180kg 普通箱拆分A 为 1 张最大箱;B 为 87+87+6.1
P0DAY-02特殊花材独立装箱普通重量先扣特殊重量;专用箱仍有推荐 id
P0DAY-03中通100kg3件,推荐 id=0,推荐容量=null
P0DAY-04白场重复执行行数和 id 不变
P0PACK-01货架筛选与角标不符筛选仅 T-993;合规筛选含无推荐 T-994
P0PACK-02推荐箱直接设箱成功,状态1,无强制留痕
P0PACK-03非推荐箱 + forceFlag首次6001不落库;force=1成功且仅一条留痕
P0PACK-04点击“否”只关闭弹窗,不发第二次请求
P0PACK-05PDA 非推荐箱不返回6001,直接成功,写扫码枪不符留痕
P0NIGHT-0145kg + 50kg 主流程49.6箱改87箱,追加13kg箱,总2件
P0NIGHT-02状态10重排推荐更新,实际箱不变,变为设箱不符
P0NIGHT-03部分已出库按实际箱容量优先扣重,状态20整行不改
P0NIGHT-04晚场幂等第二次无更新或追加,id 不变
P0NIGHT-05特殊花材跨阶段白场蝴蝶兰 + 晚场蝴蝶兰,共2张蝴蝶兰箱
P0NIGHT-06中通晚场总95kg目标3件,追加2件,均无推荐
P1EDGE-010.5 / 6 / 174kg最小有效箱、6.1箱、两个87箱且无余箱
P1EDGE-02中通冷链硬限制expressId=146 + packId 12/17,force=1也不能绕过
P1EDGE-03重算后需求变少多余面单保留,不删除、不作废、不清旧推荐
P1EDGE-04作废行与序号作废行不参与件数,但新序号从历史最大值继续
P1RISK-01FHH 更小晚场货位观察是否因 key 改变而重复整组生成,属于已知风险
P1RISK-02物流电子面单数量仅隔离配置下测试,避免真实第三方面单副作用

08 / EVIDENCE

怎样算测试完成

每条失败必须能回答:输入是什么、接口返回什么、数据库最终是什么、第二次执行是否变化。

REQUEST保留请求

接口、请求体、场次、wareId、包裹id。令牌打码,禁止贴完整 JWT。

RESPONSE保留响应

HTTP 状态、业务 code、msg、records 中的推荐与匹配字段。

DATABASE保留前后快照

id、serialNum、status、实际箱、推荐箱、总重、件数及留痕记录。

测试结果回报模板
提交:0019b5646c3a98e7c813e0cd14a4ba7561ebf89f
环境:test1 / API 实例:________
场次:________    测试账号:________

白场后台:通过 / 不通过 / 未测
供应商设箱:通过 / 不通过 / 未测
晚场 NORMAL:通过 / 不通过 / 未测
晚场 PACKED:通过 / 不通过 / 未测
晚场 PARTIAL:通过 / 不通过 / 未测
晚场 SPECIAL/ZTO:通过 / 不通过 / 未测

失败用例 ID:________
请求与响应:________
数据库前后快照:________
重跑结果:________
日志关键字:________
结论与阻塞:________

09 / TROUBLESHOOT

看不到数据时先查这里

大多数“接口没值”不是算法问题,而是日期、场景、序号、分组或缓存没有对齐。

Admin 列表没有今天的发货单
  • 确认请求 roundNo 与 SQL 的 CURDATE() 是同一天,数据库与应用时区均为 Asia/Shanghai。
  • SQL 末尾的 template_readygeneration_ready 必须为 OK。
  • 执行 SQL 只造发货单,不会自动造包裹;必须再调用白场生成接口。
  • 查所有包裹时删除 serialNum:1;它会隐藏追加序号。
晚场接口成功,但列表还是没有值
  • 主流程必须是 ware_id>0single_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 完整执行。