Reflect default price and strikethrough in cart item price in WooCommerce - php

I have added a progressive pricing based on the quantity of each cart item. What I am struggling with, is to reflect the $default_price from the product (instead the now manually added price) and also to set the layout of the new price like this (default_price has strikethrough):
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart->get_cart() as $item ) {
$quantity = $item['quantity'];
$discount_price = 0.008333333333;
$default_price = 4.25;
$minimum = 10;
$maximum = 100;
if( $quantity > $minimum ) {
if( $quantity > $maximum ) {
$new_price = $default_price - ($discount_price * ($maximum - $minimum));
}
else {
$new_price = $default_price - ($discount_price * ($quantity - $minimum));
}
$item['data']->set_price( '<del>' . $default_price . '</del> <strong>' . $new_price . '</strong>');
}
}
}
The coded $item['data']->set_price( '<del>' . $default_price . '</del> <strong>' . $new_price . '</strong>'); is wrong, but how do I reflect this so it can accept the html elements?

For what you wish to obtain you can use the following:
While the woocommerce_before_calculate_totals action hook is used to calculate totals
The woocommerce_cart_item_price filter hook ensures the strikethrough of the original price.
explanation via comment tags added in the code
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Settings
$discount_price = 0.008333333333;
$minimum = 10;
$maximum = 100;
// Iterating though each cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Product quantity in cart
$quantity = $cart_item['quantity'];
// Quantity greater than minimum
if ( $quantity > $minimum ) {
// Default price
$default_price = $cart_item['data']->get_price();
// Quantity greater than maximum
if ( $quantity > $maximum ) {
$new_price = $default_price - ( $discount_price * ( $maximum - $minimum ) );
} else {
$new_price = $default_price - ( $discount_price * ( $quantity - $minimum ) );
}
// Set price
$cart_item['data']->set_price( $new_price );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
function filter_woocommerce_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
// Get the product object
$product = $cart_item['data'];
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get reqular price
$regular_price = $product->get_regular_price();
// New price
$new_price = $cart_item['data']->get_price();
// NOT empty and NOT equal
if ( ! empty ( $regular_price ) && $regular_price != $new_price ) {
// Output
$price_html = '<del>' . wc_price( $regular_price ) . '</del> <ins>' . wc_price( $new_price ) . '</ins>';
}
}
return $price_html;
}
add_filter( 'woocommerce_cart_item_price', 'filter_woocommerce_cart_item_price', 10, 3 );

Related

Hide coupon discount raw if no coupon has been applied on WooCommerce cart page

