如何在 WooCommerce 中从总计中减去小计?

How to subtract subtotal from total in WooCommerce?

在 WooCommerce 中,我想知道是否有一种简单的解决方案可以在不增加额外费用的情况下从总数中减去小计?并将其显示在所有地方,例如结帐、订单 (Woocommerce)、我的订单 (my-account/view-order/) 等

原因是我给产品加了custom fees / surcharges 是小计的10% reservation fee,我只想先付surcharge,线下休息(如代收)。

例如

那么,有没有一种简单的方法可以从完整订单 table 以及购物车/结帐的总计中删除小计?谢谢

add_filter( 'woocommerce_calculated_total', 'custom_cart_total', 20, 2 );
function custom_cart_total( $total, $cart ) {
    return $total - $subtotal;
}

确实可以使用woocommerce_calculated_total过滤器钩子,只是$subtotal在您当前的代码中未定义。

所以你得到:

// Allow plugins to filter the grand total, and sum the cart totals in case of modifications.
function filter_woocommerce_calculated_total( $total, $cart ) { 
    // Get subtotal
    $subtotal = $cart->get_subtotal();
    
    return $total - $subtotal;
}
add_filter( 'woocommerce_calculated_total', 'filter_woocommerce_calculated_total', 10, 2 );

更新:

在第一个实例中,此挂钩有效,新的总数显示在订单详细信息表、WooCommerce 电子邮件通知等中。但是,当对订单进行更改时,所有内容都会重新计算。

为了解决这个问题,我们可以在重新计算时操纵总数。

第 1 步: 在 WooCommerce 结账后添加特定元数据(如果适用于当前订单)

/**
 * Action hook fired after an order is created used to add custom meta to the order.
 *
 * @since 3.0.0
 */
function action_woocommerce_checkout_update_order_meta( $order_id, $data ) {    
    // Get an instance of the WC_Order object
    $order = wc_get_order( $order_id );
    
    // Is a WC_Order
    if ( is_a( $order, 'WC_Order' ) ) {     
        // Get subtotal
        $subtotal = $order->get_subtotal();
        
        // Get total
        $total = $order->get_total();
        
        // Total is less than subtotal
        if ( $total < $subtotal ) {
            // Save the order data and meta data
            $order->update_meta_data( '_is_recalculated_order_id', $order_id );
            $order->save();
        }
    }
}   
add_action( 'woocommerce_checkout_update_order_meta', 'action_woocommerce_checkout_update_order_meta', 10, 2 );

第 2 步: 在针对此特定订单进行更改时操纵总数

function filter_woocommerce_order_get_total( $total, $order ) {
    global $pagenow;
    
    // Only on order edit page
    if ( $pagenow != 'post.php' || get_post_type( $_GET['post'] ) != 'shop_order' ) return $total;
    
    // Get meta
    $is_recalculated_order_id = $order->get_meta( '_is_recalculated_order_id' );
    
    // NOT empty and meta value is equal to current order ID
    if ( ! empty ( $is_recalculated_order_id ) && $is_recalculated_order_id == $order->get_id() ) {     
        // Get subtotal
        $subtotal = $order->get_subtotal();
        
        // Subtotal is less than total
        if ( $subtotal < $total ) {         
            // Manipulate
            $total = $total - $subtotal;
        }
    }
    
    return $total;
}
add_filter( 'woocommerce_order_get_total', 'filter_woocommerce_order_get_total', 10, 2 );

这样做的缺点是它只会应用于通过订单编辑页面所做的更改。要从 WooCommerce 管理员订单列表中应用此功能,您可以删除 if 条件,但更改不仅会应用于当前订单,还会应用于所有以前的订单(如果适用)。

简而言之:远非理想的解决方案