退款成功并不必然等于库存回补。Magento 2 创建 Credit Memo 时,财务退款与库存退货是两个决定;启用 MSI 后还要区分 Source Quantity 和 Salable Quantity。排查前先记录订单号、Credit Memo、SKU、退款数量、发货来源和操作人。

先确认 Credit Memo 是否要求 Return to Stock

打开退款记录,检查每个商品的 Return to Stock 是否勾选、Qty to Refund 是否正确。线上退款网关返回成功,只证明资金处理完成;如果 API 创建贷项通知单时没有传回库参数,库存不会自动增加。

把订单生命周期查完整

SELECT entity_id, increment_id, state, status, total_qty_ordered
FROM sales_order WHERE increment_id='000001500';

SELECT entity_id, increment_id, order_id, created_at
FROM sales_creditmemo
WHERE order_id=(SELECT entity_id FROM sales_order WHERE increment_id='000001500');

SELECT sku, qty, back_to_stock
FROM sales_creditmemo_item
WHERE parent_id=321;

不同版本字段可能略有差异,执行前用 DESCRIBE sales_creditmemo_item 核对。查询用于取证,不直接 UPDATE 销售表。

MSI 中 Source Quantity 与 Reservation 分开看

SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku='REFUND-SKU';

SELECT stock_id, sku, quantity, is_salable
FROM inventory_stock_1
WHERE sku='REFUND-SKU';

SELECT reservation_id, stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE sku='REFUND-SKU'
ORDER BY reservation_id DESC
LIMIT 20;

inventory_stock_1 可能是视图或索引表,Stock ID 也不一定是 1,应按销售渠道实际绑定查询。发货时 Source Deduction 减少来源库存;取消或退款相关操作则可能通过补偿预留影响可售量,两者变化时间不同。

检查不一致而不是手工加数量

php bin/magento inventory:reservation:list-inconsistencies -r
php bin/magento inventory:reservation:list-inconsistencies -c

先只列出结果并核对订单。只有确认属于缺失补偿且理解命令输出时,才在维护流程中生成补偿。直接 UPDATE inventory_reservation 或 source quantity 容易造成重复回补。

第三方退款接口是否只做了在线退款

搜索支付模块和 ERP 集成中创建 Credit Memo 的代码,检查是否设置退款商品数量与 return-to-stock 标志:

grep -R --line-number --include='*.php' \
  -E 'Creditmemo|refund\(|back_to_stock|ReturnToStock' app/code vendor/vendorname 2>/dev/null

修复时要实现幂等:支付回调重试不能创建第二张 Credit Memo,也不能再次加库存。

回归至少覆盖未发货取消、已发货全额退款、部分数量退款、Bundle/可配置商品和多来源发货。每种情况同时记录 Source Quantity、Salable Quantity、Reservation 与销售单据,四者符合业务含义才算通过。