prices in my shop are displayed with tax and also I'm using {price_excluding_tax} suffix to display also price excluding tax. But there is a problem with variable products... The shop shows only prices including tax (and the old price in case of promotion) but it doesn't shows the price excluding tax. Prices for both variable products are the same. I tried to use this code:
https://tomjesch.com/display-woocommerce-products-with-and-without-tax/
But it doesn't work properly - it shows prices, but does not react to any price change in the woocommerce admin panel. So, it works fine only when adding a new product.
Thanks in advance...
My code:
function edit_price_display() {
$product = WC_Product( get_the_ID() );
$regular_price = $product ->regular_price;
$price = $product->price;
$price_incl_tax = $price + round( $price * ( 23 / 100 ), 2 );
$price_incl_tax = number_format( $price_incl_tax, 2, ",", "" );
$price = number_format( $price, 2, ",", "" );
$display_price = '<ins><span class="woocommerce-Price-amount amount">';
$display_price .= ' '.$price_incl_tax .'<span class="woocommerce-Price-currencySymbol"> zł</span>';
$display_price .= '</span></ins> ';
$display_price .= '<small class="woocommerce-price-suffix">(netto: <span class="woocommerce-Price-amount amount">'.$price .' <span class="woocommerce-Price-currencySymbol">zł</span></span>)</small>';
$display_price .= '';
$display_regular_price ='<del><span class="woocommerce-Price-amount amount">'.$regular_price .'<span class="woocommerce-Price-currencySymbol"> zł</span></span></del>';
if($product->is_on_sale()) {
echo $display_regular_price;
}
echo $display_price;
}
add_filter('woocommerce_variable_price_html', 'edit_price_display');
Bear in mind Woocommerce developers comment about that feature:
https://github.com/woocommerce/woocommerce/issues/14839
But if you need achive such reasult, you can do that in this way:
add_filter( 'woocommerce_get_price_html', 'my_price_prefix_suffix', 100, 2 );
function my_price_prefix_suffix( $price, $product ){
// To add suffix, go to /wp-admin/admin.php?page=wc-settings&tab=tax
if($product->is_type( 'variable' ) && $product->is_in_stock()){
$price = $price . '('.wc_price($product->get_variation_regular_price()* 1.23).' z Vat)';
}
return apply_filters( 'woocommerce_get_price', $price );
}
Code is tested an working as expected.
Related
I try to manipulate the calculated price in cart but with no luck...
I hope someone can help me here.
I have found this article and implemented the code as written on the Page which is to 98% exactly what i searched for. I need to add a cart calculation if the price type is per 100g.
So this is the actual working code:
add_filter( 'woocommerce_get_price_html', 'wb_change_product_html', 10, 2 );
// Adding a custom field to the price markup
function wb_change_product_html( $price, $product ) {
//$wb_price_type = get_field('product_price_type');
$wb_price_type = get_post_meta( $product->get_id(), 'product_price_type', true);
if($wb_price_type) {
$price_html = '<span class="amount">' . $price . ' ' . $wb_price_type . '</span>';
}
else {
$price_html = '<span class="amount">' . $price . '</span>';
}
return $price_html;
}
add_filter( 'woocommerce_cart_item_price', 'wb_change_product_price_cart', 10, 3 );
// Adding a custom field to the price in the cart
function wb_change_product_price_cart( $price, $cart_item, $cart_item_key ) {
//$wb_price_type = get_field( 'product_price_type', $cart_item['product_id'] );
$wb_price_type = get_post_meta( $cart_item['product_id'], 'product_price_type', true );
if ($wb_price_type) {
$price = $price . ' ' . $wb_price_type;
}
else {
$price = $price;
}
return $price;
}
add_filter( 'woocommerce_checkout_cart_item_quantity', 'wb_checkout_review', 10, 3 );
// Adding a custom field to the price in the checkout items
function wb_checkout_review ( $quantity, $cart_item, $cart_item_key ) {
//$wb_price_type = get_field( 'product_price_type', $cart_item['product_id'] );
$wb_price_type = get_post_meta( $cart_item['product_id'], 'product_price_type', true);
if ( $wb_price_type ) {
$cart_item = ' ' . sprintf( '× %s ', $cart_item['quantity'] ) . $wb_price_type . '';
}
else {
$cart_item = ' ' . sprintf( '× %s', $cart_item['quantity'] ) . '';
}
return $cart_item;
}
Well i thought its really easy to calculate so i do something like this:
add_filter( 'woocommerce_cart_item_price', 'wb_change_product_price_cart', 10, 3 );
// Adding a custom field to the price in the cart
function wb_change_product_price_cart( $price, $cart_item, $cart_item_key ) {
//$wb_price_type = get_field( 'product_price_type', $cart_item['product_id'] );
$wb_price_type = get_post_meta( $cart_item['product_id'], 'product_price_type', true );
if ($wb_price_type) {
if ($wb_price_type == "per 100g") {
$price = $price / 100 . ' ' . $wb_price_type;
}
else {
$price = $price . ' ' . $wb_price_type;
}
}
else {
$price = $price;
}
return $price;
}
But this didnt work... i too try to manipulate the price directly but i get anytime 0 in the value of the price...
so i google a little bit more and found this article, which makes in the end exactly what i want. in the last print screen we can see that the price will displayed per kg (which is completely fine) and in the calculation it uses an other price (which i try to do with the code above).
i think that the problem is that $price has for example the value "20$" and this is a string and i cannot calculate withe a string. And it makes no sense to split this string there should be an other way.
For better understanding here a picture. in the upper part we see the working calculation (which is good) but this is not exactly what i need. in the part down we see that it will only calculate on the calculated price (right side). the left side of the downer part remain with the correct price.
i think that the problem is that $price has for example the value "20$" and this is a string and i cannot calculate withe a string. And it makes no sense to split this string there should be an other way.
This is true, it's actually a full html string. Try changing the woocommerce_cart_item_price filter to get the price out of string:
add_filter('woocommerce_cart_item_price', 'wb_change_product_price_cart', 10, 3);
// Adding a custom field to the price in the cart
function wb_change_product_price_cart($price, $cart_item, $cart_item_key)
{
$wb_price_type = get_post_meta($cart_item['product_id'], 'product_price_type', true);
if ($wb_price_type) {
if ($wb_price_type == "per 100g") {
preg_match("/([0-9]+\.[0-9]+)/", $price, $matches);
$_price = $matches[0];
$per100 = $_price / 100;
$price = $per100 . ' ' . $wb_price_type;
} else {
$price = $price . ' ' . $wb_price_type;
}
} else {
$price = $price;
}
return $price;
}
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?
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.
You are calling the right hook (woocommerce_get_price_html) but there are several flaws in your code.
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.
Don't access values of the product object directly. WooCommerce provides getter functions for a lot of data. So instead use $product->get_price().
You have an undefined variable $price which will crash your code.
You can retrieve the tax percentage of the parent product, instead of hard coding it into the calculation in your function.
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;
}
I am having a custom plugin which is used to show accessories. I want to display total savings of main product and accessories combined. my saving works if the main product is simple if the main product is variable the savings shows null. can someone update my code, please
I tried this code to show saving but it is just working for simple products
function you_save_echo_product() {
global $product;
// works for Simple and Variable type
$regular_price = get_post_meta( $product->get_id(), '_regular_price', true ); // 36.32
$sale_price = get_post_meta( $product->get_id(), '_sale_price', true ); // 24.99
if( !empty($sale_price) ) {
$saved_amount = $regular_price - $sale_price;
$currency_symbol = get_woocommerce_currency_symbol();
$percentage = round( ( ( $regular_price - $sale_price ) / $regular_price ) * 100 );
?>
<p id="saving_total_price">You Save: <span class="symbol"><?php echo $currency_symbol; ?></span> <span class="amount"><?php echo $saved_amount; ?></span>.00</p>
<?php
}
}
add_action( 'woocommerce_single_product_summary', 'you_save_echo_product', 11 );
I expect to show total savings for my accessories with the main product as a variable
I have revisited your code as it's is a bit outdated and old… On variable products there is 2 prices, a price range and the selected variation price, so you need something completely different to display the saving amount of the selected variation price.
I have added also the saving percentage (that you can remove if you don't need it).
// For simple products
add_action( 'woocommerce_single_product_summary', 'simple_product_saving_amount', 11 );
function simple_product_saving_amount() {
global $product;
if( $product->is_type('simple') && $product->is_on_sale() ) {
$regular_price = (float) wc_get_price_to_display( $product, array('price' => $product->get_regular_price() ) );
$active_price = (float) wc_get_price_to_display( $product, array('price' => $product->get_sale_price() ) );
$saved_amount = $regular_price - $active_price;
$percentage = round( $saved_amount / $regular_price * 100 );
echo '<p id="saving_total_price">'. __("You Save") .': ' . wc_price($saved_amount) . ' ('.$percentage.'%)</p>';
}
}
// For product variations (on variable products)
add_filter( 'woocommerce_available_variation', 'variable_product_saving_amount', 10, 3 );
function variable_product_saving_amount( $data, $product, $variation ) {
if( $variation->is_on_sale() ) {
$saved_amount = $data['display_regular_price'] - $data['display_price'];
$percentage = round( $saved_amount / $data['display_regular_price'] * 100 );
$data['price_html'] .= '<p id="saving_total_price">'. __("You Save") .': ' . wc_price($saved_amount) . ' ('.$percentage.'%)</p>';
}
return $data;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I'm using the following script:
add_filter('woocommerce_variable_price_html', 'custom_variation_price', 10, 2);
function custom_variation_price( $price, $product ) {
$price = '';
if ( !$product->min_variation_price || $product->min_variation_price !== $product->max_variation_price ) {
$price .= '<span style="display:none;" class="not-from">v.a. ' . _x('', 'min_price', 'woocommerce') . ' </span>';
$price .= woocommerce_price($product->get_price());
}
return $price;
}
It does show the min variation price at this moment. I want to create the following:
If the min price is 0,00, then show the 2nd product variation price.
E.g.: Product X has 3 different variations: 1 (€0,00), 2 (€5,00), 3 (€15,00). If the variation price is 0,00, then show the second price variation, €5,00.
Here is the way to display the 2nd min variable price whenthe min price is equal to 0:
add_filter('woocommerce_variable_price_html', 'custom_variation_price_html', 10, 2);
function custom_variation_price_html( $price, $product ) {
// Get all variations prices
$prices = $product->get_variation_prices( true );
// Get the prices (min and max)
$min_price = current( $prices['price'] );
$max_price = end( $prices['price'] );
// Get 2nd min price
$min_price2_arr = array_slice($prices['price'], 1, 1);
$min_price2 = $min_price2_arr[0];
if ( $min_price > 0) {
$price = wc_price( $min_price );
} elseif ( $min_price == 0 ) {
$price = wc_price( $min_price2 );
}
return $price;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This is code tested and works only in WooCommerce 3+.
The product category is "Machines"
My website is: "https://www.floorcare-supplies.co.uk/product-category/machines/"
I'm looking to be able to display the products in this category specifically without the tax on the shop front.
I've managed to do it when on the products for example:
£1,342
£1123 Ex vat
But on the shop store, I need the main price to display the total without tax for that specific category.
Use this code:
/**
* Function that will check for category id and turn off VAT/tax
*/
function wc_diff_rate_for_cat() {
if (is_product_category ('machines')) {
// set the machines category to have no VAT
WC()->customer->is_vat_exempt = true;
}
}
add_action( 'template_redirect', 'wc_diff_rate_for_cat', 1 );
/**
* Function that filters the variable product hash based on category
*/
function wc_get_variation_prices_hash_filter( $hash, $item, $display ) {
// check for the "machines" category
if (is_product_category ('machines')) {
// clear key 2, which is where taxes are
$hash['2'] = array();
}
// return the hash
return $hash;
}
add_filter( 'woocommerce_get_variation_prices_hash', 'wc_get_variation_prices_hash_filter', 1, 3 );
/**
* Function that removes the price suffix (inc. Tax) from variable products based on category
*/
function wc_get_price_suffix_filter( $price_display_suffix, $item ) {
if (is_product_category ('machines')) {
// return blank if it matches
return '';
}
// return if unmatched
return $price_display_suffix;
}
add_filter( 'woocommerce_get_price_suffix', 'wc_get_price_suffix_filter', 10, 2 );
Solved
Solution
Modified Child theme to include
Woocommerce\includes\wc-template-functions.php
&
woocommerce\loop\price.php
Code added to
Woocommerce\includes\wc-template-functions.php
/**
* Get the product price for the loop.
*
* #subpackage Loop
*/
function woocommerce_template_loop_price() {
wc_get_template( 'loop/pricemod.php' );
}
Then modified pricemod.php
global $product;
$vat = "Ex vat ";
?>
<p class="price"><?php echo $product->get_price_html(); ?></p>
<p class="priceex"><?php echo woocommerce_price($product->get_price_excluding_tax()). ' ' . $vat; ?></p>
To display prices excluding tax only for your "Machines" product category, you should use a custom function hooked in wc_price filter hook, this way:
add_filter( 'wc_price', 'product_category_price_excl_tax', 10, 3 );
function product_category_price_excl_tax( $price_html, $price, $args ){
global $post;
// Price excluding taxes for "Machines" product category with corresponding label
if( has_term( 'Machines', 'product_cat', $post->ID ) ){
$decimal_separator = wc_get_price_decimal_separator();
$thousand_separator = wc_get_price_thousand_separator();
$decimals = wc_get_price_decimals();
$price_format = get_woocommerce_price_format();
$number_format = number_format( $price, $decimals, $decimal_separator, $thousand_separator );
$negative = $price < 0;
$currency = get_woocommerce_currency();
// Get an instance of the WC_Product object
$product = wc_get_product($post->ID);
// Get the product price excluding taxes
$price = wc_get_price_excluding_tax( $product, $price );
$price = apply_filters( 'raw_woocommerce_price', floatval( $negative ? $price * -1 : $price ) );
$price = apply_filters( 'formatted_woocommerce_price', $number_format, $price, $decimals, $decimal_separator, $thousand_separator );
if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $decimals > 0 )
$price = wc_trim_zeros( $price );
$formatted_price = ( $negative ? '-' : '' ) . sprintf( $price_format, '<span class="woocommerce-Price-currencySymbol">' . get_woocommerce_currency_symbol( $currency ) . '</span>', $price );
$price_html = '<span class="woocommerce-Price-amount amount">' . $formatted_price . '</span>';
if ( wc_tax_enabled() )
$price_html .= ' <small class="woocommerce-Price-taxLabel tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
}
return $price_html;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works for WooCommerce version 3+
Now, to display that prices only in "Machines" shop category archives pages, you will need to replace:
if( has_term( 'Machines', 'product_cat', $post->ID ) ){
by:
if( has_term( 'Machines', 'product_cat', $post->ID ) && is_product_category ('machines') ){