WooCommerce dynamic minimum order amount based fee - php

I need to set a minimum order fee in the shopping cart so if products in the cart don't total more than £10 then an extra fee is applied to bring the price up to £10.
Here is the code I have at the moment which works well in the cart phase however when you reach the checkout the pricing section doesn't stop loading for some reason and you can't checkout, can anyone help?
Code from functions.php:
function woocommerce_custom_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$minimumprice = 10;
$currentprice = $woocommerce->cart->cart_contents_total;
$additionalfee = $minimumprice - $currentprice;
if ( $additionalfee >= 0 ) {
wc_print_notice(
sprintf( 'We have a minimum %s per order. As your current order is only %s, an additional fee will be applied at checkout.' ,
wc_price( $minimumprice ),
wc_price( $currentprice )
), 'error'
);
$woocommerce->cart->add_fee( 'Minimum Order Adjustment', $additionalfee, true, '' );
}
}
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );

Enhanced and updated on May 2019.
The infinite loading spin issue that you are facing is due to wc_print_notice() when it's used in woocommerce_cart_calculate_fees hook. It's seems like a bug.
If you use instead wc_add_notice(), the problem is gone but the notice is displayed 2 times.
Additionally I have revisited your code.The only solution is to split it in 2 separated functions (and a third one for the message):
// Add a custom fee (displaying a notice in cart page)
add_action( 'woocommerce_cart_calculate_fees', 'add_custom_surcharge', 10, 1 );
function add_custom_surcharge( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_cart_calculate_fees' ) >= 2 )
return;
$min_price = 100; // The minimal cart amount
$current_price = $cart->cart_contents_total;
$custom_fee = $min_price - $current_price;
if ( $custom_fee > 0 ) {
$cart->add_fee( __('Minimum Order Adjustment'), $custom_fee, true );
// NOTICE ONLY IN CART PAGE
if( is_cart() ){
wc_print_notice( get_custom_fee_message( $min_price, $current_price ), 'error' );
}
}
}
// Displaying the notice on checkout page
add_action( 'woocommerce_before_checkout_form', 'custom_surcharge_message', 10 );
function custom_surcharge_message( ) {
$min_price = 100; // The minimal cart amount
$cart = WC()->cart;
$current_price = $cart->cart_contents_total;
$custom_fee = $min_price - $current_price;
// NOTICE ONLY IN CHECKOUT PAGE
if ( $custom_fee > 0 ) {
wc_print_notice( get_custom_fee_message( $min_price, $current_price ), 'error' );
}
}
// The fee notice message
function get_custom_fee_message( $min_price, $current_price ) {
return sprintf(
__('We have a minimum %s per order. As your current order is only %s, an additional fee will be applied.', 'woocommerce'),
wc_price( $min_price ),
wc_price( $current_price )
);
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Related

Cart Message for specific shipping class, minimum amount and geolocated country in WooCommerce

I tried to make the code from Cart Message for a specific shipping class and a minimal cart total in Woocommerce coexist with my recent code Free shipping cart message for a specific shipping class, a minimal amount and a specific Country in Woocommerce, with additional multiple conditions:
add_action( 'woocommerce_before_calculate_totals', 'cart_items_shipping_class_message', 20, 1 );
function cart_items_shipping_class_message( $cart ){
if ( ! is_cart() || ( is_admin() && ! defined('DOING_AJAX') ) )
return;
$shipping_class = 'supplier';
$min_amout = 20;
$free_shipping = 50;
$amout_incl_tax = 0;
foreach( $cart->get_cart() as $cart_item ){
if( $cart_item['data']->get_shipping_class() === $shipping_class ){
$amout_incl_tax += $cart_item['line_subtotal'] + $cart_item['line_subtotal_tax'];
}
}
if( $amout_incl_tax > 0 && $amout_incl_tax < $min_amout && is_cart() && WC_Geolocation::geolocate_ip()['country'] === 'IT' ){
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
wc_add_notice( sprintf( '<p><strong><font color="#cc1602">20 € of minimum amount on products SUPPLIER</font></strong></p>Add %s of products<span class="sub-button">' . wc_price($free_shipping - $amout_incl_tax) . 'for free shipping!</span>',
wc_price($min_amout - $amout_incl_tax) ), 'error' );
}
elseif( $amout_incl_tax > 0 && $amout_incl_tax < $min_amout && is_cart() && ! WC_Geolocation::geolocate_ip()['country'] === 'IT' ){
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
wc_add_notice( sprintf( '<p><strong><font color="#cc1602">20 € of minimum amount on products SUPPLIER</font></strong></p>Add %s of products',
wc_price($min_amout - $amout_incl_tax) ), 'error' );
}
elseif( $amout_incl_tax >= $min_amout && $amout_incl_tax < $free_shipping && is_cart() && WC_Geolocation::geolocate_ip()['country'] === 'IT' ){
wc_add_notice( sprintf( '<p><strong><font color="green">FREE SHIPPING on products SUPPLIER width at least 50 €</font></strong></p>Add %s of products for free shipping!',
wc_price($free_shipping - $amout_incl_tax) ), 'notice' );
}
}
The cart "Ajax update" seems to be slowed down. Maybe it is possible to lighten the code?
I replaced old <font> html tag, make the code translatable and more modular.
The "ajax update" slow down is due to the remove_action() execution when "supplier" items subtotal is less than the minimal required amount, and can't be improved.
Your revisited code:
add_action( 'woocommerce_before_calculate_totals', 'cart_items_shipping_class_message', 20, 1 );
function cart_items_shipping_class_message( $cart ){
if ( ( is_admin() && ! defined('DOING_AJAX' ) ) || ! is_cart() )
return;
$shipping_class = 'supplier';
$min_amount = 20;
$free_shipping = 50;
$items_subtotal = 0;
// Getting non discounted "supplier" cart items subtotal including taxes
foreach( $cart->get_cart() as $cart_item ){
// Targeting our defined shipping class only
if( $cart_item['data']->get_shipping_class() === $shipping_class ){
// Add each subtotal from our defined shipping class only
$items_subtotal += $cart_item['line_subtotal'] + $cart_item['line_subtotal_tax'];
}
}
$is_geo_ip_italy = WC_Geolocation::geolocate_ip()['country'] === 'IT';
if( $items_subtotal > 0 && $items_subtotal < $min_amount ){
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
$free_message = sprintf( ' <span class="sub-button">%s %s</span>',
wc_price( $free_shipping - $items_subtotal ),
__('for free shipping!', 'woocommerce')
);
wc_add_notice( sprintf( '<p><strong style="color:#cc1602;">%s %s</strong></p>%s%s',
wc_price( $min_amout ),
__('of minimum amount on products SUPPLIER', 'woocommerce'),
home_url('/brand/supplier-slug'),
sprintf( __('Add %s of products', 'woocommerce'), wc_price($min_amount - $items_subtotal) ),
$is_geo_ip_italy ? $free_message : '',
), 'error' );
}
elseif( $items_subtotal >= $min_amount && $items_subtotal < $free_shipping && $is_geo_ip_italy ){
wc_add_notice( sprintf( '<p><strong style="color:green">%s %s</strong></p>%s',
__('FREE SHIPPING on products SUPPLIER width at least', 'woocommerce'),
wc_price( $free_shipping ),
home_url('/brand/supplier-slug'),
sprintf( __('Add %s of products for free shipping!', 'woocommerce'), wc_price($free_shipping - $items_subtotal) ),
), 'notice' );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Free Give-Away product for specific cart subtotal in WooCommerce

I have one product that is in cheap. I want to give that product away if and only if the cart subtotal is 200 or more.
If the cart subtotal is 200 or more, add the product to the cart and set the price to 0.
If the cart subtotal is less than 200, remove the product from the cart.
On adding and removing, I use a notice to inform the customer. Everything works as planned except for changing the product price.
If someone can please review the code I'm using and fix that one thing, I would be very grateful.
add_action( 'woocommerce_before_calculate_totals', 'free_product_if_cart_minimum', 10, 1 );
function free_product_if_cart_minimum( $cart ) {
// go away if admin
if (is_admin() && !defined( 'DOING_AJAX' )) return;
// say no to hook repetition
if (did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
$minimum_amount = 200;
$free_product_id = 4576;
$cart_items_total = 0;
// cart loop
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// is the free product there?
if ( $cart_item['data']->get_id() == $free_product_id ) {
$free_item_key = $cart_item_key;
// set the price to zero
// I've tried them both without success
// $free_item_key->set_price( 0 );
// $free_product_id->set_price( $price * 0.00 );
}
// cart subtotal incl. tax and discounts
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
// add the free product if not already there
if ( $cart_items_total >= $minimum_amount && !isset( $free_item_key ) ) {
$cart->add_to_cart( $free_product_id );
wc_add_notice( 'Thank you! Here\'s your free product.', 'notice' );
}
// if below the minimum, remove the free product
elseif ( $cart_items_total < $minimum_amount && isset( $free_item_key ) ) {
$cart->remove_cart_item( $free_item_key );
// display notice after removal
wc_add_notice( 'Your cart subtotal is less than 200 and therefore, the free product was removed.', 'notice' );
}
}
The following will do the job, setting the free product price to zero when it's in cart:
add_action( 'woocommerce_before_calculate_totals', 'conditionally_add_free_product' );
function conditionally_add_free_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Settings
$minimum_amount = 200;
$free_product_id = 4576;
// Initializing
$cart_subtotal = 0;
$cart_items = $cart->get_cart();
// Loop through cart items (first loop)
foreach ( $cart_items as $cart_item_key => $cart_item ){
// When free productis is cart
if ( $cart_item['data']->get_id() == $free_product_id ) {
$free_item_key = $cart_item_key; // Free product found (get its cart item key)
$cart_item['data']->set_price(0);
}
// Get cart subtotal incl. tax and discounts (excluding free product)
else {
$cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// When cart total is up to the minimum amount, add the free product if not already there
if ( $cart_subtotal >= $minimum_amount && ! isset($free_item_key) ) {
$cart_item_key = $cart->add_to_cart( $free_product_id );
// display notice after removal
wc_add_notice( __("Thank you! Here's your free product."), 'notice' );
}
// if below the minimum, remove the free product
elseif ( $cart_subtotal < $minimum_amount && isset( $free_item_key ) ) {
$cart->remove_cart_item( $free_item_key );
// display notice after removal
wc_add_notice( sprintf(
__("Your cart subtotal is less than %s and therefore, the free product was removed."), wc_price($cart_subtotal)
), 'notice' );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Dynamic information based on shipping method and cart total In Woocommerce

This seems like it should be simple but I can't quite get there.
Goal: I need to display a notice to users when they change their shipping method if the cart total is less than the required limit.
I wrote a function in functions.php file
function min_delivery(){
//Get Chosen Shipping Method//
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
//end method
//check if they've chosen delivery
if ($chosen_shipping == 'flat_rate:2') {
//set cart minimum
$minimum = 15.00;
//get cart total - 2.00 is the delivery fee
$total = WC()->cart->total-2.00;
// check if the total of the cart is less than the minium
if ( $total < $minimum ) {
//check if it's in the cart
if( is_cart() ) {
wc_print_notice(
sprintf( 'Minimum £15.00 for Delivery' ,
wc_price( $minimum ),
wc_price( $total )
), 'error'
);
//else at checkout
} else {
wc_add_notice(
sprintf( 'Min 15.00 for Delivery' ,
wc_price( $minimum ),
wc_price( $total )
), 'error'
);
}
}//end of total less than min
//else they have pick up
} else {
//set cart minimum
$minimum = 4.50;
//get cart total - 2.00 is the delivery fee
$total = WC()->cart->total-2.00;
if ( $total < $minimum ) {
//check if it's in the cart
if( is_cart() ) {
wc_print_notice(
sprintf( 'Minimum £15.00 for Delivery' ,
wc_price( $minimum ),
wc_price( $total )
), 'error'
);
//else at checkout
} else {
wc_add_notice(
sprintf( 'Min 15.00 for Delivery' ,
wc_price( $minimum ),
wc_price( $total )
), 'error'
);
}
}//end of total less than min
}//end pickup/delivery else
}//end function
Now calling this function with the before checkout form works great
add_action( 'woocommerce_before_checkout_form' , 'min_delivery' );
However my issue is when people update the shipping on the fly, i.e choose between them. I figured there would be a hook I could use such as one of these
//add_action( 'woocommerce_checkout_process', 'min_delivery' );
//add_action( 'update_order_review' , 'min_delivery' );
//add_action( 'woocommerce_review_order_after_shipping' , 'min_delivery' );
add_action( 'woocommerce_before_checkout_form' , 'min_delivery' );
//add_action( 'woocommerce_after_checkout_shipping_form', 'min_delivery' );
//add_action('woocommerce_cart_totals_after_shipping', 'min_delivery');
However none of them do the job. When i look into the console, when updating there is an AJAX Call to ?wc-ajax=update_order_review but I couldn't seem to hook into that
I'm wandering if i'm barking up the wrong tree here and you can even amend the page through hooks and functions as PHP has already rendered?
As per the goal the whole point is to restrict order/payment for delivery where cart total is less than £15 and notify the customer of the reason.
I have revisited and tried to simplify your code. The following will add conditionally a custom information message (refreshed dynamically) in cart and checkout totals table after shipping rows:
add_action( 'woocommerce_cart_totals_after_shipping', 'shipping_notice_displayed', 20 );
add_action( 'woocommerce_review_order_after_shipping', 'shipping_notice_displayed', 20 );
function shipping_notice_displayed() {
if ( did_action( 'woocommerce_cart_totals_after_shipping' ) >= 2 ||
did_action( 'woocommerce_review_order_after_shipping' ) >= 2 ) {
return;
}
// Chosen Shipping Method
$chosen_shipping_method_id = WC()->session->get( 'chosen_shipping_methods' )[0];
$chosen_shipping_method = explode(':', $chosen_shipping_method_id)[0];
$cart_subtotal = WC()->cart->subtotal; // No need to remove the fee
// Settings
$cart_minimum1 = 4.5;
$cart_minimum2 = 15;
// HERE define the cart mininimum (When delivery is chosen)
if ( $cart_subtotal < $cart_minimum2 && $chosen_shipping_method != 'flat_rate' ) {
$cart_minimum = $cart_minimum1;
} elseif ( $cart_subtotal < $cart_minimum2 && $chosen_shipping_method == 'flat_rate' ) {
$cart_minimum = $cart_minimum2;
}
// Display a message
if( isset($cart_minimum) ){
// The message
$message = sprintf( '%s %s for Delivery' ,
is_cart() ? 'Minimum' : 'Min',
strip_tags( wc_price( $cart_minimum, array('decimals' => 2 ) ) )
);
// Display
echo '</tr><tr class="shipping info"><th> </th><td data-title="Delivery info">'.$message.'</td>';
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Pair normal products with subscriptions based on item count in Woocommerce

In my website I use WooCommerce v3.1+ and Woocommerce Subscriptions. My products that contains items like video cameras and subscription plans. What I would like to do is:
when purchasing a camera and subscription plan, at cart page(before checkout), the quantity of the subscription plan must be equal to the quantity of cameras,
if another camera is added to the cart an error massage must appear...or something like that.
For example, if I have in my cart 2 specific products like a camera (quantity 2) and a subscription plan (quantity 1), the customer will not be able to checkout, if the subscription plan quantity does not match with cameras quantity.
I believe I have to modify the functions.php in child theme. Any help would be appreciated
Edit: I have added a piece of code in functions.php, but this will add x2 total items in cart:
add_action('woocommerce_check_cart_items', 'wh_wc_minimum_order_amount');
function wh_wc_minimum_order_amount() {
$minimum = 2;
if (WC()->cart->get_cart_contents_count() % $minimum != 0) {
// wc_clear_notices();
wc_add_notice(sprintf('<strong>Error: check product quantity</strong>', $minimum), 'error');
}
}
So this doesn't work.
Here is a complete solution that will display custom notices when normal products count doesn't match with subscription plans, warning the customer lightly. If products doesn't match your requirements, the customer will be redirected from checkout to shop page (avoiding checkout).
The code (commented):
// Replacing add to cart button link on shop and archives
add_filter( 'woocommerce_loop_add_to_cart_link', 'replacing_add_to_cart_button', 10, 2 );
function replacing_add_to_cart_button( $button, $product ) {
if( $product->is_type( 'variable-subscription' ) || $product->is_type( 'variable' ) ) return $button;
$button_text = __( 'View product', 'woocommerce' );
$button = '<a class="button" href="' . $product->get_permalink() . '">' . $button_text . '</a>';
return $button;
}
// Counting cart items (utility function)
function counting_cart_items( $subscriptions_count = 0, $products_count = 0, $wc_cart = '' ) {
$cart_obj = $wc_cart != '' ? $wc_cart : WC()->cart;
foreach( $cart_obj->get_cart() as $cart_item ){
if ( $cart_item['data']->is_type( 'subscription' ) )
$subscriptions_count += intval( $cart_item['quantity'] );
else
$products_count += intval( $cart_item['quantity'] );
}
return array( 'subscrip' => $subscriptions_count, 'product' => $products_count );
}
// Displaying Notification messages (utility function)
function conditionally_display_notice( $subscriptions_count, $products_count ) {
$count = $subscriptions_count - $products_count;
if( $subscriptions_count < $products_count )
$txt = sprintf( _n( '%s subscription plan', '%s subscriptions plans', -$count, 'woocommerce' ), -$count );
elseif( $subscriptions_count > $products_count )
$txt = sprintf( _n( '%s product', '%s products', $count, 'woocommerce' ), $count );
if( $subscriptions_count != $products_count )
wc_add_notice( sprintf( __( "You need to add %s, to be able to checkout", "woocommerce" ), $txt ), "notice" );
}
// Checking and notifying when products are added to cart
add_filter( 'woocommerce_add_to_cart_validation', 'conditionally_check_add_to_cart', 10, 3 );
function conditionally_check_add_to_cart( $passed, $product_id, $quantity ) {
$items_count = counting_cart_items(); // Counting cart items
$product = wc_get_product( $product_id ); // Get an instance of the WC_Product object
// Get the total live count
if( $product->is_type( 'subscription' ) )
$items_count['subscrip'] += intval( $quantity );
else
$items_count['product'] += intval( $quantity );
// Notification messages
conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
return $passed;
}
// Conditionally checking and adding your subscription when a product is added to cart
add_action( 'woocommerce_before_main_content', 'display_notice_on_shop_archives' );
function display_notice_on_shop_archives( ) {
if( is_product() ) return;
$items_count = counting_cart_items(); // Counting cart items
// Notification messages
conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
wc_print_notices();
}
/*
// Conditionally checking and adding your subscription when a product is added to cart
add_action( 'woocommerce_add_to_cart', 'conditionally_check_add_to_cart', 10, 6 );
function conditionally_check_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
$items_count = counting_cart_items(); // Counting cart items
$product = wc_get_product( $product_id ); // Get an instance of the WC_Product object
// Get the updated count
if( $product->is_type( 'subscription' ) )
$items_count['subscrip'] += intval( $quantity );
else
$items_count['product'] += intval( $quantity );
// Notification messages
conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
}
*/
// Checking and validating when updating cart item quantities
add_filter( 'woocommerce_update_cart_validation', 'conditionally_check_cart_update', 10, 4 );
function conditionally_check_cart_update( $passed, $cart_item_key, $values, $updated_quantity ) {
$items_count = counting_cart_items(); // Counting cart items
// Get the updated count
if( $values['data']->is_type( 'subscription' ) )
$items_count['subscrip'] += intval( -$values['quantity'] + $updated_quantity );
else
$items_count['product'] += intval( -$values['quantity'] + $updated_quantity );
// Notification messages
conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
return $passed;
}
// Checking and validating when updating cart item quantities
add_filter( 'woocommerce_cart_item_removed', 'conditionally_check_removed_cart_item', 10, 2 );
function conditionally_check_removed_cart_item( $cart_item_key, $wc_cart ) {
$items_count = counting_cart_items( 0, 0, $wc_cart ); // Counting cart items
// Notification messages
conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
}
// Checking and conditionally redirecting to shop page
add_action( 'template_redirect', 'conditional_checkout_redirection');
function conditional_checkout_redirection(){
if ( is_checkout() ) {
$items_count = counting_cart_items(); // Counting cart items
if ( $items_count['subscrip'] != $items_count['product']) {
// redirecting to shop page
wp_redirect( get_permalink( woocommerce_get_page_id( 'shop' ) ) );
exit(); // always exit
}
}
}
code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works

Conditionally apply coupons automatically for specific Product IDs and quantities

I am trying to automatically apply coupons in my WooCommerce store based on product ID and quantity conditions. My end goal is for a particular coupon to apply automatically when TWO (2) of the desired products are added to the cart, and for another coupon to app,y automatically whenever THREE (3) of the desired products are added to the cart. A single quantity of the product should have no discount. The following is the CORRECTED version of the code, which now works:
add_action( 'woocommerce_before_cart', 'conditional_auto_add_coupons' );
function conditional_auto_add_coupons() {
if ( !WC()->cart->is_empty() ){
// Define HERE your Targeted Product ID and coupons codes
$target_pid = 103;
$coupon1 = 'soccer-sibling-2';
$coupon2 = 'soccer-sibling-3';
// First cart loop: Counting number of subactegory items in cart
foreach ( WC()->cart->get_cart() as $cart_item ){
if( $target_pid == $cart_item['data']->id ){
// Removes any coupons in the cart already
WC()->cart->remove_coupons();
if( 2 == WC()->cart->get_cart_contents_count() && !WC()->cart->has_discount( $coupon1 ) ){
WC()->cart->remove_coupons();
WC()->cart->add_discount( $coupon1 );
wc_add_notice( __( 'The multiple sibling discount has been applied.', 'theme_domain' ), 'success' );
} elseif( 3 == WC()->cart->get_cart_contents_count() && !WC()->cart->has_discount( $coupon2 ) ){
WC()->cart->remove_coupons();
WC()->cart->add_discount( $coupon2 );
wc_add_notice( __( 'The multiple sibling discount has been applied.', 'theme_domain' ), 'success' );
}
// Recalculates Cart Totals to show correct price
WC()->cart->calculate_totals();
}
}
}
}
Theres is a lot of errors in your code and it's a little obsolete too...
I have rewrite everithing in your function and hooked it in another hook.
Here is your revisited code:
add_action( 'woocommerce_before_cart', 'conditional_auto_add_coupons' );
function conditional_auto_add_coupons() {
if ( !WC()->cart->is_empty() ){
// Define HERE your Targeted Product ID and coupons codes
$target_pid = 103;
$coupon1 = 'soccer-sibling-2';
$coupon2 = 'soccer-sibling-3';
// First cart loop: Counting number of subactegory items in cart
foreach ( WC()->cart->get_cart() as $cart_item ){
if( $target_pid == $cart_item['data']->id ){
if( 2 == WC()->cart->get_cart_contents_count() && !WC()->cart->has_discount( $coupon1 ) ){
WC()->cart->add_discount( $coupon1 );
wc_add_notice( __( 'A quantity discount of <strong>5%</strong> has been added.', 'theme_domain' ), 'success' );
} elseif( 3 == WC()->cart->get_cart_contents_count() && !WC()->cart->has_discount( $coupon2 ) ){
WC()->cart->add_discount( $coupon2 );
wc_add_notice( __( 'A quantity discount of <strong>10%</strong> has been added.', 'theme_domain' ), 'success' );
}
}
}
}
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This should work and will not make your website crash, but I haven't really test it, as this is very particular.
Coming back here a few years later: I found a loophole that caused an issue. Because the function was counting the total cart contents, rather than just the quantity of the product the coupon is applied to, customers could exploit this to add non-coupon related products to get the additional coupons for the discounted product. The following code closes the loophole by checking the quantity of just the product in question:
add_action( 'woocommerce_before_cart', 'conditional_auto_add_coupons_tourney' );
function conditional_auto_add_coupons_tourney() {
if ( !WC()->cart->is_empty() ){
// Define HERE your Targeted Product ID and coupons codes
$target_pid = 96;
$coupon1 = 'multiple-25';
$coupon2 = 'multiple-50';
// UPDATE: switched WC()->cart->get_cart_contents_count() for $quantity on 236 and 240
// First cart loop: Counting number of subcategory items in cart
foreach ( WC()->cart->get_cart() as $cart_item ){
if( $target_pid == $cart_item['product_id'] ){
WC()->cart->remove_coupons();
$quantity = $cart_item['quantity']; // Added to find quantity of specific product
if( 5 <= $quantity && !WC()->cart->has_discount( $coupon2 ) ){
WC()->cart->remove_coupons();
WC()->cart->add_discount( $coupon2 );
wc_add_notice( __( 'The multiple team discount has been applied.', 'theme_domain' ), 'success' );
} elseif( 2 <= $quantity && !WC()->cart->has_discount( $coupon1 ) ){
WC()->cart->remove_coupons();
WC()->cart->add_discount( $coupon1 );
wc_add_notice( __( 'The multiple team discount has been applied.', 'theme_domain' ), 'success' );
}
WC()->cart->calculate_totals();
}
}
}
}

Categories