本手册从一个采购单号出发,逐层回答:单据是否创建、状态为什么停住、明细数量去了哪里、支付/订单中心/配送消息是否生效、入库是否重复、库存是否一致、关闭和退货是否完成、特殊来源是否释放。
适用于普通采购、在线支付采购、急件、自提、云仓直发、预订单、赠品、秒杀、首配、自制订单和各类采购退货。本文强调“先证明事实,再决定补偿”,不提供未经核对即可执行的生产修改语句。
1. 业务目标
- 拿到
billNo、采购 ID、支付单号、外部订单号任一标识后,能找回整条采购链。 - 明确主单、采购明细、数量账、出库、入库、关闭、支付、库存和来源业务之间的关联键。
- 用状态和数量守恒判断问题发生在创建、审核、支付、出库、入库、关闭还是退货。
- 把“消息没来”“消息来了但被 ACK”“事务部分成功”“查询分表错了”区分开。
- 修复前保留证据,修复后同时核对业务单、库存、资金和下游系统。
2. 适用现象
3. 排查前必须收集的信息
3.1 最小事实卡
环境:
服务站 sid:
采购单号 billNo:
采购单 ID:
订单类型 orderType:
来源类型 srcOrderType:
来源单号 srcOrderNo / srcOrderId:
支付类型 paymentType:
当前状态 billStatus:
异常 SKU / invId:
外部订单号/支付单号/配送单号:
首次发现时间:
最近一次操作和操作者:
预期结果:
实际结果:
3.2 不要一开始就做的事
- 不要先改
billStatus。 - 不要先把入库单软删。
- 不要先重放整批 MQ。
- 不要只根据页面文案判断真实状态。
- 不要忽略
sid 直接查默认分表。 - 不要把
sign_qty 与 in_qty 相加当成当前已入库量。 - 不要把支付中心“支付成功”直接等价为采购全部履约成功。
4. 采购主键和分表定位
4.1 表定位规则
例如 sid=100035:
采购/入库分表后缀 = 100035 % 32 = 3
库存分表后缀 = 100035 % 128 = 67
4.2 关联键总图
flowchart LR
A["SCM_PO_ORDER.id"] --> B["PO_INFO.iid"]
A --> C["PO_INFO_QTY.po_order_id"]
A --> D["PO_OUT_INFO.srcOrderId"]
A --> E["PO_CLOSE_INFO.srcOrderId/iid"]
A --> F["PU_INVOICE.srcOrderId"]
B --> G["srcOrderEntryId / orderEntryId"]
G --> H["出库/关闭/入库明细行"]
A --> I["PO_ORDER_PAYINFO.po_order_id"]
A --> J["FLASH_ORDER.po_order_id"]
A --> K["来源业务 srcOrderId/srcOrderNo"]
不同历史代码会同时使用 iid、orderId、po_order_id、srcOrderId 表示采购主单 ID。排查时应根据表和方法语义确认,不可只凭字段名字面判断。
5. 状态字典
5.1 状态主链
stateDiagram-v2
[*] --> 草稿
草稿 --> 待支付: 在线支付提交
草稿 --> 待处理: 挂账/无需先支付
待支付 --> 待处理: 支付成功
待支付 --> 支付超时: 超时任务
待支付 --> 已关闭: 主动取消/异常关闭
待处理 --> 审核中: 外部审核受理
审核中 --> 待出库: 审核通过
审核中 --> 审核不通过: 审核拒绝
待出库 --> 配送中: 发生出库
配送中 --> 已完成: 全部入库/履约
待出库 --> 已关闭: 全部未发关闭
配送中 --> 已关闭: 剩余量关闭且业务终止
状态只是汇总结果,必须与明细数量账互证。手工把状态改成 5 不会自动生成入库单或库存流水。
6. 数量账模型
6.1 字段含义
6.2 字段迁移
flowchart LR
A["wait_out_qty"] -->|供应方出库 q| B["going_out_qty"]
B -->|签收/入库 q| C["in_qty"]
B -->|签收累计| D["sign_qty += q"]
A -->|未发关闭 q| E["close_qty"]
A -->|未发退货 q| F["going_refund_qty"]
C -->|已入库退货 q| F
F -->|退货完成 q| G["finish_refund_qty"]
6.3 守恒检查
对正常历史数据,可用以下关系做异常筛查:
qty ≈ wait_out_qty
+ going_out_qty
+ in_qty
+ close_qty
+ going_refund_qty
+ finish_refund_qty
其中:
sign_qty 是累计签收事实,不加入右侧。- 赠品按
sku_id + is_gift 分开核对。 - 历史迁移、旧逻辑和部分特殊订单可能未完整维护数量账,应再用出库/入库/关闭明细反算。
- 浮点数量、包装单位转换要先统一基本单位。
7. 一页式诊断树
flowchart TD
A["拿到 billNo + sid"] --> B["查 SCM_PO_ORDER"]
B --> C{"主单存在?"}
C -->|否| D["查保存日志/来源单/环境/sid"]
C -->|是| E["记录状态、类型、来源、支付方式"]
E --> F["计算 sid%32,查明细与数量账"]
F --> G{"状态停在哪"}
G -->|0| H["草稿保存/提交权限与参数"]
G -->|10/12| I["支付与超时"]
G -->|1/2/8| J["订单中心审核"]
G -->|3/4| K["出库、配送、入库"]
G -->|5| L["核对数量是否真正完成"]
G -->|9/11/13| M["关闭、退款、退货"]
K --> N["出库表 -> 入库表 -> 库存流水"]
M --> O["关闭明细 -> 支付退款 -> 来源释放"]
L --> P["若数量不守恒,按行定位脏数据"]
8. 基础查询包
以下为只读模板。先用主表查 sid,再计算后缀,不要猜分表。
8.1 主单
SELECT id, sid, billNo, billStatus, orderType, transType,
paymentType, srcOrderType, srcOrderId, srcOrderNo,
totalQty, totalAmount, amount, createTime, updateTime, isDelete
FROM t_scm_po_order
WHERE billNo = '<采购单号>';
若目标库字段名与此不同,先 SHOW COLUMNS,不要直接改 SQL。
8.2 明细
SELECT id, iid, sid, billNo, invId, skuId, isGift, qty,
price, amount, locationId, srcOrderEntryId, srcOrderId, srcOrderNo, isDelete
FROM t_scm_po_order_info_<sid_mod_32>
WHERE iid = <采购单ID>
ORDER BY id;
8.3 数量账
SELECT po_order_id, bill_no, sku_id, is_gift, qty,
wait_out_qty, going_out_qty, sign_qty, in_qty,
close_qty, going_refund_qty, finish_refund_qty
FROM t_scm_po_order_info_qty
WHERE po_order_id = <采购单ID>
ORDER BY sku_id, is_gift;
8.4 出库、关闭和入库
SELECT *
FROM t_scm_po_out_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
ORDER BY id;
SELECT *
FROM t_scm_po_close_info
WHERE (srcOrderId = <采购单ID> OR iid = <采购单ID>) AND isDelete = 0
ORDER BY id;
SELECT *
FROM t_scm_pu_invoice_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
ORDER BY id;
SELECT *
FROM t_scm_pu_invoice_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
ORDER BY id;
8.5 行级汇总
SELECT skuId, isGift,
SUM(qty) AS po_qty
FROM t_scm_po_order_info_<sid_mod_32>
WHERE iid = <采购单ID> AND isDelete = 0
GROUP BY skuId, isGift;
SELECT skuId, isGift,
SUM(qty) AS out_qty
FROM t_scm_po_out_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
GROUP BY skuId, isGift;
SELECT skuId, isGift,
SUM(qty) AS in_qty
FROM t_scm_pu_invoice_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
GROUP BY skuId, isGift;
9. 创建、保存和提交问题
9.1 入口
9.2 保存链路
sequenceDiagram
participant U as 采购员
participant C as InvPo
participant V as InvPoValidate
participant P as PoOrderSer
participant S as NormalOrderSaveService
participant DB as 采购表
U->>C: postData JSON + Session
C->>V: 仓库/订单类型/备注校验
C->>P: checkOrderGoods
P-->>C: 规范化商品明细
C->>S: savePoOrder
S->>DB: 主单/明细/扩展
DB-->>U: 草稿 ID 或错误
9.3 保存失败检查表
9.4 提交后找不到订单
- 查草稿 ID 是否真实返回。
- 查主单
isDelete 和 billStatus。 - 查提交请求是否使用了同一个
orderId。 - 查 Controller 当前分支中的
submitInvPo Service 是否真实存在并部署。 - 查是否改走新采购服务或远程 Provider。
- 查提交事务和外部创建请求日志。
- 查来源业务是否生成了另一个采购单号。
10. 审核问题
10.1 调用链
sequenceDiagram
participant D as DGJ采购
participant O as 订单中心
participant Q as ordercenter_notify
participant C as OrderCenterNotify/采购服务
participant DB as 采购表
D->>O: 创建/提交采购单
O-->>Q: ordercenter_order_audit
Q->>C: 审核结果
C->>DB: 校验来源、订单、前置状态
C->>DB: 通过->3 / 驳回->8
C-->>Q: ACK/NACK
10.2 排查步骤
- 主单当前应为 1 或 2;如果已经 3、5、9,重复审核不能再次推进。
- 查订单中心单号与
billNo/srcOrderNo/srcOrderId 的映射。 - 查
sourceChannel 是否为 DGJ 来源。 - 查
auditResult 是否能映射到通过或驳回。 - 查
ordercenter_notify.ordercenter_order_audit 是否到达当前消费服务。 - 采购售后四类回调已迁移到采购服务;不要只看 DGJ 的 ACK。
- 查驳回时来源活动、数量账和待支付关系是否需要回滚。
10.3 状态不动的判断
11. 支付问题
11.1 关键链路
flowchart LR
A["采购单状态10"] --> B["getPayInfo/noPagePay"]
B --> C["支付中心支付单"]
C --> D["paycenter_pay_result"]
D --> E["PayCenterNotify"]
E --> F["Payment + PaymentInfo"]
E --> G["PoOrderPayInfo"]
E --> H["采购状态推进"]
H --> I["活动/预订单后置处理"]
11.2 支付查询包
SELECT *
FROM t_scm_po_order_payinfo
WHERE po_order_id = <采购单ID>
ORDER BY id;
SELECT *
FROM t_scm_payment_<sid_mod_32>
WHERE srcOrderNo = '<采购单号>' OR billNo = '<支付业务单号>'
ORDER BY id;
字段以目标环境 DDL 为准。先查主表,再根据 payment id 查 t_scm_payment_info_<n>。
11.3 支付成功仍待支付
- 从支付中心确认
sourceOrderNo 是否等于 DGJ billNo。 - 确认
sourceOrderType=01 是采购单,而非预订单 04。 - 确认
payStatus=02。 - 查
PayCenterNotify::paycenterPayResult 日志。 - 查是否因主单已超时、关闭或已支付而状态校验失败并 NACK。
- 查 Payment 主明细和采购支付关系是否部分写入。
- 查事务是否回滚。
- 秒杀来源继续查
FLASH_ORDER 状态和 locked_qty/used_qty。
11.4 迟到支付决策
flowchart TD
A["支付成功消息迟到"] --> B["采购状态已12/9?"]
B -->|否| C["按正常回调处理"]
B -->|是| D["确认支付中心不可撤销事实"]
D --> E["确认订单中心是否已取消"]
E --> F["确认活动锁量是否释放"]
F --> G{"能恢复履约?"}
G -->|能| H["按领域方案恢复,补齐状态和占用"]
G -->|不能| I["走退款,不直接改回待处理"]
12. 出库和配送问题
12.1 数量变化
供应方出库 q 时:
wait_out_qty -= q
going_out_qty += q
同时写 t_scm_po_out_info_<sid%32>,其中 srcOrderOutId 可用于识别调拨中心明细重复。
12.2 出库排查步骤
- 查采购状态是否为 3 或 4。
- 查原采购行
qty 和 wait_out_qty。 - 查配送中心出库消息中的采购单号、明细行号、数量和仓库。
- 查
PoOutInfoModel::getCollectionBySrcOrderOutIds 是否判定重复。 - 查出库明细是否已写但数量账未更新。
- 查事务是否回滚。
- 查主单是否从 3 推进到 4。
- 多次部分出库按行汇总,不要只取最后一条。
12.3 出库量异常 SQL
SELECT srcOrderEntryId, skuId, isGift, SUM(qty) AS out_qty,
COUNT(*) AS out_rows
FROM t_scm_po_out_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
GROUP BY srcOrderEntryId, skuId, isGift;
SELECT srcOrderOutId, COUNT(*) AS duplicate_count, SUM(qty) AS qty
FROM t_scm_po_out_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
GROUP BY srcOrderOutId
HAVING COUNT(*) > 1;
13. 入库和库存问题
13.1 入库入口
13.2 入库主链
sequenceDiagram
participant U as 仓库/PDA
participant C as 入库入口
participant P as InvPoService
participant PI as PuInvoice表
participant INV as InventorySer
participant Q as 数量账
participant MQ as inventory_event/dgj_notify
U->>C: 采购单行 + 入库数量 + 仓库货位
C->>P: 防重复锁与可入量校验
P->>PI: 写入库主单/明细
P->>INV: 写库存流水并增加实时库存
P->>Q: going_out -= q, sign += q, in += q
P->>P: 判断主单是否完成
P->>MQ: 库存预警/入库通知
P-->>U: 成功或超过数量错误
13.3 两道超收校验
当前 Service 明确检查:
已入库数量 + 本次入库数量 <= 发货明细数量。- 汇总后
已入库数量 + 本次入库数量 <= 原采购明细数量。
如果提示超量,不应直接去掉校验。先证明是哪一种事实异常:
- 配送中心重复发货明细。
- 已存在重复入库单。
- 已软删入库单仍有库存流水。
- 并发请求在锁外或不同入口进入。
- 采购行替换/拆分后关联键错位。
- 旧历史数据已超收。
13.4 入库后库存没变
flowchart TD
A["入库接口返回成功"] --> B["PU_INVOICE 主单存在?"]
B -->|否| C["响应误判/事务回滚"]
B -->|是| D["入库明细存在且数量正确?"]
D -->|否| E["部分写入/分表错误"]
D -->|是| F["SCM_INVENTORY 流水存在?"]
F -->|否| G["InventorySer 未完成"]
F -->|是| H["REAL_TIME 仓库货位维度正确?"]
H -->|否| I["实时库存聚合/维度错误"]
H -->|是| J["页面缓存/ES/查询条件"]
13.5 库存维度
库存必须按以下组合核对:
sid + invId/skuId + warehouse/storage + location + 批次/效期(如启用)
只按 skuId 汇总可能把不同仓库、货位或批次抵消。
14. 重复入库和超收入库专项
14.1 识别重复 CG 单
SELECT srcOrderId, srcOrderNo, billNo, COUNT(*) AS cnt, SUM(totalQty) AS total_qty
FROM t_scm_pu_invoice_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
GROUP BY srcOrderId, srcOrderNo, billNo
HAVING COUNT(*) > 1;
如果每次入库生成不同 billNo,还要按来源采购行和商品汇总:
SELECT srcOrderEntryId, skuId, isGift, SUM(qty) AS total_in_qty, COUNT(*) AS row_count
FROM t_scm_pu_invoice_info_<sid_mod_32>
WHERE srcOrderId = <采购单ID> AND isDelete = 0
GROUP BY srcOrderEntryId, skuId, isGift;
14.2 四层事实核对
14.3 修复原则
flowchart TD
A["发现重复入库"] --> B["冻结单据和库存快照"]
B --> C["确认哪张是合法业务事实"]
C --> D["识别重复入库主明细"]
D --> E["识别对应库存流水/实时库存增量"]
E --> F["设计成对冲销或领域撤销"]
F --> G["更新数量账和主单状态"]
G --> H["重算库存预警和报表"]
H --> I["全链验证"]
不要只删入库表,也不要只减实时库存。过程事实、当前结果和报表来源必须一起处理。
15. 关闭和取消问题
15.1 关闭量公式
对未发采购行,通常可关闭量为:
可关闭量 = 原采购 qty - 已出库 outQty - 已入库 inQty - 已关闭 closeQty
代码中还会根据订单类型、支付方式、外部订单状态和是否已有售后决定能否关闭。
15.2 关闭数据流
flowchart LR
A["closeInvPo/closeInvPoOrder"] --> B["锁与状态校验"]
B --> C["PO_CLOSE_INFO"]
C --> D["wait_out_qty -= q"]
D --> E["close_qty += q"]
E --> F{"全部行终结?"}
F -->|是| G["主单状态9"]
F -->|否| H["部分关闭"]
G --> I["po_close_order_confirm"]
H --> I
I --> J["inventory_event 重算在途/预警"]
G --> K["在线支付退款/来源释放"]
15.3 关闭后仍有在途
- 查关闭明细是否写入正确
srcOrderEntryId。 - 查数量账
close_qty 是否增加、wait_out_qty 是否减少。 - 查
PoOrderInfoSer::getOnWayQtyByInvIds 的在途计算是否包含该状态。 - 查
sendInventoryEvent(... po_order_id) 是否发送。 - 查
SaasOrderNotify::inventory_event 是否重算预警。 - 查缓存和报表刷新延迟。
16. 采购退货问题
16.1 类型
16.2 退货数量迁移
stateDiagram-v2
[*] --> 待出库量
待出库量 --> 待退货量: 未发货退货
已入库量 --> 待退货量: 已入库商品退货
待退货量 --> 退货完成量: 退货出库/退款完成
待退货量 --> 待出库量: 未发退货取消
待退货量 --> 已入库量: 已入库退货取消/驳回
16.3 退货排查步骤
- 查退货单自身
billNo/orderType/transType/srcOrderId/srcOrderNo。 - 查原采购单和原采购行。
- 查
going_refund_qty 从 wait_out_qty 还是 in_qty 转入。 - 查订单中心售后实际由采购服务消费还是 DGJ 历史消费者。
- 需要退实物时查退货出库库存流水。
- 在线支付退货查支付中心退款事实。
- 完成后
finish_refund_qty 应增加,going_refund_qty 应减少。 - 取消/驳回后数量必须回到原来源桶。
17. 特殊来源采购
17.1 来源识别
17.2 秒杀串查
SELECT id, sid, order_no, bill_no, po_order_id, status, pay_deadline, update_time
FROM t_flash_order
WHERE po_order_id = <采购单ID>
OR bill_no = '<采购单srcOrderNo>';
SELECT d.*, g.locked_qty, g.used_qty
FROM t_flash_order_detail d
LEFT JOIN t_flash_activity_goods g ON g.id = d.activity_goods_id
WHERE d.order_id = <秒杀订单ID>;
17.3 秒杀数量变化
flowchart LR
A["提交秒杀订单"] --> B["locked_qty += q"]
B --> C["生成采购单"]
C --> D{"支付结果"}
D -->|成功| E["locked_qty -= q; used_qty += q"]
D -->|取消/超时| F["locked_qty -= q"]
E --> G{"采购关闭/退货"}
G --> H["按关闭行释放 used/locked"]
采购状态正确但秒杀锁量错误时,应使用 releaseByPoOrder、releaseByPoCloseItems 或专项补偿能力,而不是直接改活动数量字段。
18. 按现象执行 SOP
18.1 页面显示待出库,但实际上已全部入库
- 查所有入库明细并按采购行汇总。
- 查数量账
going_out_qty/in_qty/sign_qty。 - 查是否存在未关闭、未入库的赠品行。
- 查软删明细是否被页面与状态计算使用不同条件过滤。
- 查主单状态更新事务是否失败。
- 查是否属于退货单状态 13,不套普通采购完成逻辑。
- 只在数量完全守恒后设计状态补偿。
18.2 页面显示已完成,但仍有待入库数量
- 不要以主单 5 作为完成证据。
- 对每个
sku_id + is_gift 计算守恒。 - 查是否有采购行被替换、拆分或软删。
- 查关闭量是否漏记。
- 查旧代码是否只按某一张入库单推进主单。
- 评估是补入库/关闭事实还是回退主单状态。
18.3 关闭成功但退款没到
- 确认
paymentType=1。 - 查采购状态 11/9/12 和关闭原因。
- 查支付关系与原支付单。
- 查退款申请是否发给支付中心。
- 查
paycenter_refund_result。 - 查退款账户/支付明细状态。
- 不要重复发起退款,先用支付中心退款单号去重。
18.4 App 能查列表但操作提示接口不存在
- 查
tradeCode。 - 查
appapis.php 映射。 - 拼出
application/service/api/app/...php。 - 当前静态审计显示部分旧采购映射目标不存在。
- 确认 App 版本是否仍调用旧 code。
- 确认是否已迁移到直接 Controller 或新采购服务。
19. 日志与代码定位
19.1 代码命令
rg -n "public function (saveInvPo|submitInvPo|cancelWaitPayOrder|closeInvPo|invPoInStroage)" application/controllers/scm/InvPo.php
rg -n "入库数量超过发货数量|入库数量超过采购数量" application/service/scm/InvPoService.php
rg -n "wait_out_qty|going_out_qty|sign_qty|going_refund_qty" application/models/orders/PoOrderInfoQtyModel.php
rg -n "ordercenter_order_audit|paycenter_pay_result|dispatchcenter_delivery_stock_out" application/controllers/tasks application/KzData/Enums
rg -n "sendInventoryEvent|sendPoCloseOrderConfirm|sendInStorageEvent" application/service/scm/InvPoService.php application/Services
rg -n "ORDERTYPE_FLASH_ORDER|releaseByPoOrder|compensatePaidOrders" application/Services/Activity/FlashSaleSer.php
19.2 日志关键词
billNo + InvPo
billNo + paycenterPayResult
billNo + orderCenterOrderAudit
billNo + dispatchCenterDeliveryStockOut
srcOrderOutId + 出库
采购单ID + 入库数量超过
po_order_id + inventory_event
19.3 时间线模板
把真实数据填进时间线,空白处就是需要继续查的断点。
20. 修复和补偿安全流程
20.1 修复前快照
- 采购主单完整行。
- 采购明细和数量账。
- 出库、关闭、入库主明细。
- 支付主明细和退款事实。
- 库存流水、实时库存、库存预警。
- 来源活动/预订单/渠道关系。
- 相关 MQ 原始 payload 和消费日志。
20.2 补偿选择
flowchart TD
A["确定断点"] --> B{"主业务事实存在?"}
B -->|否| C["重做领域命令/补发原始事件"]
B -->|是| D{"缺的是哪类副作用"}
D -->|状态| E["领域状态补偿,先校验数量"]
D -->|库存| F["库存冲销/补流水,不裸改实时库存"]
D -->|支付| G["按支付中心事实补账或退款"]
D -->|后置MQ| H["只补对应事件"]
D -->|来源释放| I["调用活动/预订单领域补偿"]
C --> J["单条验证"]
E --> J
F --> J
G --> J
H --> J
I --> J
20.3 修复后四层验收
21. 改动风险
22. 回归清单
22.1 普通采购
- [ ] 草稿保存、修改、删除、提交。
- [ ] 普通仓、不可用仓、移动仓校验。
- [ ] 单商品、多商品、赠品、不同包装单位。
- [ ] 审核通过、驳回、重复审核。
- [ ] 整单出库、部分出库、多批次出库。
- [ ] 整单入库、部分入库、多批次入库。
- [ ] 部分关闭、整单关闭、已出库不可关闭。
22.2 在线支付
- [ ] 支付成功、失败、异常、取消和超时。
- [ ] 相同成功回调重复投递。
- [ ] 超时关闭后迟到支付。
- [ ] 关闭后退款成功、失败和重复退款回调。
- [ ] Payment、PaymentInfo、PoOrderPayInfo 金额一致。
22.3 仓储数量
- [ ]
wait_out -> going_out -> in 数量守恒。 - [ ] 入库不得超过发货量。
- [ ] 入库不得超过采购量。
- [ ] 并发重复入库被锁或数据库规则阻止。
- [ ] 入库失败时采购入库表和库存都回滚。
- [ ] 库存流水、实时库存、预警同步。
22.4 退货和特殊来源
- [ ] 未发货退货、已入库退货、驳回和取消。
- [ ] 退货出库减库存,完成量正确。
- [ ] 秒杀支付成功、超时、采购关闭和行关闭释放数量。
- [ ] 赠品活动、预订单、首配、自制单来源关系正确。
- [ ] App 旧 code 和新入口兼容策略明确。
23. 已确认与待确认
23.1 静态代码已确认
- 采购主单使用不分表
SCM_PO_ORDER。 - 采购明细和出库明细按
sid % 32。 - 采购入库主单、明细按
sid % 32。 - 数量账
PoOrderInfoQtyModel 当前不分表。 - 入库 Service 同时校验不得超过发货数量和采购数量。
- 入库完成后发送库存事件和采购入库通知。
- 关闭后会发送库存事件,部分场景发送采购关闭确认。
- 支付中心、订单中心、配送中心通过 MQ 推进采购。
- 订单中心四个售后回调已迁移到采购服务并在 DGJ 直接 ACK。
- 秒杀采购使用
30-Cxx-77 和来源类型 13。
23.2 环境和历史数据待确认
- 当前部署的提交采购真实 Service 和远程采购 Provider 版本。
- 线上表 DDL、索引、唯一键和字段名。
- 采购服务对已迁移订单中心消息的队列所有权。
- 支付、订单、配送 MQ 的重试/死信配置。
- 历史订单是否完整维护数量账。
- App 旧采购映射是否仍有调用流量。
- 入库 Redis 锁粒度、TTL 和多入口覆盖范围。
- 报表读取业务表、历史月表还是 DWD,以及同步延迟。
24. 证据来源
25. 一页式执行结论
先查不分表采购主单,拿到 sid 和 id。
再算 sid%32,查采购明细、出库明细、入库主明细。
用数量账判断卡在待出库、配送、入库、关闭还是退货。
状态10/12查支付;状态1/2/8查订单中心;状态3/4查配送和入库;状态9/11/13查关闭退款退货。
主单状态与数量不一致时,以过程事实和数量守恒为准,不先改状态。
任何修复都必须同时核对采购、库存、资金和来源业务。
请求-日志-数据变更追踪卡
多入口请求链路
日志证据矩阵
| 链路段 | 日志来源 | 可检索锚点 | 成功信号 | 失败信号 | 与下一段关联方式 | | --- | --- | --- | --- | --- | --- | --- | | 入口 | Web/App/MQ 日志 | request_id、sid、采购/来源单号、action | 命中对应方法 | 校验、鉴权、未知事件失败 | 单号进入 Service/主表 | | 主明细 | InvPoService/PoOrderSer | billNo、订单类型、当前状态 | commit,主明细数量金额一致 | rollback、状态冲突、重复来源 | 查 SCM_PO_ORDER* | | 支付 | PayCenterNotify | payOrderNo、采购单、payStatus | 支付记录一次落账 | 重复入账、迟到支付、金额不符 | 支付关系查采购状态 | | 履约库存 | 入出库 Service、InventorySer | 单号、SKU、transType、仓位 | 发/收/关数量守恒,库存同步 | 超收/超退、重复流水、实时不一致 | 采购明细 + 库存流水 + 实时表 |
环节数据变更台账
子模块追踪:po-create-check 采购创建、保存与提交排查
子模块追踪:po-audit-check 采购审核排查
子模块追踪:po-pay-check 采购支付排查
子模块追踪:po-delivery-check 采购出库与配送排查
子模块追踪:po-inbound-check 采购入库与库存排查
子模块追踪:po-overreceipt-check 重复入库与超收排查
子模块追踪:po-close-check 采购关闭取消排查
子模块追踪:po-return-check 采购退货与特殊来源排查