1
votes

I'm trying to change the price for a specific product so that it shows the price with VAT (as opposed to other products where the price is shown without VAT)

I have managed to get this to work with the variable products themselves, by using the following code from https://tomjesch.com/display-woocommerce-products-with-and-without-tax/

function edit_selected_variation_price( $data, $product, $variation ) {
    if(is_singular('product') && $product->get_id() == 68719 ) {
    $price = $variation->price;
    $price_incl_tax = $price + round($price * ( 20 / 100 ), 2);  
    $price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
    $price = number_format($price, 2, ",", ".");
        $display_price = '<span class="price">';
        $display_price .= '<span class="amount">£ ' . $price_incl_tax .'<small class="woocommerce-price-suffix"> incl VAT</small></span>';
        $display_price .= '</span>';
    $data['price_html'] = $display_price;
    }
    return $data;
}
add_filter( 'woocommerce_available_variation', 'edit_selected_variation_price', 10, 3);

This works when an option is chosen. However, before an option is chosen, there is a price that says FROM: £xxx which I now also want to change to say "FROM: £xxx inc VAT"

However, I can't seem to do anything to change it. So I have added the following to setup the html for the price:

function cw_change_product_html( $price_html, $product ) {
 if ( $product->get_id() == 68719 ) {
     $price_incl_tax = $product->price + round($price * ( 20 / 100 ), 2);  
    $price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
 $price_html = '<span class="amount">From ' . $price_incl_tax . 'incl VAT</span>';
 }
 echo $price_html;
}

And then I tried using these three different hooks.

add_filter( 'woocommerce_get_price_html_from_to', 'cw_change_product_html', 10, 2 );
add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
add_filter('woocommerce_variable_price_html', 'cw_change_product_html', 10, 2);

Only the second one seems to trigger the code but then it outputs all of the prices for all the different variants.

Do I need to use a different hook or is there a way I can run the above code once?

2

2 Answers

1
votes

There are some mistakes in your code. woocommerce_variable_price_html is best hook to be used. Also instead of using custom tax calculations, you can use WC_Tax methods to get dynamically the tax amount. Finally wc_price() is the formatted price function to be used in WooCommerce.

The code:

add_filter( 'woocommerce_variable_price_html', 'filter_wc_variable_price_html', 10, 2 );
function filter_wc_variable_price_html( $price_html, $product ) {
    // only for variable product 68719
    if( $product->get_id() != 68719 )
        return $price_html;

    $min_price = $product->get_variation_price( 'min' );
    $tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
    $taxes     = WC_Tax::calc_tax( $min_price, $tax_rates, false );

    return sprintf(
        __( 'From %s %s', 'woocommerce' ),
        wc_price( $min_price + array_sum( $taxes ) ),
        '<small class="woocommerce-price-suffix">' . __( 'incl VAT', 'woocommerce' ) . '</small>'
    );
}

As your other code is a bit outdated and complicated, you can try the following instead:

add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_price_html', 10, 3);
function filter_wc_available_variation_price_html( $data, $product, $variation ) {
    // only for variable product 68719
    if( $product->get_id() != 68719 )
        return $data;

    $price     = $data['display_price'];
    $tax_rates = WC_Tax::get_rates( $variation->get_tax_class() );
    $taxes     = WC_Tax::calc_tax( $price, $tax_rates, false );

    $data['price_html'] = sprintf( '%s %s',
        wc_price( $price + array_sum( $taxes ) ),
        '<small class="woocommerce-price-suffix">' . __( 'incl VAT', 'woocommerce' ) . '</small>'
    );

    return $data;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

1
votes

You are calling the right hook (woocommerce_get_price_html) but there are several flaws in your code.

  1. Lets address your problem of running the code only for the price display at the top. Make sure the id you are checking for is the parent id.

  2. Don't access values of the product object directly. WooCommerce provides getter functions for a lot of data. So instead use $product->get_price().

  3. You have an undefined variable $price which will crash your code.

  4. You can retrieve the tax percentage of the parent product, instead of hard coding it into the calculation in your function.

  5. You can use the wc_price() function to output a formatted price.

The final code should look something like this:

add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
function cw_change_product_html( $price_html, $product ) {

     if ( $product->get_id() == 68719 ) {
        $tax_rates = WC_Tax::get_rates( $product->get_tax_class() );

        //Check the product tax rate of parent
        if ( !empty( $tax_rates ) ) {
            $tax_rate = reset($tax_rates);
            $price_incl_tax =  $product->get_price() + ( $product->get_price() * $tax_rate['rate'] / 100 );
            $price_html = sprintf( 'From %s incl VAT', wc_price( $price_incl_tax, array( 'currency' => get_woocommerce_currency() ) ) );
        }
     
    }
    
    return $price_html;
}