phpwordpresswoocommercecartfee

Remove Woocommerce handling fee if cart total is zero


I am using the following snippet to add a flat rate handling fee to physical items in my cart. My company offers free books with free shipping to our employees via use of a coupon, so I need this fee to be removed if the cart total is zero. Not sure how to accomplish this.

/* Add handling to cart at checkout */
add_action( 'woocommerce_cart_calculate_fees','handling_fee' );
function handling_fee() {
    global $woocommerce; 
 
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
 
    // First test if all products are virtual. Only add fee if at least one product is physical.
    $allproductsvirtual = true; 
    $fee = 0;
    foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values) {
 
        $product = $values['data'];
 
        if( !$product->is_virtual() ){
            $allproductsvirtual = false;
        }
    }
    if ( !$allproductsvirtual ) {
        $fee = 3.00;
    }
    $woocommerce->cart->add_fee( 'Handling', $fee, false, 'standard' );
}

I have tried researching the issue and have not found a solution.


Solution

  • You can use the following simplified and optimized code that will add a fee if the cart has at least a physical item and if cart subtotal is not equal to zero (meaning that there is at least a cart item with a price greater than zero):

    add_action( 'woocommerce_cart_calculate_fees', 'add_shipping_handling_fee', 10, 1 );
    function add_shipping_handling_fee( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( $cart->needs_shipping() && $cart->subtotal > 0 ) {
            $cart->add_fee( __('Handling', 'woocommerce'), 3.00, false );
        }
    }
    

    Or keeping your way:

    add_action( 'woocommerce_cart_calculate_fees', 'add_shipping_handling_fee', 10, 1 );
    function add_shipping_handling_fee( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        $needs_shipping = false; // Initializing
    
        // Check if there is at least one physical product in cart 
        foreach ( $cart->get_cart() as $item ) {
            if( ! $item['data']->is_virtual() ){
                $needs_shipping = true;
                break;
            }
        }
    
        if ( $needs_shipping && $cart->subtotal > 0 ) {
            $cart->add_fee( __('Handling', 'woocommerce'), 3.00, false );
        }
    }
    

    Both ways should work.

    Note that we can only check for cart subtotal amount.