skip to Main Content

I need to set a different tax class for company users whose billing address is outside Germany in WooCommerce. Generally, it is always 19%, but in this case, I need to set it to 0%. I have implemented this with the following code snippet. However, it only works on the checkout page. On the thank you page and invoice, it always shows 19% instead of the 0% I set with the code snippet below. What I need is to set a 0% tax class for particular orders and ensure that it remains consistent throughout the purchasing process.
Any guidance on resolving this issue would be highly appreciated.

function apply_conditionally_taxes() {
    if ( !is_admin() && !empty(WC()->cart->get_cart()) ) {  
        $billing_country = WC()->customer->get_billing_country();
        $post_data = isset( $_POST['post_data'] ) ? wp_unslash( $_POST['post_data'] ) : '';
        parse_str( $post_data, $parsed_data );
        $billing_company = isset( $parsed_data['billing_company'] ) ? sanitize_text_field( $parsed_data['billing_company'] ) : '';
        
        if ( !empty( $billing_company ) && $billing_country != 'DE'   ) {
            $cart_item['data']->set_tax_class( 'Online World' );
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'apply_conditionally_taxes', 99, 1 );

I’m providing additional details to clarify the situation. No custom forms are being utilized; instead, I’m solely relying on the standard WooCommerce checkout form, specifically focusing on the billing address field. Although the code snippet mentioned earlier functions correctly on the checkout page, it consistently reverts to the default tax rate when a user proceeds to complete the purchase.

2

Answers


  1. To ensure that the tax class is consistently set to 0% for company users outside Germany throughout the entire purchasing process, you need to adjust your approach. The issue with the code you provided is that it only modifies the tax class during the woocommerce_before_calculate_totals action, which might not cover all scenarios.

    To achieve a more consistent tax class setting, you can use the woocommerce_before_calculate_totals hook along with additional hooks that cover different stages of the purchasing process, such as the woocommerce_checkout_create_order and woocommerce_checkout_update_order_meta hooks.

    Here’s an updated code snippet:

    function apply_conditionally_taxes( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
            return;
        }
    
        $billing_country = WC()->customer->get_billing_country();
        $billing_company = WC()->customer->get_billing_company();
    
        if ( ! empty( $billing_company ) && $billing_country !== 'DE' ) {
            foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
                $cart_item['data']->set_tax_class( 'zero-rate' );
            }
        }
    }
    add_action( 'woocommerce_before_calculate_totals', 'apply_conditionally_taxes', 10, 1 );
    
    function set_order_tax_class( $order_id ) {
        $order = wc_get_order( $order_id );
        $billing_country = $order->get_billing_country();
        $billing_company = $order->get_billing_company();
    
        if ( ! empty( $billing_company ) && $billing_country !== 'DE' ) {
            foreach ( $order->get_items() as $item_id => $item ) {
                $item->set_tax_class( 'zero-rate' );
            }
        }
    }
    add_action( 'woocommerce_checkout_create_order', 'set_order_tax_class', 10, 1 );
    add_action( 'woocommerce_checkout_update_order_meta', 'set_order_tax_class', 10, 1 );
    

    Make sure you have a tax class named ‘Online World’ with a tax rate of 0% set up in your WooCommerce settings.

    This code will set the tax class to ‘zero-rate’ during the cart calculation and will update the tax class for each item in the order during the order creation process. Adjust the tax class name (‘zero-rate’) accordingly based on your actual setup.

    Login or Signup to reply.
  2. You need a script to set/update the billing company when customer input/remove a billing company in checkout. This can be done via an Ajax request targeting billing company changes in checkout page.

    You need to be sure that "Online World" is the right working tax rate (for zero rate), as in WooCommerce we use "Zero rate" or better "zero-rate". So be sure to set in the first function the correct working tax rate.

    The code:

    // Change conditionally cart items tax rate
    add_action( 'woocommerce_before_calculate_totals', 'alter_cart_items_tax_rate', 99, 1 );
    function alter_cart_items_tax_rate( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( ! ( WC()->customer->get_billing_country() !== 'DE' && ! empty(WC()->customer->get_billing_company()) ) )
            return;
    
        // Here define the replacement tax class
        $company_tax_class_slug = 'zero-rate'; // or 'online-world';
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item ) {
            $cart_item['data']->set_tax_class( $company_tax_class_slug );
        }
    }
    
    // Send Ajax request: Update customer billing company on change
    add_action('woocommerce_checkout_init', 'enqueue_checkout_custom_js_script');
    function enqueue_checkout_custom_js_script() {
        wc_enqueue_js( "$('form.checkout').on('change', 'input[name=billing_company]', function() {
            $.ajax({
                type: 'POST',
                url: '" . admin_url('/admin-ajax.php') . "',
                data: {
                    'action' : 'billing_company_update',
                    'company': $(this).val()
                },
                success: function (response) {
                    $(document.body).trigger('update_checkout');
                }
            });
        });" );
    }
    
    // PHP AJAX Receiver: Process ajax request
    add_action('wp_ajax_billing_company_update', 'set_customer_billing_company');
    add_action('wp_ajax_nopriv_billing_company_update', 'set_customer_billing_company');
    function set_customer_billing_company() {
        if ( isset($_POST['company']) ) {
            $company = sanitize_text_field($_POST['company']);
    
            WC()->customer->set_billing_company( $company );
            WC()->customer->save();
        }
        wp_die();
    }
    

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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search