我通过创建新订单并将订单项移至其中,在钩子 woocommerce_order_status_changed 上将订单分成 2 个。然而,当调用
calculate_totals()
时,calculate_taxes()
将调用 save()
,从而立即提前发送电子邮件通知,订单总数为 0,因为总数尚未计算,绕过 calculate_taxes()
意味着税费将是错误的。
在这种情况下,如何才能最好地计算总额和税费,而不在计算之前触发电子邮件通知?我想我可以做任何一个:
calculate_totals()
并手动计算两者都同样没有吸引力,那么什么是一个好的方法呢?
public static function add_hooks() {
// After payment is confirmed, we split the order based on order items
add_action( 'woocommerce_order_status_pending_to_processing', [ __CLASS__, 'split_order' ], 10, 2 );
}
public static function split_order( $order_id, WC_Order $order, $force = null ) {
// Iterate the order items and add them to $items_to_split if they need to be split into a
// seperate order, reason for this is that we explicitely need them in separate orders
$items_to_split = array();
foreach ( $order->get_items() as $item_id => $item_data ) {
if ( $item_data->meta_exists( '_SnapshotId' ) ) {
$items_to_split[ $item_id ] = $item_data;
}
}
if ( count( $items_to_split ) === 0 ) return;
$new_order = wc_create_order();
$new_order->set_customer_id( $order->get_customer_id() );
$new_order->set_payment_method( $order->get_payment_method() );
$new_order->set_created_via( 'split_order' );
$new_order->set_status( $order->get_status() );
$new_order->set_billing( $$order->get_address( 'billing' ) );
$new_order->set_shipping( $$order->get_address( 'shipping' ) );
// Move the items to split to new order
foreach ( $items_to_split as $item_id => $item_data ) {
/** @var WC_Order_Item_Product $item_data */
$new_order_item = new WC_Order_Item_Product();
// set_meta_data() doesn't accept WC_Meta_data and causes issues reusing metadata ids
// $new_order_item->set_meta_data($item_data->get_meta_data());
// Also can't clone $item_data because it does not truncate id & order_id on __clone
// Add item (meta) data to new order item
$data = $item_data->get_data();
unset( $data['id'] );
unset( $data['order_id'] );
$new_order_item->set_props( $data );
$meta_data = array_map( function ( $n ) {
return $n->get_data();
}, $data['meta_data'] );
foreach ( $meta_data as $meta_data_entry ) {
$new_order_item->add_meta_data( $meta_data_entry['key'], $meta_data_entry['value'] );
}
$new_order->add_item( $new_order_item );
$order->remove_item( $item_id );
}
// Will call save(), causing immediate early trigger of email notifications
// with order totals as 0
$new_order->calculate_totals();
$order->calculate_totals();
}
解决方案是简单地将新订单的状态更改移至
calculating_totals()
之后,因为对于状态为待处理的订单,不会发送电子邮件通知。
$new_order->calculate_totals();
$new_order->set_status( $order->get_status() );
$new_order->save();
感谢 LoicTheAztec 指出了这一点。
状态更改挂钩保留有利于
woocommerce_checkout_create_order
和 woocommerce_new_order
,因为在付款完成之前拆分订单可能会导致必须为 2 个单独的订单付款,而我们的用例希望将其保留为单个订单的付款分裂之前。