Progressive discount based on cart total in WooCommerce - php

I'm trying to automatically apply 3 different coupon codes in WooCommerce Cart.
Here's my code!
add_action( 'woocommerce_before_cart', 'apply_matched_coupons' );
function apply_matched_coupons() {
global $woocommerce;
$coupon_code5 = '5percent';
$coupon_code10 = '10percent';
$coupon_code55 = '15percent';
if ( $woocommerce->cart->has_discount( $coupon_code ) ) return;
if ( $woocommerce->cart->cart_contents_total >= 50 && $woocommerce->cart->cart_contents_total < 100 && $woocommerce->cart->cart_contents_total != 100 ) {
$woocommerce->cart->add_discount( $coupon_code5 );
} elseif ($woocommerce->cart->cart_contents_total >= 100 && $woocommerce->cart->cart_contents_total < 150 && $woocommerce->cart->cart_contents_total != 150 ) {
$woocommerce->cart->add_discount( $coupon_code10 );
} else {
$woocommerce->cart->add_discount( $coupon_code15 );
}
}
This code seems to work when adding the 5percent discount, but once I go over €100 it doesn't apply the 10percent discount.
It just keeps applying the 5percent discount.
UPDATE:
This code works like a charm. Credit goes to LouicTheAztek
add_action( 'woocommerce_cart_calculate_fees', 'progressive_discount_based_on_cart_total', 10, 1 );
function progressive_discount_based_on_cart_total( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_total = $cart_object->cart_contents_total; // Cart total
if ( $cart_total > 150.00 )
$percent = 15; // 15%
elseif ( $cart_total >= 100.00 && $cart_total < 150.00 )
$percent = 10; // 10%
elseif ( $cart_total >= 50.00 && $cart_total < 100.00 )
$percent = 5; // 5%
else
$percent = 0;
if ( $percent != 0 ) {
$discount = $cart_total * $percent / 100;
$cart_object->add_fee( "Discount ($percent%)", -$discount, true );
}
}

Using multiple coupons with different cart percentage discount is a nightmare as you have to handle when customer add new items, remove items, change quantities and add (or remove) coupons…
You should better use this simple code below, that will add a cart discount based on cart total amount (Here we use a negative fee which is a discount):
add_action( 'woocommerce_cart_calculate_fees', 'progressive_discount_based_on_cart_total', 10, 1 );
function progressive_discount_based_on_cart_total( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_total = $cart_object->cart_contents_total; // Cart total
if ( $cart_total > 150.00 )
$percent = 15; // 15%
elseif ( $cart_total >= 100.00 && $cart_total < 150.00 )
$percent = 10; // 10%
elseif ( $cart_total >= 50.00 && $cart_total < 100.00 )
$percent = 5; // 5%
else
$percent = 0;
if ( $percent != 0 ) {
$discount = $cart_total * $percent / 100;
$cart_object->add_fee( "Discount ($percent%)", -$discount, true );
}
}
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.

Related

Infinite Loop at Checkout Woocommerce [woocommerce_package_rates]

I have written the following script to automatically apply a $350 credit to the shipping rates if the shipping rate is over $350. When removing this script from my functions.php there are no issues at Checkout, the shipping methods will populate. When leaving this script in functions.php, the Checkout page requires multiple refreshes to populate and does not end the spinning loading loop.
Is there something I am missing here?
add_filter('woocommerce_package_rates', 'custom_shipping_rate_label_based_on_cost', 100, 2);
function custom_shipping_rate_label_based_on_cost( $rates, $package ){
// Declare Variables
$subtotal = $package['cart_subtotal'];
$counter = 0;
$first = 0;
$category = 0;
$discount = 350;
// Set Category True if Walk In Tub
foreach ($package['contents'] as $product) {
$product_cats = wp_get_post_terms( $product['product_id'], 'product_cat', array('fields' => 'names') );
if( in_array('Walk In Tubs', $product_cats) ) {
$category = 1;
}
}
// Set First Shipping Rate Cost and Counter
foreach ( $rates as $key => $rate ) {
$rate_cost = $rate->cost;
if( $counter == 0 ) {
$firstcost = $rate_cost;
}
if( $counter == 1 ) {
$secondcost = $rate_cost;
}
$counter = $counter + 1;
}
if ($firstcost == 0) {
$firstcost = $secondcost;
}
// Over or Equal to 350
if ( $firstcost >= 350 && $subtotal >= 4500 && $category = 1 && is_checkout()) {
$rates[$key]->cost = $rates[$key]->cost - ( $discount );
wc_print_notice( __( '<div class="shippingdiscount">$350 Discount Applied to Total Shipping Cost</div>', 'woocommerce' ), 'notice' );
}
// Under 350
else if ( $firstcost < 350 && $firstcost != 0 && $subtotal >= 4500 && $category = 1 && is_checkout()) {
foreach ( $rates as $key => $rate ) {
$rates[$key]->cost = $rates[$key]->cost - ( $firstcost );
}
wc_print_notice( __( '<div class="shippingdiscount">Your order is eligible for Free Shipping</div>', 'woocommerce' ), 'notice' );
}
else {
return;
}
return $rates;
}
It seems the issue is stemming from: wc_print_notice

