Search code examples
phpwordpresswoocommerceproduct

Exclude Product Taxes based on product categories and country in WooCommerce


We want to exclude tax from some of our WooCommerce products (specific categories). For now, we have created a tax class when buyers are from Australia. I want to make it tax free even it's from Australia or somewhere else.

I created a new class with zero tax rate and trying this custom code:

function change_tax_for_specific_cat_product( $id ) {
    $product = wc_get_product( $id );

    if ( $product && $product instanceof WC_Product ) {
        // Array of category IDs for which we want to set 'Zero rate'
        $zero_tax_categories = array( 30, 32, 29, 34, 28 ); // Add other category IDs as needed

        // Check if the product belongs to any of the specified categories
        if ( has_term( $zero_tax_categories, 'product_cat', $id ) ) {
            $product->set_tax_class( 'Zero rate' );
        } else {
            $product->set_tax_class( 'Standard' );
        }

        // Temporarily remove the action to avoid recursion
        remove_action( 'woocommerce_update_product', 'change_tax_for_specific_cat_product' );

        $product->save();

        // Re-add the action after saving
        add_action( 'woocommerce_update_product', 'change_tax_for_specific_cat_product' );
    }
}

add_action( 'woocommerce_update_product', 'change_tax_for_specific_cat_product' );

Is there any better option to achieve this functionality. Also I want no price suffix when there is no Tax applied.


Solution

  • To alter the product tax class based on product categories and specific country (Australia), you could use the following:

    // Utility function: check if product category handle zero rate tax class
    function is_zero_rate_tax_class( $product_id ) {
        return  has_term( array(28, 29, 30, 32, 34), 'product_cat', $product_id );
    }
    
    // Conditional function: Check if the customer is from specific country code
    function is_from_targeted_country( $country_code ) {
        return WC()->customer->get_billing_country() === $country_code;
    }
    
    // Alter product tax class
    add_filter( 'woocommerce_product_get_tax_class', 'filter_product_tax_class', 10, 2 );
    add_filter( 'woocommerce_product_variation_get_tax_class', 'filter_product_tax_class', 10, 2 );
    function filter_product_tax_class( $tax_class, $product ) {
        $product_id = $product->get_parent_id() ?: $product->get_id();
    
        if ( is_from_targeted_country('AU') && is_zero_rate_tax_class($product_id) ) {
            return 'zero-rate';
        }
        return $tax_class;
    }
    
    // Alter cart items tax class (and order items too)
    add_action( 'woocommerce_before_calculate_totals', 'alter_cart_items_tax_rate', 20, 1 );
    function alter_cart_items_tax_rate( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( ! is_from_targeted_country('AU') ) 
            return;
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $item ) {
            if ( is_zero_rate_tax_class($item['product_id']) ) {
                $item['data']->set_tax_class('zero-rate');
            }
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work.