订单显示已付款,但后台没有“发货”按钮,不能简单等同于支付异常。Magento 是否允许创建 Shipment,取决于订单中是否仍有可发货的实体商品、订单 state 是否允许,以及模块对 canShip() 的判断。付款只是其中一个条件。
先看每个订单行的数量
虚拟商品和下载商品本来就不需要发货。实体商品则要比较 ordered、shipped、refunded 和 canceled 数量。可以在只读数据库连接中检查:
SELECT item_id, sku, product_type,
qty_ordered, qty_shipped, qty_refunded, qty_canceled,
is_virtual, parent_item_id
FROM sales_order_item
WHERE order_id = 100001;
可配置商品会同时保存父行和简单商品子行,不能把两行都当成独立可发数量。若所有实体行都已发完、取消或退款,系统不再提供发货入口是正常的。
状态标签和内部 state 不是一回事
自定义状态可能显示“已付款”,但绑定的内部 state 已经是 complete、closed 或 canceled。查询订单的 state、status,并在后台检查状态分配。不要为了显示按钮直接修改 sales_order 表;订单状态、库存和支付记录必须保持一致。
SELECT entity_id, increment_id, state, status,
total_qty_ordered
FROM sales_order
WHERE increment_id = '000000123';
支付方式采用 Authorize Only 时,订单可以已授权但尚未捕获;采用 Capture 时可能已自动生成发票。能否发货不要求所有场景都先有发票,但支付扩展经常通过插件增加业务限制,因此要同时查看 payment additional information 与支付模块日志。
启用 MSI 后还要选择正确来源
Multi-Source Inventory 会在下单时创建 reservation,发货时从 Source 扣减。确认订单销售渠道关联的 Stock 包含可用 Source,来源商品状态启用且有足够数量。可用量异常时可运行官方库存一致性命令做检查,但不要直接手工删除 reservation 记录。
bin/magento inventory:reservation:list-inconsistencies
bin/magento inventory:reservation:create-compensations
第二条命令会写入补偿预约,执行前应先审阅第一条输出,并在备份和维护窗口内处理。
如果原生订单可以发货,只有特定支付、ERP 或仓储模块的订单不行,就检查它们对 Order 或 Shipment service 的 around/after plugin。修复后用一个实体商品新建订单,完成付款、开票、部分发货和剩余发货,确认可发数量随流程正确减少,而不是仅让按钮重新出现。