Add tag to WooCommerce products based on discount percentage

I combined the code from here Setting Woocommerce Product Tags and Categories via Custom Frontend Form with the code from here Display the discount percentage on the sale badge in Woocommerce 3 :) and it looks like its working but I am not confident, what do you think?
for testing purposes I just added an if
if ($percentage > 15) {
wp_set_object_terms($product->get_id(), array('tag5'), 'product_tag');
}
and I can see the tags on the back end/front end.
Thank you
add_filter( 'woocommerce_sale_flash', 'add_percentage_to_sale_badge', 20, 3 );
function add_percentage_to_sale_badge( $html, $post, $product ) {
if( $product->is_type('variable')){
$percentages = array();
// 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 - ( floatval($prices['sale_price'][$key]) / floatval($prices['regular_price'][$key]) * 100 ) );
}
}
// We keep the highest value
$percentage = max($percentages) . '%';
} elseif( $product->is_type('grouped') ){
$percentages = array();
// Get all variation prices
$children_ids = $product->get_children();
// Loop through variation prices
foreach( $children_ids as $child_id ){
$child_product = wc_get_product($child_id);
$regular_price = (float) $child_product->get_regular_price();
$sale_price = (float) $child_product->get_sale_price();
if ( $sale_price != 0 || ! empty($sale_price) ) {
// Calculate and set in the array the percentage for each child on sale
$percentages[] = round(100 - ($sale_price / $regular_price * 100));
}
}
// We keep the highest value
$percentage = max($percentages) . '%';
} else {
$regular_price = (float) $product->get_regular_price();
$sale_price = (float) $product->get_sale_price();
if ( $sale_price != 0 || ! empty($sale_price) ) {
$percentage = round(100 - ($sale_price / $regular_price * 100)) . '%';
} else {
return $html;
}
}
if ($percentage > 15) {
wp_set_object_terms($product->get_id(), array('tag5'), 'product_tag');
}
return '<span class="onsale">' . esc_html__( 'SALE', 'woocommerce' ) . ' ' . $percentage . '</span>'. $product->get_id();
}

Multiply shipping cost in WooCommerce

I've tried to multiply shipping cost depending on how many pallets are in order. I think filter is wrong or something. It just doesnt change shipping price.
$calc = ceil($a+$b / 8); $a > is quantity of pallets, $b > is quantity of units what calculates how many pallets.
My code (function.php):
add_filter( 'woocommerce_cart_shipping_total', 'woocommerce_cart_shipping_total_filter_callback', 11, 2 );
function woocommerce_cart_shipping_total_filter_callback( $total, $cart )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( 0 < $cart->get_shipping_total() ) {
if ( $cart->display_prices_including_tax() ) {
$a = 0;
$b = 0;
foreach( WC()->cart->get_cart() as $cart_item ){
if (!empty(get_post_meta($cart_item['variation_id'], '_number_field', true))) {
$a += $cart_item['quantity'];
} else {
$atk = strstr(get_post_meta($cart_item['variation_id'], '_alus_al', true), 'tk', true);
$b += ceil($cart_item['quantity'] / $atk);
}
}
$calc = ceil($a+$b / 8); // 8 pallets maximum
$total = wc_price( ( $cart->shipping_total + $cart->shipping_tax_total ) * $calc );
if ( $cart->shipping_tax_total > 0 && ! wc_prices_include_tax() ) {
$total .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
}
} else {
$a = 0;
$b = 0;
foreach( WC()->cart->get_cart() as $cart_item ){
if (!empty(get_post_meta($cart_item['variation_id'], '_number_field', true))) {
$a += $cart_item['quantity'];
} else {
$atk = strstr(get_post_meta($cart_item['variation_id'], '_alus_al', true), 'tk', true);
$b += ceil($cart_item['quantity'] / $atk);
}
}
$calc = ceil($a+$b / 8); // 8 pallets maximum
$total = wc_price( $cart->shipping_total * $calc );
if ( $cart->shipping_tax_total > 0 && wc_prices_include_tax() ) {
$total .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
}
}
}
return $total;
}
My problem is that it doesnt change shipping cost. So I excpect it doesnt work.
Like user #LoicTheAztec mentioned I should use woocommerce_package_rates to override custom prices for shipping plugin.
add_filter( 'woocommerce_package_rates', 'custom_shipping_costs', 20, 2 );
function custom_shipping_costs( $rates, $package ) {
$a = 0;
$b = 0;
foreach( WC()->cart->get_cart() as $cart_item ){
if (!empty(get_post_meta($cart_item['variation_id'], '_number_field', true))) {
$a += $cart_item['quantity'];
} else {
$atk = strstr(get_post_meta($cart_item['variation_id'], '_alus_al', true), 'tk', true);
$atb = $atk / 2;
if ($cart_item['quantity'] < $atb) {
$b += 0;
} else {
$b += ceil($cart_item['quantity'] / $atk);
}
}
}
$tt = $a+$b;
$calc = ceil($tt / 8);
foreach( $rates as $rate_key => $rate ){
// Excluding free shipping methods
if( $rate->method_id != 'free_shipping'){
// Set rate cost
$rates[$rate_key]->cost = $rates[$rate_key]->cost * $calc;
// Set taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $rates[$rate_key]->taxes[$key] > 0 )
$taxes[$key] = $new_cost * $tax_rate;
}
$rates[$rate_key]->taxes = $taxes;
}
}
return $rates;
}

