Add calculated saving total in Woocommerce order totals rows - php

In Woocommerce, I am using the following code to calculate and display 'Total Saving' on the order in Cart and checkout pages:
function wc_discount_total_30() {
global $woocommerce;
$discount_total = 0;
foreach ( $woocommerce->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'];
$discount_total += $discount;
}
}
if ( $discount_total > 0 ) {
echo '<tr class="cart-discount">
<th>'. __( 'Saved', 'tsavedis' ) .'</th>
<td data-title=" '. __( 'Saved', 'tsavedis' ) .' ">'
. wc_price( $discount_total + $woocommerce->cart->discount_cart ) .'</td>
</tr>';
}
}
// Hook our values to the Basket and Checkout pages
add_action( 'woocommerce_cart_totals_after_order_total', 'wc_discount_total_30', 99);
add_action( 'woocommerce_review_order_after_order_total', 'wc_discount_total_30', 99);
I need to display this total saving in 'Order Edit' page at backend as a custom field.
How to do that ?

Here is the way to add the same thing to orders totals table:
// Display the chosen delivery information
add_filter( 'woocommerce_get_order_item_totals', 'add_saving_total_order_totals', 10, 3 );
function add_saving_total_order_totals( $total_rows, $order, $tax_display ) {;
$saving_total = 0;
// Loop through Order items
foreach($order->get_items() as $item ){
$product = $item->get_product();
if( $product->is_on_sale() ){
$regular_price = (float) $product->get_regular_price();
$active_price = (float) $product->get_price();
$saving_total += ($regular_price - $active_price) * $item->get_quantity();
}
}
if( $saving_total > 0 ) {
$discount_total = $order->get_discount_total();
$label = __( 'Saved', 'tsavedis' );
$value = wc_price( $saving_total + $discount_total );
$total_rows['saving'] = array( 'label' => $label,'value' => $value );
}
return $total_rows;
}
Code goes in function.php file of your active child theme (or active theme). tested and works.

Related

WooCommerce specific coupon discount based on product category

I've a problem with this code to apply different percentage of discount to product in different category
The function work but is execute n times where n depends on the number of products in cart
add_filter( 'woocommerce_coupon_get_discount_amount', 'alter_shop_coupon_data', 1, 5 );
function alter_shop_coupon_data( $discount, $discounting_amount, $cart_item, $single, $instance ){
$coupons = WC()->cart->get_coupons();
$cart_items = WC()->cart->get_cart();
foreach ( $coupons as $code => $coupon ) {
if ( $coupon->discount_type == 'percent' && $coupon->code == 'newsite' ) {
foreach ($cart_items as $cart_item){
$product_id = $cart_item['data']->id;
if( has_term( 'cat1', 'product_cat', $product_id ) ){
$quantity = $cart_item['quantity'];
$price = $cart_item['data']->price;
$discount_20 = 0.2 * ($quantity * $price); // 20%
}else{
$quantity = $cart_item['quantity'];
$price = $cart_item['data']->price;
$discount_10 = 0.1 * ($quantity * $price); //10%
}
}
}
}
$discounting_amount = ($discount_20 + $discount_10);
return $discounting_amount;
}
Since WooCommerce 3, there are many mistakes in your code… Also the $cart_item argument is included in the function, so you don't need to loop through cart items.
Also note that $coupon->is_type('percent') (coupon type) is not needed as you target a specific coupon in your code: $coupon->get_code() == 'newsite.
Try the following:
add_filter( 'woocommerce_coupon_get_discount_amount', 'alter_shop_coupon_data', 100, 5 );
function alter_shop_coupon_data( $discount, $discounting_amount, $cart_item, $single, $instance ){
// Loop through applied WC_Coupon objects
foreach ( WC()->cart->get_coupons() as $code => $coupon ) {
if ( $coupon->is_type('percent') && $coupon->get_code() == 'newsite' ) {
$discount = $cart_item['data']->get_price() * $cart_item['quantity'];
if( has_term( 'cat1', 'product_cat', $cart_item['product_id'] ) ){
$discount *= 0.2; // 20%
}else{
$discount *= 0.1; // 10%
}
}
}
return $discount;
}
Code goes in functions.php file of the active child theme (or active theme). It should better work.

Custom total savings amount display issue in WooCommerce Checkout

