订单 Grand Total 是 1000,后台创建发票时却只显示 850,或多张部分发票相加与订单差 0.01。先不要直接修改发票金额。Magento 发票只包含本次可开票的商品数量及其分摊税费、折扣、运费和调整金额,订单总额还可能包含已取消、已退款或尚未开票的部分。
逐行比较 ordered、invoiced、refunded 与 canceled
SELECT item_id, sku, qty_ordered, qty_invoiced,
qty_refunded, qty_canceled, row_total,
tax_amount, discount_amount
FROM sales_order_item
WHERE order_id=100001;
可配置商品同时有父子行,金额通常只落在其中一层,不能把两行相加。Bundle 动态价格与固定价格的金额分布也不同。先找出本次实际开票的实体行和数量,再比较金额。
部分开票会按比例分摊折扣和税
固定购物车折扣需要分配到多条商品行。第一次只开其中一部分时,Magento 会把对应折扣计入发票,并保留剩余金额给后续发票。逐次舍入可能产生小额 delta,通常在最后一张发票中调整,确保累计不超过订单。
第三方 Total Collector 如果只在 Quote 保存自定义费用,却没有把字段复制到 Order、Invoice 和 Credit Memo,就会出现订单有费用、发票没有,或退款无法还原。自定义金额必须同时维护 base 与订单币字段。
运费是否进入第一张发票要看操作
后台创建部分发票时可以选择是否包含运费。第一张已把全部运费开票,后续发票不会再次包含。税费是否随运费计算也受税配置影响。
在线捕获与离线发票不能混淆
点击 Submit Invoice 时选择 Capture Online,会向支付网关捕获本次金额;Capture Offline 只更新 Magento,不一定向网关收款。订单已在下单时全额捕获,后台发票只是账务记录时,也不应再次捕获。
检查支付 transaction 与发票:
SELECT entity_id, increment_id, order_id, grand_total,
base_grand_total, state, created_at
FROM sales_invoice
WHERE order_id=100001;
SELECT txn_id, txn_type, is_closed, created_at
FROM sales_payment_transaction
WHERE order_id=100001;
0.01 差异要追踪到首次舍入位置
比较 base 与 display currency、单价、行总计、税和折扣。不要在最终 grand_total 上硬加一分钱,这会让订单、发票、支付和退款不一致。应修复自定义 collector 的 delta round 或外部系统的重算规则。
验证时创建包含多数量、固定折扣、百分比折扣、税、运费和多币种的订单,分两次开票,再做部分退款。累计 Invoice、Capture 与 Credit Memo 都应与订单可收可退金额一致。