Change the displayed shipping total in WooCommerce

I need to change shipping price programmatically:
<?php
$percentage = 50;
$current_shipping_cost = WC()->cart->get_cart_shipping_total();
echo $current_shipping_cost * $percentage / 100;
?>
Unfortunately it's not working and I always get 0 (zero).
How to change the displayed shipping total with a total based on a calculated discount percentage?
The following will displayed shipping total based on a percentage. There is 2 ways:
1) First way with a custom function.
In the function.php file of your active child theme (or active theme):
function wc_display_cart_shipping_total( $percentage = 100 )
{
$cart = WC()->cart;
$total = __( 'Free!', 'woocommerce' );
if ( 0 < $cart->get_shipping_total() ) {
if ( $cart->display_prices_including_tax() ) {
$total = wc_price( ( $cart->shipping_total + $cart->shipping_tax_total ) * $percentage / 100 );
if ( $cart->shipping_tax_total > 0 && ! wc_prices_include_tax() ) {
$total .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
}
} else {
$total = wc_price( $cart->shipping_total * $percentage / 100 );
if ( $cart->shipping_tax_total > 0 && wc_prices_include_tax() ) {
$total .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
}
}
}
return $totals;
}
Usage:
<?php echo wc_display_cart_shipping_total(50); ?>
2) Second way with a filter hook.
In the function.php file of your active child theme (or active theme):
add_filter( 'woocommerce_cart_shipping_total', 'woocommerce_cart_shipping_total_filter_callback', 11, 2 );
function woocommerce_cart_shipping_total_filter_callback( $total, $cart )
{
// HERE set the percentage
$percentage = 50;
if ( 0 < $cart->get_shipping_total() ) {
if ( $cart->display_prices_including_tax() ) {
$total = wc_price( ( $cart->shipping_total + $cart->shipping_tax_total ) * $percentage / 100 );
if ( $cart->shipping_tax_total > 0 && ! wc_prices_include_tax() ) {
$total .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
}
} else {
$total = wc_price( $cart->shipping_total * $percentage / 100 );
if ( $cart->shipping_tax_total > 0 && wc_prices_include_tax() ) {
$total .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
}
}
}
return $totals;
}
Usage:
<?php echo WC()->cart->get_cart_shipping_total(); ?>

return and echo in the same function

I'm trying to add some HTML code via echo inside this PHP code:
if( $quantity == 0 )
return __("ZERO ITEMS");
elseif( $quantity > 0 && $quantity <= 5 )
return $quantity;
elseif( $quantity > 5 )
return __("OVER 5 ITEMS");
When the $quantity is 3, for example, I want to return the quantity and also have the word "ITEMS" echo'd after it. So "3 ITEMS" instead of just "3".
If there are 3 items, your control will go to else if.
You are returning only $quantity that is number.
You need to concatenate the string ITEMS after $quantity
...
elseif( $quantity > 0 && $quantity <= 5 )
return $quantity . ' ITEMS';
...
You can do this:
if ( $quantity == 0 )
return __("ZERO ITEMS");
else if( $quantity > 0 && $quantity <= 5 ) {
$itemText = ($quantity == 1) ? 'ITEM' : 'ITEMS';
echo $quantity . ' ' . $itemText;
return $quantity . ' ' . $itemText;
} else if( $quantity > 5 )
return __("OVER 5 ITEMS");
You can have 1, so it's interesting to show ITEM or ITEMS
You can do this like below.
$post_str = 'ITEMS';
if( $quantity == 0 )
return __("ZERO ".$post_str);
elseif( $quantity > 0 && $quantity <= 5 )
return $quantity.' '.$post_str;
elseif( $quantity > 5 )
return __("OVER 5 ".$post_str);

Categories