Add Tax Exempt form on checkout in woocommerce

I am trying to add a form to my checkout page so when a user clicks the ‘Tax Exempt’ checkbox, a textbox will popup and ask the user what the Tax Exempt Id number is.

I got all of that working great, and I even added the update_totals_on_change class to my form field so it will update the totals.

Read More

My next step was to add an action/filter on a method so when the update_totals_on_change executes, I can set the tax to 0 and then it will finish calculating the total.

Does anyone know which functions I can hook on to?

Looking at the checkout.js file in WooCommerce, they set the action to woocommerce_update_order_review for the ajax operation.

I tried following that but soon got lost.

I was thinking I could add some post data by hooking in to woocommerce_checkout_update_order_review

and then hooking in to woocommerce_before_calculate_totals to modify the tax stuff, but I have no idea what I need to modify.

Am I even on the right path?

Related posts

Leave a Reply

5 comments

  1. Alright, I finally figured it out in case anyone is interested.

    In my plugin, I made a form after the order notes by hooking in to this function: ‘woocommerce_before_order_notes’

    add_action('woocommerce_before_order_notes', array(&$this, 'taxexempt_before_order_notes') );
    

    my ‘taxexempt_before_order_notes’ function contained:

    function taxexempt_before_order_notes( $checkout ) {
    
            echo '<div style="clear: both"></div>
    
            <h3>Tax Exempt Details</h3>';
    
            woocommerce_form_field( 'tax_exempt_checkbox', array(
                'type'          => 'checkbox',
                'class'         => array('tiri taxexempt'),array( 'form-row-wide', 'address-field' ),
                'label'         => __('Tax Exempt'),
                ), $checkout->get_value( 'tax_exempt_checkbox' ));
    
            woocommerce_form_field( 'tax_exempt_name', array(
                'type'          => 'text',
                'class'         => array('form-row-first', 'tiri', 'taxexempt', 'textbox', 'hidden'),
                'label'         => __('Tax Exempt Name'),
                ), $checkout->get_value( 'tax_exempt_name' ));
    
            woocommerce_form_field( 'tax_exempt_id', array(
                'type'          => 'text',
                'class'         => array('form-row-last', 'tiri', 'taxexempt', 'textbox', 'hidden', 'update_totals_on_change'),
                'label'         => __('Tax Exempt Id'),
                ), $checkout->get_value( 'tax_exempt_id' ));
        }
    

    Then the most important woocommerce function to hook was: ‘woocommerce_checkout_update_order_review’

    add_action( 'woocommerce_checkout_update_order_review', array(&$this, 'taxexempt_checkout_update_order_review' ));
    function taxexempt_checkout_update_order_review( $post_data ) {
            global $woocommerce;
    
            $woocommerce->customer->set_is_vat_exempt(FALSE);
    
            parse_str($post_data);
    
            if ( isset($tax_exempt_checkbox) && isset($tax_exempt_id) && $tax_exempt_checkbox == '1' && !empty($tax_exempt_id))
                $woocommerce->customer->set_is_vat_exempt(true);                
        }
    

    I simply parsed out the $post_data that is the serialized form data from the checkout.js file in woocommerce and checked if my part of the form was filled out correctly.

    If it was, then I would set the tax exempt for the user.

  2. The accepted solution didn’t work for me, but I modified it to use the following:

    //=============================================================================
    // ADD TAX EXEMPT CHECKMARK
    // =============================================================================
    add_action( 'woocommerce_after_order_notes', 'qd_tax_exempt');
    
    function qd_tax_exempt( $checkout ) {
    
      echo '<div id="qd-tax-exempt"><h3>'.__('Tax Exempt').'</h3>';
    
      woocommerce_form_field( 'shipping_method_tax_exempt', array(
          'type'          => 'checkbox',
          'class'         => array(),
          'label'         => __('My organization is tax exempt.'),
          'required'  => false,
          ), $checkout->get_value( 'shipping_method_tax_exempt' ));
    
      echo '</div>';
    }
    
    add_action( 'woocommerce_checkout_update_order_review', 'taxexempt_checkout_update_order_review');
    function taxexempt_checkout_update_order_review( $post_data ) {
      global $woocommerce;
    
      $woocommerce->customer->set_is_vat_exempt(FALSE);
    
      parse_str($post_data);
    
      if ( isset($shipping_method_tax_exempt) && $shipping_method_tax_exempt == '1')
        $woocommerce->customer->set_is_vat_exempt(true);                
    }
    

    The key here is understanding that any field with a name that starts with shipping_method is going to inherit this updating order functionality (which was the part that didn’t work for me). I found this answer at http://www.affectivia.com/blog/have-a-checkbox-on-the-checkout-page-which-updates-the-order-totals/

  3. After a long search I found that there is a method for the cart object called remove_taxes() .
    So, after setting a user meta for the tax exempt users, this cancels the tax totals.

    function remove_tax_for_exempt( $cart ) {
        global $current_user;
        $ok_taxexp = get_the_author_meta( 'granted_taxexempt', $current_user->ID );
        if ($ok_taxexp){ // now 0 the tax if user is tax exempt
            $cart->remove_taxes();
        }
        return $cart;
    } 
    add_action( 'woocommerce_calculate_totals', 'remove_tax_for_exempt' );
    
  4. Because $cart->remove_taxes(); is deprecated. This is what I used instead.

    I didn’t have a form on the frontend, but have a user roll that is tax exempt. This was my solution.

    Also worth noting that set_is_vat_exempt(true) also works in the US to set as tax exempt.

    /**
     * Set customer as tax exempt if user is a wholesale customer
     */
    function remove_tax_for_exempt( $cart ) {
        global $woocommerce;
    
        if ( is_user_logged_in() && current_user_can( 'wholesale_customer' ) ) {
            $woocommerce->customer->set_is_vat_exempt(true);
        }
        return $cart;
    } 
    add_action( 'woocommerce_calculate_totals', 'remove_tax_for_exempt' );
    
  5. Since this answer still pops up on google, I thought I’d share that setting the customer as tax exempt only works during checkout, if you need to edit the order on the back-end after it is placed and use the “recalculate” button, the taxes will still appear. Fortunately there is a hook for this as well:

    function remove_tax_for_exempt($exempt, $order){
        return $exempt || user_can($order->get_user_id(), 'wholesale_customer');
    }
    
    add_filter('woocommerce_order_is_vat_exempt', 'remove_tax_for_exempt', 10, 2);