skip to Main Content

I need to set a different tax class for company whose field nip is different than polish in WooCommerce

I have in my checkout field nip, and I want the tax to change to 0% after entering the tax number, e.g. RO123456789. I have 2 class tax Standard and zero rate if I have nip PL123456789 I want the rate to be standard.

i have this code and this didn’t work and I don’t know why.Any guidance on resolving this issue would be highly appreciated.

// Add the Tax Identification Number field at checkout
add_action( 'woocommerce_after_order_notes', 'custom_add_nip_field' );

function custom_add_nip_field( $checkout ) {
    echo '<div id="custom_nip_field"><h2>' . __('Dane firmy') . '</h2>';

    woocommerce_form_field( 'vat_nip', array(
        'type'          => 'text',
        'class'         => array('vat-nip-field form-row-wide'),
        'label'         => __('Numer NIP (dla firm z UE)'),
        'placeholder'   => __('Wpisz numer VAT UE'),
    ), $checkout->get_value( 'vat_nip' ));

    echo '</div>';
}

// NIP from field to checkout
add_action( 'woocommerce_checkout_update_order_meta', 'custom_save_nip_field' );

function custom_save_nip_field( $order_id ) {
    if ( ! empty( $_POST['vat_nip'] ) ) {
        update_post_meta( $order_id, '_vat_nip', sanitize_text_field( $_POST['vat_nip'] ) );
    }
}
// Apply 0% VAT for companies from outside Poland based on the NIP number
add_action( 'woocommerce_cart_calculate_fees', 'custom_apply_vat_exemption_based_on_nip' );

function custom_apply_vat_exemption_based_on_nip() {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }

    // Download the Tax Identification Number from the field at the checkout
    $vat_nip = isset( $_POST['vat_nip'] ) ? sanitize_text_field( $_POST['vat_nip'] ) : '';

    // Check if the NIP does not start with "PL"
    if ( ! empty( $vat_nip ) && substr( $vat_nip, 0, 2 ) !== 'PL' ) {
        // Assign a 'zero rate' tax class to the products in your cart
        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
            $cart_item['data']->set_tax_class( 'zero rate' ); // set tax zero rate (0% VAT)
        }
    }
}

I try some plugins but didn’t work as I expect.

2

Answers


  1. Chosen as BEST ANSWER

    Thanks for code, I would never be able to do it looking at it.

    You could target the billing country code instead of targeting the first 2 characters from the VAT code.

    How could I do that?


  2. There are some mistakes and missing things in your current code. JavaScript, Ajax and WooCommerce Sessions are required.

    The following code will work with Classic Checkout and is compatible High Performance Order Storage:

    // Display a custom input field on checkout
    add_action( 'woocommerce_after_order_notes', 'display_custom_vat_nip_input_field' );
    function display_custom_vat_nip_input_field( $checkout ) {
        echo '<div id="custom_nip_field">
        <h2>' . esc_html__('Dane firmy') . '</h2>';
    
        woocommerce_form_field( 'vat_nip', array(
            'type'          => 'text',
            'class'         => array('vat-nip-field form-row-wide'),
            'label'         => esc_html__('Numer NIP (dla firm z UE)'),
            'placeholder'   => esc_html__('Wpisz numer VAT UE'),
        ), $checkout->get_value( 'vat_nip' ));
    
        echo '</div>';
    }
    
    // Save custom checkout field value (compatible with HPOS)
    add_action( 'woocommerce_checkout_create_order', 'save_custom_vat_nip_field_value' );
    function save_custom_vat_nip_field_value( $order ) {
        if ( isset($_POST['vat_nip']) && ! empty($_POST['vat_nip']) ) {
            $order->update_meta_data('_vat_nip', sanitize_text_field($_POST['vat_nip']) );
        }
    }
    
    // Javascript / Ajax
    add_action( 'woocommerce_checkout_init', 'checkout_vat_code_js' );
    function checkout_vat_code_js() {
        wc_enqueue_js("if (typeof wc_checkout_params === 'undefined') {
            return false;
        }
    
        $('#vat_nip').on('input', function() {
            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': 'change_tax_rate',
                    'vat_nip': $(this).val()
                },
                success: function (response) {
                    $(document.body).trigger('update_checkout');
                }
            });
        });");
    }
    
    // Get Ajax request and saving Vat code value to a WC Session variable
    add_action( 'wp_ajax_change_tax_rate', 'set_vat_nip_to_wc_session' );
    add_action( 'wp_ajax_nopriv_change_tax_rate', 'set_vat_nip_to_wc_session' );
    function set_vat_nip_to_wc_session() {
        if ( isset($_POST['vat_nip'])  ) {
            WC()->session->set('vat_nip', sanitize_text_field($_POST['vat_nip']));
        }
        wp_die();
    }
    
    // Set Zero tax rate based on VAT code
    add_action( 'woocommerce_before_calculate_totals', 'custom_apply_vat_exemption_based_on_nip', 20 );
    function custom_apply_vat_exemption_based_on_nip( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
            return;
        }
        // Get VAT Code from WC Session
        $vat_nip = WC()->session->get('vat_nip');
    
        // Check that the vat code starts with "PL"
        if ( ! empty( $vat_nip ) && strtoupper( substr( $vat_nip, 0, 2 ) ) !== 'PL' ) {
            // Loop through cart items
            foreach ( $cart->get_cart() as $item ) {
                $item['data']->set_tax_class('zero-rate');
            }
        }
    }
    

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


    You could target the billing country code instead of targeting the first 2 characters from the VAT code.

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