Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
4.6 KiB
库存「装箱数被当成数量」脏数据排查报告
排查日期:2026-06-22 · 只读核查,未修改任何生产数据 明细清单:
docs/review/inventory-qty-packsize-dirty.csv(820 行)
一、起因
用户反馈「商品编号 P1297 有 12 个库存,正常只有一个」,并认为「库存都是 1,quantity 字段可以删」。排查后两个判断都需要修正。
二、P1297 真相
P1297 = product 4830(shop 8),只有 1 条库存行(inventory id 9412),不是 12 条:
| 字段 | 值 |
|---|---|
| 商品名称 | 茅台公斤大件2005原件 |
| 规格 | 1.00L*12/件(一件装 12 瓶) |
| 单位 | (空) |
| 当前数量 | 12.000 |
| 来源 | 入库明细 32353 / 入库单 7976,录入数量本身就是 12 |
即 inventory 忠实快照了入库单的 12,不是代码 bug。问题在于导入时把规格里的「装箱数 12」当成了库存数量,用户预期是「1 件」。
三、系统性结论:装箱数泄漏
这不是个例。全库 9412 条活跃库存中,820 条 quantity > 1,其中 784 条的数量恰好等于规格里的装箱数(*N/件 → 数量 N):
- qty=12 的行:82 条里 80 条规格含
*12 - qty=6 的行:641 条里绝大多数规格含
*6 - 判定规则:规格
\*(\d+)捕获的装箱数 == 当前数量 → 标记dirty_pack_eq_qty=Y
按门店分布(疑似脏 dirty=Y)
| shop_id | 脏行数 | 备注 |
|---|---|---|
| 8 | 279 | 主力门店 |
| 7 | 239 | |
| 1 | 142 | 疑似 seed/demo(商品信息多为 NULL) |
| 6 | 124 | |
| 合计 | 784 |
另有 36 行 quantity>1 但装箱数≠数量(dirty=N)
需人工复核,不能机械归 1。典型:
- shop 1 的 seed 数据:数量 108/54/36/24…,商品编码/规格全 NULL(demo,可忽略)。
ZXZ026602 茅台小白条2023原件规格500ml*5/件,数量却是 12 / 10 —— 装箱数 5,数量非整箱倍数,真实库存存疑。
四、quantity 字段能否删除
不能删(用户原设想不成立):
- 数据层面:并非「都是 1」,真有 820 行多单位(其中 784 是脏数据,但删字段前必须先治脏,且仍有真实多单位场景)。
- 代码层面:
quantity被 FIFO 扣减、出库库存校验、库存流水inventory_logs、财务对账、公开商品在库量、盘点全链路依赖,删列等于重构整个库存系统。
本轮已按决策仅在前端隐藏库存数量列(库存列表表格 + 手机卡片),DB 字段与后端逻辑保留;缺货/预警/流水不动。
五、建议(待决策,本轮不执行)
- 784 行脏数据按「件」归正为 1:把「规格装箱数 == 数量」的行,数量统一改为 1(视作 1 件);同步修对应入库明细
stock_in_items.quantity,保持单据与库存一致。执行前先备份,并对照 CSV 的suggest_qty列逐店确认。 - 36 行 dirty=N 单独人工核对:shop 1 demo 可忽略;
*5/件却数量 12/10 等异常逐条问业务。 - 根治导入器:库存/入库导入时,遇到
规格含 *N且「数量列恰好等于 N」的情况给出告警或按件折算,避免再次把装箱数写进数量。
是否执行第 1 项数据归正,请确认后另行单独处理(需备份 + 逐店复核 + 影响行数预览)。
六、全量数据质量审计(2026-06-22 补充)
对全部活跃库存(9412 行 / 7282 distinct product)逐类核查:
| 类别 | 行数 | 说明 |
|---|---|---|
| 数量 ≤ 0 | 0 | 干净 |
| product_id=0(无主数据) | 0 | 干净 |
| 孤儿(product_id 指向不存在 product) | 0 | 干净 |
| 快照商品编码为空 | 24 | 轻微,无法定位编号 |
| 快照编码 ≠ 所指 product.code(错指) | 2130 | 重大,全在 shop 7 |
| 装箱数=数量(脏数量) | 784 | 见上文,跨 shop 8/7/6/1 |
重大:shop 7 的 product_id 错指(与 shop 8 旧损坏同款)
shop 7 有 2130 条库存行错指,涉及 514 个被多编码共享的 product(每个 product 名下挂多个不同商品编号)。典型:product 234 名下有 130 条库存行、130 个不同商品编码——即 130 个真实商品编号的库存全部指向了同一个 product。这正是上次给 shop 8 修过的「按名称合并导致 product_id 搞混」根因。
各店对比:
| shop | 活跃库存行 | 错指行 | 状态 |
|---|---|---|---|
| 1 | 1213 | 0 | 干净 |
| 6 | 1134 | 0 | 干净 |
| 7 | 3286 | 2130 | ❌ 未修复 |
| 8 | 3779 | 0 | 已修复(本次之前) |
建议:对 shop 7 跑既有的 backend/cmd/fix-inventory-products 工具(按库存快照编码重建 per-code product),流程同 shop 8——先备份 → dry-run 预览 → 执行 → 复核「错指=0、distinct product 数=活跃行去重数」。需你确认后单独执行。