fix: MKH-BOM 预警与库存口径修复:日销以出库为准 + 库存增加箱表兜底 #19
Loading…
x
Reference in New Issue
Block a user
No description provided.
Delete Branch "codex/mkh-sale-exclude-special-order-0919"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
业务口径:标了「已发货」但没有实际出库的 SKU,不需要出现缺货预警。
日销兜底(⑦-a)此前只看订单表的
send_date是否为空来判定「已发货」,但订单表的「已发货」不等于真实销售。本 PR 把判据下沉到出库表。口径
已发货分支计入销量需同时满足(待发货分支不变):
pay_amount <= 0.01或labels含「特殊单」o_id出库表两张都要查:
rpt.jst_salesOutboundInfo(京东/拼多多/抖音)+rpt.jst_qmcust_salesoutbound(天猫/淘宝/1688)。实测jst_qmcust_orderlist来源的 208 张单里,7 张只有京东表有记录、1 张只有天猫表有记录。🔥 两个必须豁免的情形(不豁免会大面积误杀真实单)
status='Split':父单被拆后出库记录挂在子单上,父单必然查不到。实测窗口内 40 张 Split 单 100% 无出库记录;不豁免会误杀「京东-HX旗舰店104 09-19 实付 1194.14 元」这类真实单。⚠️ 豁免只到「昨天」为止:09-18 的 18 张无出库 Sent 单 100% 是特殊单,且出库表 09-18 数据完整,豁免 09-18 会放过刷单。
豁免只免「出库校验」,金额/标签判据照样生效(拆分单里的 0.01 元单仍会被排除)。
真实数据验收(近 15 天窗口)
窗口内 1,086 张已发货 MKH 单:出库表命中 889 张 → 197 张无出库 = 40 张拆分单 + 157 张 Sent。
157 张里 131 张是 ≤0.01 元或「特殊单」(即上一版已排除的刷单),唯一 1 张正常金额的是 09-05 的 388 元单(标签「发货后取消 / 发货后售后 / 风控订单」)——判据 3 正是为它这类单兜底。
MKHDNZ0409260601175(拆分单驱动,真实单 1194.14 元)性能与降级
(整窗口拉全量
DISTINCT o_id实测要 8s,故不采用。)degraded:漏杀只是多报一条预警,错杀会让真实缺货彻底隐身。附带修复(⑦-d,commit
5e029f8):库存源时效兜底现象:
MKHDNZ0409260700491当天已入库、实物有货,但页面「现有库存」一直是 0,点「同步最新数据」也不变。根因:页面唯一的库存源
rpt.jst_inventoryInfo是「有变化才写 updateTime」的同步表。该 SKU 在它里面只有主仓14138566的一行qty=0,品牌仓连行都没有;而小时级的箱表rpt.jst_packInventoryInfo里,品牌仓bin='P-1' / qty=4 / createTime 当天 15:19—— 当日入库的���只有箱表看得见。(「同步最新数据」按钮只清服务端缓存
clearMkhBomCache,不触发上游同步,所以点多少次都是 0。)改法(只补 0,不覆盖有效值):
stockSourceinventoryInfo品牌仓qty > 0realtime(旧口径不变)bin非空合计 > 0pack(新增)inventoryInfo有品牌仓行(qty≤0)realtimejsStockmonitorinventoryInfo更大(箱表只记已装箱的货,散货不计),拿它当主源会系统性低估库存、误报缺货。bin为空的行:那是装箱记录不是库存(品牌仓合计 21 件)。影响面(实测):品牌仓 4,408 个成品里只有 3 个走箱表兜底(
MKHDNZ0409260601548=5/MKHDNZ0409260700059=4/MKHDNZ0409260700491=4,同一箱115870495000001201、货位P-1、均为当天新建行);预警列表 27 → 24 条(缺货 21 → 18),少的正是这 3 条「入库当天被误判缺货」。前端:「现有库存」列 tooltip 增加
pack来源说明;导出列直接用stock,自动跟随。性能:箱表全量取数 87ms。
⚠️ 遗留(需上游跟进):
inventoryInfo当天 06:41 之后就再没更新过(09-17 / 09-18 都是全天逐小时更新),疑似上游同步任务异常。箱表兜底只解决「当日入库看不见」,存量库存仍依赖该表恢复。验证
scripts/check-syntax.js:151 文件通过node --test test/*.test.js:340/341(唯一失败为既有的resilientSecretStoreWindows 权限断言,与本改动无关)test/mkhBomService.test.js:47/47,覆盖「无出库排除」「拆分单豁免」「今天发货豁免」「拆分单仍过金额判据」「出库源失败不砍销量」五个场景,以及 ⑦-d 的箱表兜底五分支eslint src/pages/MkhBomData/index.jsx:通过stock=4 / stockSource=pack,点「同步最新数据」后仍正确⚠️ 给后续维护者
rpt.jst_salesOutboundInfo.qty全表 1,119,606 行恒为 0(MAX(qty)=0),判断「有没有真出库」只能看行数,不能用SUM(qty)(永远得 0)。MAX(updateTime):inventoryInfo与packInventoryInfo哪个停更,一眼可辨是上游停了还是本页取数问题。背景 - 业务反馈 MKHDNZ0410260700005 从没发过货,页面却显示日销 0.6 并报缺货。 - 根因是上一版日销兜底(⑦-a)只看 send_date,把「0.01 元特殊单」当成了真实销售: · 拼多多-亿家达书房家具官方旗舰店在 2026-09-18 10:35–10:36 **一分钟内**批量生成 18 张 MKH 订单,实付合计仅 0.18 元、免额合计 16,344 元(单张:实付 0.01 元、 商品额 908.01、免额 908 全额免),备注统一为 SSDD,标签含「特殊单」「转x00005」; 同批还有 18 张商品码为占位码 1.X00005 的 0.01 元订单。 · 这批单 status=Sent、有物流单号,但 **rpt.jst_salesOutboundInfo 里查不到对应出库记录** (同店同时段其他订单有 6,467 行出库)—— 即系统标了「已发货」,货并没有真出。 · 后果:把 10 个 SKU 的日销从 0 抬到 0.6~1.8(共 162 件),凭空产出缺货预警。 改动 - loadOrderIndex 的**已发货分支**增加异常单过滤:命中任一即不计入日销 · pay_amount <= 0.01(0.01 元全免单) · labels 含「特殊单」 - 查询补充取出 o.pay_amount / o.labels(两张订单表均有这两列,已确认)。 - 金额取不到(null / 空串 / 非数字)时**不排除** —— 宁可少排也别误杀,取不到就退化成旧口径。 - ⚠️ **不使用 free_amount > 0 作为判据**:正常订单普遍带折扣免额(窗口内实测 569/1086 行 free_amount > 0),按它筛会把实付 356 / 458 / 1338 元的正常单一并误杀(第一版即踩此坑)。 - 本次只作用于「已发货」分支,待发货(⑩)口径未改动。 验证 - 语法检查:151 文件通过。 - 后端测试:338 项 337 通过。唯一失败为 resilientSecretStore 权限断言(期望 0o600、 Windows 实际 0o666),平台固有,与本改动无关。mkhBomService 单测 44/44。 - 新增回归断言:实付 0.01 / 0 元及字符串金额判为异常单;标签含「特殊单」判为异常单; **有免额的正常单不得被排除**;金额缺省/为 null/非数字时不排除。 - 订单索引用例补充:0.01 元单与「特殊单」标签行不进入 shippedBySku,而带折扣免额的 正常单照常计入(shippedBySku.size 由 1 调整为 2)。 - 真实数据端到端(业务库实时,窗口 15 天): · 应排除的 10 个异常单 SKU(MKHDNZ0410260700001/0002/0004/0005/0007/0008/0009/ 0010/0011/0012)**全部已排除**; · 应保留的 12 个真实单 SKU **全部保留**(含本问题之外的 MKHDNZ0409260601548 等); · 兜底生效 SKU 由 **22 → 12**;兜底日销最大值由 **1.8000 → 0.2000** (0.2 来自 MKHDNZ0409260700483 的 3 件真实发货,属正常)。 风险与回退 - 只影响「快照日销 ≤ 0 且近 15 天有发货」的商品;快照 > 0 的商品行为完全不变。 - 实付 ≤ 0.01 元的订单在任何业务口径下都不构成正常销售,排除不会误伤真实需求。 - 回退:本提交可整体 revert,无表结构变更、无数据迁移。 - 遗留(未在本次改动内):待发货(⑩)分支同样可能被 0.01 元单驱动, 是否一并排除需业务确认;「售后 / 补发」类订单是否计入亦有待定夺。独立审核结论:通过(附条件)
审核范围:代码逻辑 + 边界处理 + 查询正确性 + 真实数据复算 + 测试基线。未发现阻断性问题,核心结论已用业务库实时数据独立复现。
一、复现结果
pay_amount/labels测试(在 PR 分支重跑):
check-syntax151 文件通过;node --test338/337,唯一失败为resilientSecretStoreWindows 权限断言(环境固有);mkhBomService.test.js44/44。新增断言的反例保护(有免额的正常单不得被排除)质量很好。判据宽度已做反例检查:
(0.01, 1]区间 19 行全部是MKH-组合装(被isMkhProductCode先排除,命中索引 0 行),当前窗口内无漏网。二、建议补充(3 点,非代码缺陷)
1. 描述范围写小了 ⚠️
实测窗口内 ≤0.01 元的已发货 MKH 单共 137 行(104 张 0.01 元 + 33 张 0 元),且每月重复、且都是几秒内批量生成:
这是系统性流程产物(标签
AB包/大单自动匹配/刷单待处理,备注BBFF/SSDD),不是脏数据孤例。建议写进描述,供业务判断是否治上游。2. 0 元单里混着「售后补发单」,被判据一刀切 ⚠️
逐单交叉出库表后,两类成因不同:
order_type=补发订单、status=Confirmed、标签含发货后售后→ 真实售后补发流程。这两类被
pay_amount <= 0.01一起排除了。当前影响为 0(这 7 张涉 6 个 SKU,其快照日销均 > 0,兜底本就不生效;天猫表单独复算 6→6、被排除 0),但若日后快照掉到 0 会漏算 —— 与遗留项 2 同源,建议明确口径:要么「0 元单一律不算销售」,要么把 0 元分支收窄为「带特殊单/刷单待处理/AB包标签的 0 元单」。3. 顺带修复的隐性收益(建议写进描述)
判据同时排除了窗口内的负数金额单(天猫
9263814,−694.61 元)。这类退款/冲销单此前只要send_date非空就会累加件数、虚增日销,属正收益。三、一个必须写进注释的坑 🔥
实测
rpt.jst_salesOutboundInfo全表 1,119,606 行qty全部为 0(近 15 天 180,433 行同样,MAX(qty)=0)。→ 该列不能作为「出库数量」判据,只能看行数/单据存在性。 PR 用「出库行数 = 0」判断虚假单,方法正确;建议补注释,防止后人误用
SUM(qty)(恒得 0)。四、性能
同一查询取 5 列 vs 7 列:首次 1185ms / 二次 224ms,差异来自计划缓存而非列数;两列均为基表列,非计算列,无退化。
五、遗留项量化(供业务决策)
待发货(⑩)分支未改(PR 已声明),实测该分支异常单��� 8 张(京东 3 + 天猫 5,均为 0 元单),规模很小,建议保持本次不改、单独确认口径。
完整报告:
outputs/审核-PR19-日销兜底排除异常单.md建议:可合并;合并前建议把「范围补全」补进描述、把「qty 不可用」写进注释。
独立审核结论:通过(附条件)
审核范围:代码逻辑 + 边界处理 + 查询正确性 + 真实数据复算 + 测试基线。未发现阻断性问题,核心结论已用业务库实时数据独立复现。
一、复现结果
pay_amount/labels测试(在 PR 分支重跑):
check-syntax151 文件通过;node --test338/337,唯一失败为resilientSecretStoreWindows 权限断言(环境固有);mkhBomService.test.js44/44。新增断言的反例保护(有免额的正常单不得被排除)质量很好。判据宽度已做反例检查:
(0.01, 1]区间 19 行全部是MKH-组合装(被isMkhProductCode先排除,命中索引 0 行),当前窗口内无漏网。二、建议补充(3 点,非代码缺陷)
1. 描述范围写小了 ⚠️
实测窗口内 ≤0.01 元的已发货 MKH 单共 137 行(104 张 0.01 元 + 33 张 0 元),且每月重复、且都是几秒内批量生成:
这是系统性流程产物(标签
AB包/大单自动匹配/刷单待处理,备注BBFF/SSDD),不是脏数据孤例。建议写进描述,供业务判断是否治上游。2. 0 元单里混着「售后补发单」,被判据一刀切 ⚠️
逐单交叉出库表后,两类成因不同:
order_type=补发订单、status=Confirmed、标签含发货后售后→ 真实售后补发流程。这两类被
pay_amount <= 0.01一起排除了。当前影响为 0(这 7 张涉 6 个 SKU,其快照日销均 > 0,兜底本就不生效;天猫表单独复算 6→6、被排除 0),但若日后快照掉到 0 会漏算 —— 与遗留项 2 同源,建议明确口径:要么「0 元单一律不算销售」,要么把 0 元分支收窄为「带特殊单/刷单待处理/AB包标签的 0 元单」。3. 顺带修复的隐性收益(建议写进描述)
判据同时排除了窗口内的负数金额单(天猫
9263814,−694.61 元)。这类退款/冲销单此前只要send_date非空就会累加件数、虚增日销,属正收益。三、一个必须写进注释的坑 🔥
实测
rpt.jst_salesOutboundInfo全表 1,119,606 行qty全部为 0(近 15 天 180,433 行同样,MAX(qty)=0)。→ 该列不能作为「出库数量」判据,只能看行数/单据存在性。 PR 用「出库行数 = 0」判断虚假单,方法正确;建议补注释,防止后人误用
SUM(qty)(恒得 0)。四、性能
同一查询取 5 列 vs 7 列:首次 1185ms / 二次 224ms,差异来自计划缓存而非列数;两列均为基表列,非计算列,无退化。
五、遗留项量化(供业务决策)
待发货(⑩)分支未改(PR 已声明),实测该分支异常单共 8 张(京东 3 + 天猫 5,均为 0 元单),规模很小,建议保持本次不改、单独确认口径。
完整报告:
outputs/审核-PR19-日销兜底排除异常单.md建议:可合并;合并前建议把「范围补全」补进描述、把「qty 不可用」写进注释。
业务口径:标了「已发货」但没有实际出库的 SKU,不需要出现缺货预警。 即在 ⑦-a 的金额/标签判据之上,再以出库表为准判定「有没有真出货」。 已发货分支计入销量需同时满足(待发货分支不变): 1. 非样品/测试店铺(⑦-a) 2. 非异常单:pay_amount <= 0.01 或 labels 含「特殊单」(⑦-a) 3. 出库表能查到该 o_id:rpt.jst_salesOutboundInfo / rpt.jst_qmcust_salesoutbound 两个必须豁免的情形(否则会大面积误杀真实单): · 拆分单(status='Split'):出库记录挂在子单上,父单必然查不到。 实测窗口内 40 张 Split 单 100% 无出库记录;不豁免会误杀 「京东-HX旗舰店104 09-19 实付 1194.14 元」这类真实单 · 今天发货的单:当天出库尚未同步完(09-19 全天出库表仅 1 行,09-18 有 14,690 行)。 豁免只到「昨天」为止——09-18 的 18 张无出库 Sent 单 100% 是特殊单, 且出库表 09-18 数据完整,豁免 09-18 会放过刷单 豁免只免「出库校验」,金额/标签判据照样生效。 真实数据验收(近 15 天窗口,1,086 张已发货 MKH 单): · 出库表命中 889 张 → 197 张无出库 = 40 张拆分单 + 157 张 Sent · 157 张里 131 张是 ≤0.01 元或「特殊单」(即 ⑦-a 已排除的刷单), 唯一 1 张正常金额的是 09-05 的 388 元单(标签「发货后取消/发货后售后/风控订单」) · 兜底生效 SKU = 12 个(与只按金额/标签判据一致),兜底日销最大值 = 0.2 · 10 个异常单 SKU 在预警列表中零出现;总预警 27 条(缺货 21 + 仅预警 6) 性能:1086 个订单号分 2 块并行 UNION 查询,冷缓存约 0.4~1.4s; 整窗口拉全量 DISTINCT o_id 实测要 8s,故不采用。 降级策略:出库数据取不到时整体跳过出库校验(退化成只按金额/标签判据)并标 degraded。 漏杀只是多报一条预警,错杀会让真实缺货彻底隐身。 注意:jst_salesOutboundInfo.qty 全表 1,119,606 行恒为 0,只能判「有没有出库行」, 不能用 SUM(qty)(永远得 0)。 验证:check-syntax 151 文件通过;node --test 338/339(唯一失败是既有的 resilientSecretStore Windows 权限断言,与本改动无关);mkhBomService.test.js 45/45。fix: MKH-BOM 日销兜底排除 0.01 元特殊单,修复「没发过货却有日销」to fix: MKH-BOM 日销兜底:以出库为准,标了「已发货」但无实际出库的单不计销量口径升级说明(请按最新提交
0e0fcbb重新审核)业务补充口径:「这些异常 SKU,系统标记了『已发货』,但没有实际出库的,不需要出现缺货预警」——即判据要从「金额/标签」下沉到「有没有真出库」。
本次新增提交
0e0fcbb(旧提交dff2422仍在,属递进关系):o_id必须能在rpt.jst_salesOutboundInfo/rpt.jst_qmcust_salesoutbound查到status='Split'—— 出库挂子单,窗口内 40 张 Split 单 100% 无出库;不豁免会误杀 09-19 那张 1194.14 元真实单审核时建议重点看两点:
最新数据(近 15 天窗口):兜底生效 SKU 12、日销最大值 0.2、10 个异常单 SKU 在预警列表零出现、总预警 27 条。详见 PR 描述。
fix: MKH-BOM 日销兜底:以出库为准,标了「已发货」但无实际出库的单不计销量to fix: MKH-BOM 预警与库存口径修复:日销以出库为准 + 库存增加箱表兜底