Reputation: 534
In WooCommerce, I'm wondering is there a simple solution to subtract the subtotal from the total without adding another fee? And have this appear in all places such as checkout, orders (Woocommerce), my orders (my-account/view-order/) etc.
The reason for this is that I have added custom fees / surcharges to products which is 10% reservation fee of subtotal, and I only want the surcharges to be paid first and rest offline (like collection).
For example
So, Is there a simple way to remove the subtotal from total on complete order table as well as cart / checkout? Thanks
add_filter( 'woocommerce_calculated_total', 'custom_cart_total', 20, 2 );
function custom_cart_total( $total, $cart ) {
return $total - $subtotal;
}
Upvotes: 1
Views: 1478
Reputation: 29614
The woocommerce_calculated_total
filter hook can indeed be used, only $subtotal
is undefined in your current code.
So you get:
// 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 );
Update:
In first instance this hook works and the new total is displayed in order details tables, WooCommerce email notifications, etc.. however, when changes are made to the order, everything is recalculated.
To get around this, we can manipulate the total when the recalculations take place.
Step 1: Add specific meta data if applicable to the current order after WooCommerce checkout
/**
* 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 );
Step 2: manipulate the total, when changes are made for this specific order
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 );
The downside of this is that it will only be applied for changes made via the order edit page. To also apply this from the WooCommerce admin orders list you could remove the if condition, but then the change will not only be applied to the current order but also to all previous orders (if applicable).
In short: far from the ideal solution
Upvotes: 2