I add coupons and discounts total savings to my cart page. My code works fine but I have an additional question.
This is the code I am currently using:
add_action( 'woocommerce_cart_totals_before_shipping', 'show_total_discount_cart_checkout', 9999 );
function show_total_discount_cart_checkout() {
global $woocommerce;
$discount_total = 0;
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$product = $values['data'];
if ( $product->is_on_sale() ) {
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
$discount = ( $regular_price - $sale_price ) * $values['quantity'];
$regular_total = $regular_price * $values['quantity'];
$discount_total += $discount;
}
}
if ( $discount_total > 0 ) {
echo '
<tr><th colspan="2">You will save '. wc_price( $woocommerce->cart->subtotal - $woocommerce->cart->total + $woocommerce->cart->shipping_total*1.23 + $discount_total ) .'</td></tr>
<tr><th class="smalltl">Price normal</th><td data-title="Poupa" class="smalltot">'. wc_price( $regular_total ) .'</td></tr>
<tr><th class="smalltl">Dicsount Pack</th><td data-title="Poupa" class="smalltot">-'. wc_price( $discount_total ) .'</td></tr>
<tr><th class="smalltl">Discount Cupon</th><td data-title="Poupa" class="smalltot">-'. wc_price( $woocommerce->cart->subtotal - $woocommerce->cart->total + $woocommerce->cart->shipping_total*1.23 ) // need to hide this tr when there i no coupon applied
.'</td></tr>
';
}
}
Currently: if no coupons are applied, it shows 0.
My question: How can I hide the table output when 0 is displayed?
You could use WC_Cart::get_applied_coupons() and when NOT empty.
I've cleaned up your code and rewritten it a little bit
So you get:
function show_total_discount_cart_checkout() {
// Counter
$discount_total = 0;
// WC Cart
if ( WC()->cart ) {
// Get cart
$cart = WC()->cart;
// If cart is NOT empty
if ( ! $cart->is_empty() ) {
// Loop through cart items and calculate total volume
foreach( $cart->get_cart() as $cart_item ) {
// Get product
$product = $cart_item['data'];
// On sale
if ( $product->is_on_sale() ) {
// Getters
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
$quantity = $cart_item['quantity'];
// Calculations
$discount = ( $regular_price - $sale_price ) * $quantity;
$regular_total = $regular_price * $quantity;
$discount_total += $discount;
}
}
}
}
// Greater than
if ( $discount_total > 0 ) {
// Getters
$subtotal = $cart->get_subtotal();
$total = $cart->total;
$shipping_total = $cart->shipping_total;
// Output
echo '<tr><th colspan="2">You will save ' . wc_price( $subtotal - $total + $shipping_total * 1.23 + $discount_total ) . '</td></tr>';
echo '<tr><th class="smalltl">Price normal</th><td data-title="Poupa" class="smalltot">' . wc_price( $regular_total ) . '</td></tr>';
echo '<tr><th class="smalltl">Dicsount Pack</th><td data-title="Poupa" class="smalltot">-' . wc_price( $discount_total ) . '</td></tr>';
// Get applied coupons
$coupon_applieds = $cart->get_applied_coupons();
// NOT Empty coupon applieds
if ( ! empty ( $coupon_applieds ) ) {
echo '<tr><th class="smalltl">Discount Cupon</th><td data-title="Poupa" class="smalltot">-' . wc_price( $subtotal - $total + $shipping_total * 1.23 ) . '</td></tr>';
}
}
}
add_action( 'woocommerce_cart_totals_before_shipping', 'show_total_discount_cart_checkout', 10, 0 );

Display the discounted percentage under regular price & sale price in Variation products pages for WC 3.0+ [duplicate]

This question already has an answer here:
Display the discounted percentage near sale price in Single product pages for WC 3.0+
(1 answer)
Closed 3 years ago.
I want to show the discount sale percentage under the prices (regular and sale prices).
There is a very close solution to that in the post:
Display the discounted percentage near sale price in Single product pages for WC 3.0+
But the problem is that it changes the price.
Before the code appears like this:
And after the code like this:
As you can see the decimals disappeared and the percentage is not correct as it should show 15% Price 55€-15% off --> 46,75€
The code used:
add_filter( 'woocommerce_format_sale_price', 'woocommerce_custom_sales_price', 10, 3 );
function woocommerce_custom_sales_price( $price, $regular_price, $sale_price ) {
// Getting the clean numeric prices (without html and currency)
$regular_price = floatval( strip_tags($regular_price) );
$sale_price = floatval( strip_tags($sale_price) );
// Percentage calculation and text
$percentage = round( ( $regular_price - $sale_price ) / $regular_price * 100 ).'%';
$percentage_txt = __(' Save ', 'woocommerce' ).$percentage;
return '<del>' . wc_price( $regular_price ) . '</del> <ins>' . wc_price( $sale_price ) . $percentage_txt . '</ins>';
}
My expected result would be something like this, but can't find the way to do it.
I've been reading a lot of posts about it but couldn't find the right solution. My apologies if I duplicate the post. Thank you
Update 08/24/2019 Solved
I finally solved the problem and got the result as i wanted after some research in toher websites. I leave here the code i used so anyone can use it too.
add_action( 'woocommerce_single_product_summary',
'porcentaje_ahorro_ficha_producto', 12 );
function porcentaje_ahorro_ficha_producto() {
global $product;
if ( ! $product->is_on_sale() ) return;
if ( $product->is_type( 'simple' ) ) {
$max_percentage = ( ( $product->get_regular_price() - $product-
>get_sale_price() ) / $product->get_regular_price() ) * 100;
} elseif ( $product->is_type( 'variable' ) ) {
$max_percentage = 0;
foreach ( $product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id );
$price = $variation->get_regular_price();
$sale = $variation->get_sale_price();
if ( $price != 0 && ! empty( $sale ) ) {
$percentage = ( $price - $sale ) / $price * 100;
}
if ( $percentage > $max_percentage ) {
$max_percentage = $percentage;
}
}
}
if ( $max_percentage > 0 ) echo "<div class='porcentaje-ahorro'>-" .
round($max_percentage) . "%</div>";
}
Then I did some css and that's all. thank you all for your support.
You can add the follows code snippet with exact prices -
function add_discount_woocommerce_format_sale_price( $price, $regular_price, $sale_price ){
$percentage = round( ( $regular_price - $sale_price ) / $regular_price * 100 ).'%';
$price = '<del>' . ( is_numeric( $regular_price ) ? wc_price( $regular_price ) : $regular_price ) . '</del> <ins>' . ( is_numeric( $sale_price ) ? wc_price( $sale_price ) : $sale_price ) . '</ins> <sup>' . $percentage . __( ' save', 'text-domain' ) . '</sup>';
return $price;
}
add_filter( 'woocommerce_format_sale_price', 'add_discount_woocommerce_format_sale_price', 99, 3 );
But if you want the exact same styling then you have to do some styling over there.