I'm using this code snippet to display the total order savings at WooCommerce checkout:
add_action( 'woocommerce_review_order_after_order_total', 'show_total_discount_cart_checkout', 9999 );
function show_total_discount_cart_checkout() {
$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'];
$discount_total += $discount;
}
}
if ( $discount_total > 0 ) {
echo '<tr class="total-saved"><th>You Saved</th><td data-title="You Saved">' . wc_price( $discount_total + WC()->cart->get_discount_total() ) .'</td></tr>';
}
}
It should display the total amount of money a customer saved (sale prices plus coupon discounts). Screenshot: https://ibb.co/KXg2bDj
However, if there are no discounted products in the cart, the total order savings do not show up, even if there is a coupon code applied to the order. The total order savings show up only if there are discounted products in the cart. Screenshot: https://ibb.co/PCQPGZx
I would like the total order savings to show up if there is a coupon code applied to the order, if there are discounted products in the cart or if there's both. If there's neither 1 of those 2, the total order savings do not need to show up.
Could someone please help me achieve this?
Try the following instead, that will solve your issue and handle displaying tax settings:
add_action( 'woocommerce_review_order_after_order_total', 'show_total_discount_cart_checkout', 1000 );
function show_total_discount_cart_checkout() {
$discount_total = 0; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
$product = $item['data'];
if ( $product->is_on_sale() ) {
$regular_args = array( 'price' => $product->get_regular_price() );
if ( WC()->cart->display_prices_including_tax() ) {
$active_price = wc_get_price_including_tax( $product );
$regular_price = wc_get_price_including_tax( $product, $regular_args );
} else {
$active_price = wc_get_price_excluding_tax( $product );
$regular_price = wc_get_price_excluding_tax( $product, $regular_args );
}
$discount_total += ( $regular_price - $active_price ) * $item['quantity'];
}
}
if ( WC()->cart->display_prices_including_tax() ) {
$discount_total += WC()->cart->get_discount_tax();
}
$discount_total += WC()->cart->get_discount_total();
if ( $discount_total > 0 ) {
$text = __("You Saved", "woocommerce");
printf( '<tr class="total-saved"><th>%s</th><td data-title="%s">%s</td></tr>', $text, $text, wc_price($discount_total) );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

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 );

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.

WooCommerce - Transpose Cart loop in Order loop for pdf invoices

I'm using woocommerce and "Print Invoices & Packing lists"
available at "https://woocommerce.com/products/print-invoices-packing-lists/" .
For Display the Total Saving in the woocommerce cart & checkout pages I'm used this code and works perfectly :
function bbloomer_wc_discount_total() {
global $woocommerce;
$cart_subtotal = $woocommerce->cart->cart_contents;
$discount_total = 0;
foreach ($woocommerce->cart->cart_contents as $product_data) {
if ($product_data['variation_id'] > 0) {
$product = wc_get_product( $product_data['variation_id'] );
} else {
$product = wc_get_product( $product_data['product_id'] );
}
if ( !empty($product->sale_price) ) {
$discount = ($product->regular_price - $product->sale_price) * $product_data['quantity'];
$discount_total += $discount;
}
}
if ( $discount_total > 0 ) {
echo '<tr class="cart-discount">
<th>'. __( 'Total Saving :', 'woocommerce' ) .'</th>
<td data-title=" '. __( 'Total Saving :', 'woocommerce' ) .' ">'
. wc_price($discount_total+$woocommerce->cart->discount_cart) .'</td>
</tr>';
}
}
add_action( 'woocommerce_cart_totals_after_order_total', 'bbloomer_wc_discount_total');
add_action( 'woocommerce_review_order_after_order_total', 'bbloomer_wc_discount_total');
This function based in the woocommerce cart contents .
How I can Display The Total Saving in the Html Invoice generated By Print Invoices & Packing lists Plugin ( based On the Order Instead of the cart contents ) in the plugin Hooks like :
add_action( 'wc_pip_after_header', 'bbloomer_wc_discount_total');
add_action( 'wc_pip_document_header', 'bbloomer_wc_discount_total');
— Update 2 — (Added compatibility for WooCommerce version 3+)
Now as I know you are using WooCommerce PDF Invoices & Packing Slips plugin.
This code can only be used directly in invoice.php PIP template at the beginning, replacing <?php global $wpo_wcpdf ?> by this:
<?php
global $wpo_wcpdf, $woocommerce;
// Get the order object
$_order = $wpo_wcpdf->export->order;
foreach ( $_order->get_items() as $item ) {
// Added WC 3+ compatibility
$quantity = method_exists( $item, 'get_quantity' ) ? $item->get_quantity() : $item['quantity'];
$variation_id = method_exists( $item, 'get_variation_id' ) ? $item->get_variation_id() : $item['variation_id'];
$_product = version_compare( WC_VERSION, '3.0', '<' ) ? wc_get_product( $item['product_id'] ) : $item->get_product();
// Get the product object when it's a product variation ( Before version WC 3+)
if ( version_compare( WC_VERSION, '3.0', '<' ) )
if ($item['variation_id'] > 0) $_product = wc_get_product( $item['variation_id'] );
// Get prices
$sale_price = $_product->get_sale_price();
$regular_price = $_product->get_regular_price();
// Only when sale price exits
if ( ! empty( $sale_price ) && $sale_price > 0 ) {
$discount = ($regular_price - $sale_price) * $item->get_quantity();
$discount_total += $discount;
}
}
if ( $discount_total > 0 ) {
$display_discount = '<tr class="cart-discount">
<th>'. __( 'Total you saved :', 'woocommerce' ) .'</th>
<td data-title=" '. __( 'Total you saved :', 'woocommerce' ) .' ">' . wc_price( $discount_total + $_order->get_total_discount() ) .'</td>
</tr>';
}
?>
Then you can use it where you want in the template to output it, this way (inside html):
<?php echo $display_discount; ?>
Or (inside php code):
echo $display_discount;
This code is tested and works.

Categories