库存一致性排查手册

本文用于处理“列表有库存但下单失败”“库存流水和实时库存不一致”“报表库存和业务库存不一致”等问题。库存问题不要只看一个表,必须同时看商品、仓库、货位、流水、实时库存、缓存和报表口径。

适用场景

  • 采购/秒杀/销售页面显示有库存,但加购或出库提示库存不足。
  • 采购入库、销售出库、退货入库后实时库存没变化。
  • 库存流水有记录,但 t_scm_inventory_real_time 数量不对。
  • 业务库存和报表库存不一致。
  • 指定仓、供给仓、服务站仓口径混淆。

入口文件

  • 库存服务:application/Services/Storage/InventorySer.php
  • 库存查询:application/Services/Storage/InventoryQuerySer.php
  • 仓库服务:application/Services/Storage/StorageSer.php
  • 套包库存:application/Services/Storage/PackageSer.php
  • 采购入库:application/controllers/scm/InvPu.php
  • 销售出库:application/controllers/scm/InvSa.php
  • 盘点:application/controllers/inner/gpda/TakeStock.php
  • 库存任务:application/controllers/tasks/GoodsCache.phpGoodsEsCache.phpUpdateEsGoodsInfo.php

核心表

  • 商品:t_bs_goodst_bs_goods_extt_bs_goods_sto
  • 仓库:t_bs_storaget_bs_storage_location
  • 货位:t_bs_storage_areat_bs_storage_area_rel
  • 库存流水:t_scm_inventoryt_scm_inventory_info
  • 往月流水:th_scm_inventory
  • 实时库存:t_scm_inventory_real_time
  • 盘点:t_scm_inventory_checkt_scm_inventory_check_info
  • 库存预警:t_scm_inventory_warning

状态和枚举

  • TransTypeEnums.php 是库存方向的核心字典。
  • 增加库存:采购入库 150501、销售退货入库 150502、其他入库 150706、盘盈 150701、套包入库。
  • 减少库存:销售出库 150601、采购退货 170402、其他出库 150806、盘亏 150801、套包出库。
  • 盘点:180510

主流程排查

  1. 确认商品口径。
  • 明确页面或接口用的是 skuIdinvId 还是商品编码。
  • 查商品是否启用、是否套包、是否有销售/采购限制、是否存在编码合并。
  1. 确认仓库口径。
  • 普通服务站仓、指定仓、供给仓、微仓、周转仓不要混用。
  • 秒杀活动还要看库存范围:服务站对应仓、指定仓、全局预留。
  1. 查实时库存。
  • sid + invId/skuId + storageId + areaIdt_scm_inventory_real_time
  • 如果页面聚合展示,确认是否包含多个货位、多个仓库。
  1. 查库存流水。
  • 按业务单号查 t_scm_inventory
  • 按库存主表 id 查 t_scm_inventory_info
  • 对同一个商品汇总流水方向,和实时库存变化对比。
  1. 查业务单据。
  • 采购入库看 t_scm_pu_invoice_info
  • 销售出库看 t_scm_sa_invoice_info
  • 采购退货/销售退货看对应退货单和关闭记录。
  • 秒杀看活动商品锁定量、已用量和采购单。
  1. 查缓存和索引。
  • 商品搜索可能走 ES 或物料缓存。
  • 服务站物料缓存可能未刷新,导致列表展示旧库存或旧状态。
  • Redis/Mongo/ES 只作为展示或查询加速,最终库存以业务库流水和实时库存为准。
  1. 查报表口径。
  • 报表可能走业务库汇总、历史归档或 Hologres/DWD。
  • 当天实时业务和离线报表存在延迟是常见现象。

常见问题判断

| 现象 | 优先检查 | | --- | --- | | 列表有库存,加购失败 | 列表仓库口径、服务站黑白名单、活动库存范围、实时库存货位 | | 出库失败提示不足 | 销售明细未出库数量、实时库存、货位选择、冻结/锁定逻辑 | | 入库成功但库存没加 | 入库单是否生成库存流水、InventorySer::save/changeInventoryQty 是否执行 | | 流水有但实时库存不对 | 是否重复写流水、实时库存更新失败、分表/月份归档查询错 | | 报表库存和业务不一致 | 报表同步延迟、查询条件、历史表和当月表合并口径 |

常用 SQL 模板

-- 实时库存
select * from t_scm_inventory_real_time
where sid = :sid and invId = :inv_id;

-- 按业务单号查库存流水
select * from t_scm_inventory
where sid = :sid and srcBillNo = :bill_no;

-- 查流水明细
select * from t_scm_inventory_info
where sid = :sid and inventoryId = :inventory_id;

-- 查仓库和货位
select * from t_bs_storage where sid = :sid;
select * from t_bs_storage_area where sid = :sid and storageId = :storage_id;

常用 rg 命令

rg -n "function save|changeInventoryQty|SCM_INVENTORY_REAL_TIME" application/Services/Storage application/service
rg -n "TRANSTYPE_PU_PURCHASE|TRANSTYPE_SA_INVOICE_SALE|TRANSTYPE_OI_LOSS" application/KzData/Enums/TransTypeEnums.php
rg -n "MaterielCache|GoodsEsCache|UpdateEsGoodsInfo|redis|Mongo|EsSer" application/Services application/controllers/tasks
rg -n "stock_qty|supply_stock_qty|locked_qty|used_qty" application/Services application/controllers

改动风险和回归清单

  • 任意库存写入改动,都要回归采购入库、销售出库、销售退货、采购退货、盘点、调拨。
  • 任意库存查询改动,都要回归普通商品、套包、指定仓、服务站仓、活动商品。
  • 任意缓存改动,都要回归商品列表、活动列表、加购、确认页、库存报表。
  • 修数据时先备份原始记录,优先补业务流水,不要只改实时库存结果表。