Display variable product discounted percentage only on Woocommerce archive pages

I'd like to display the percentage variable products are discounted in the archive pages. With the code below, I was able to get both the discounts % on variable products but also for simple products. Can I do this ONLY for variable products and not simple products? I realize it's probably a simple adjustment in the code but I can't figure it out because I'm an idiot when it comes to PHP.
add_action( 'woocommerce_after_shop_loop_item', 'show_sale_percentage', 25 );
function show_sale_percentage() {
global $product;
if ( $product->is_on_sale() ) {
if ( ! $product->is_type( 'variable' ) ) {
$max_percentage = ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100;
} else {
$max_percentage = 0;
foreach ( $product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id );
$price = $variation->get_regular_price();
$sale = $variation->get_sale_price();
if ( $price != 0 && ! empty( $sale ) ) $percentage = ( $price - $sale ) / $price * 100;
if ( $percentage > $max_percentage ) {
$max_percentage = $percentage;
}
}
}
echo "<div class='saved-sale'>-" . round($max_percentage) . "%</div>";
}
}
To display the on sale percentage, on archives pages, for variable products only, try the following:
add_action( 'woocommerce_after_shop_loop_item', 'loop_variable_product_sale_percentage', 25 );
function loop_variable_product_sale_percentage() {
global $product;
if ( $product->is_on_sale() && $product->is_type( 'variable' ) ) {
$max_percentage = 0;
foreach ( $product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id );
$percentage = 0;
$price = $variation->get_regular_price();
$sale = $variation->get_sale_price();
if ( $price != 0 && ! empty( $sale ) ) {
$percentage = ( $price - $sale ) / $price * 100;
}
if ( $percentage > $max_percentage ) {
$max_percentage = $percentage;
}
}
echo '<div class="saved-sale">-' . round($max_percentage) . '%</div>';
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Replace on sale product price with saving amount and percentages in Woocommerce

I use some code that shows the discounted price on Woocommerce archive pages for on sale products:
add_filter( 'woocommerce_get_price_html', 'display_savings_as_price_and_percentage', 10, 2 );
//add_filter( 'woocommerce_variable_price_html','display_savings_as_price_and_percentage', 10, 2 );
function display_savings_as_price_and_percentage( $price, $product ) {
if( $product->is_on_sale() && ! is_admin() && ! $product->is_type('variable')){
$product_price = (float) $product->get_regular_price();
$sale_price = (float) $product->get_price();
$save_price = wc_price( $product_price - $sale_price );
$save_percentage = round( 100 - ( $sale_price / $product_price * 100 ), 1 ) . '%';
$price .= sprintf( __('<p class="saved-on-sale">Save: %s (%s)</p>', 'woocommerce' ), $save_price, $save_percentage );
}
return $price;
}
Discount on archives pages:
But it doesn't work for variable products and I've tried with every hook I've found but I cannot figure out how to make it work variable products.
(I commented out the hook for the variable in my code).
This is what I would like to have:
If the variable has a price span of 10-20 with a discount making it 10-15 I would like for that to be displayed like this with the default price striked through:
$40 - $50
$20 - $30
Save: $20 (40-50%)
How can I replace the on sale product price for variable products with saving amount and percentages?
The following code will handle both simple and variable on sale products:
add_filter( 'woocommerce_get_price_html', 'display_savings_price_and_percentages', 20, 2 );
function display_savings_price_and_percentages( $price_html, $product ) {
// Only on frontend and for on sale products
if( is_admin() || ! $product->is_on_sale() )
return $price_html;
// Only on archives pages
if( ! ( is_shop() || is_product_category() || is_product_tag() ) )
return $price_html;
// Variable product type
if( $product->is_type('variable')){
$percentages = $savings = array(); // Initializing
// Get all variation prices
$prices = $product->get_variation_prices();
// Loop through variation prices
foreach( $prices['price'] as $key => $price ){
// Only on sale variations
if( $prices['regular_price'][$key] !== $price ){
// Calculate and set in the array the percentage for each variation on sale
$percentages[] = round(100 - ($prices['sale_price'][$key] / $prices['regular_price'][$key] * 100), 1 );
// Calculate and set in the array the savings for each variation on sale
$savings[] = $prices['regular_price'][$key] - $prices['sale_price'][$key];
}
}
$save_price = wc_price( max($savings) );
if( min($percentages) !== max($percentages) ){
$save_percentage = min($percentages) . '-' . max($percentages) . '%';
$save_text = __( 'Save up to:', 'woocommerce' );
} else {
$save_percentage = max($percentages) . '%';
$save_text = __( 'Save:', 'woocommerce' );
}
}
// All other product types
else {
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
$save_price = wc_price( $regular_price - $sale_price );
$save_percentage = round( 100 - ( $sale_price / $regular_price * 100 ), 1 ) . '%';
$save_text = __( 'Save:', 'woocommerce' );
}
return '<p class="saved-on-sale">' . sprintf( '%s %s (%s)', $save_text, $save_price, $save_percentage ) . '</p>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Set product variation custom calculated price dynamically in WooCommerce

I am trying to dynamically add to a products price when a user checks out based on what they have entered in the product page. The setting of the price is only working on a non variation product.
I need to be able to set the price on the variations of the products as well.
The code that I am using:
function add_cart_item_data( $cart_item_meta, $product_id, $variation_id ) {
$product = wc_get_product( $product_id );
$price = $product->get_price();
$letterCount = strlen($_POST['custom_name']);
$numberCount = strlen($_POST['custom_number']);
if($letterCount != '0') {
$letterPricing = 20 * $letterCount;
$numberPricing = 10 * $numberCount;
$additionalPrice = $letterPricing + $numberPricing;
$cart_item_meta['custom_price'] = $price + $additionalPrice;
}
return $cart_item_meta;
}
function calculate_cart_total( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
foreach ( $cart_object->cart_contents as $key => $value ) {
if( isset( $value['custom_price'] ) ) {
$price = $value['custom_price'];
$value['data']->set_price( ( $price ) );
}
}
}
I have completely revisited your code:
// Set custom data as custom cart data in the cart item
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_data_to_cart_object', 30, 3 );
function add_custom_data_to_cart_object( $cart_item_data, $product_id, $variation_id ) {
if( ! isset($_POST['custom_name']) || ! isset($_POST['custom_number']) )
return $cart_item_data; // Exit
if( $variation_id > 0)
$product = wc_get_product( $variation_id );
else
$product = wc_get_product( $product_id );
$price = $product->get_price();
// Get the data from the POST request and calculate new custom price
$custom_name = sanitize_text_field( $_POST['custom_name'] );
if( strlen( $custom_name ) > 0 )
$price += 20 * strlen( $custom_name );
$custom_number = sanitize_text_field( $_POST['custom_number'] );
if( strlen( $custom_number ) > 0 )
$price += 10 * strlen( $custom_number );
// Set new calculated price as custom cart item data
$cart_item_data['custom_data']['price'] = $price;
return $cart_item_data;
}
// Set the new calculated price of the cart item
add_action( 'woocommerce_before_calculate_totals', 'set_new_cart_item_price', 50, 1 );
function set_new_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
foreach ( $cart->get_cart() as $cart_item ) {
if( isset( $cart_item['custom_data']['price'] ) ) {
// Get the new calculated price
$new_price = (float) $cart_item['custom_data']['price'];
// Set the new calculated price
$cart_item['data']->set_price( $new_price );
}
}
}
This code goes on function.php file of your active child theme (or theme).
Tested and works as well with product variations.

Categories