Custom discount for every NTH item in the cart - php

I came here from this question here looking to find a solution for my WooCommerce site. I am looking for a way to get a discount in my cart only for even number of items in the cart.
For example:
If there's only 1 item in the cart: Full Price
2 Items in the cart: - (minus) 2$ for both of it
5 Items in the cart: - (minus) 2$ for 4 of it (if there's odd number of items in the cart. 1 item will always have the full price)
By the way, all of my products are having the same price.
Would someone be able to help me on this, as someone helped for the guy on the question link I've mentioned?

Here is your custom function hooked in woocommerce_cart_calculate_fees action hook, that will do what you are expecting:
add_action( 'woocommerce_cart_calculate_fees','cart_conditional_discount', 10, 1 );
function cart_conditional_discount( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_count = 0;
foreach($cart_object->get_cart() as $cart_item){
// Adds the quantity of each item to the count
$cart_count += $cart_item["quantity"];
}
// For 0 or 1 item
if( $cart_count < 2 ) {
return;
}
// More than 1
else {
// Discount calculations
$modulo = $cart_count % 2;
$discount = (-$cart_count + $modulo);
// Adding the fee
$discount_text = __('Discount', 'woocommerce');
$cart_object->add_fee( $discount_text, $discount, false );
}
}
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

Deposit field ONLY for BACKORDER ITEMS [duplicate]

I've taken this code from another post and basically this code is trying to force the cart price with a discount.
What I want to do is force the discount only if the product is on backorder. So if product is on backorder, the client can order this item which leads to a deposit calculation in the cart.
From Deposit based on a percentage of total cart amount 2nd code snippet answer, I have tried to make code changes to get a specific discount on backordered cart items.
The original code works fine as it's, but how to make it work only for backordered items?
I tried several days now using for example $product->is_on_backorder( 1 ) but I can't get it to work. How to get backordered items total amount in cart?
I know it's an easy solution, but I have tried several solutions and can't get it to work.
Updated: To make that for backordered items only, you will use the following:
add_action( 'woocommerce_cart_calculate_fees', 'calculated_deposit_discount_on_backorders' );
function calculated_deposit_discount_on_backorders( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
## Set HERE your negative percentage (to remove an amount from cart total)
$percent = -.80; // 80% off (negative)
$backordered_amount = 0;
foreach( $cart->get_cart() as $cart_item ) {
if( $cart_item['data']->is_on_backorder( $cart_item['quantity'] ) ) {
$backordered_amount = $cart_item['line_total'] + $cart_item['line_tax'];
}
}
## ## CALCULATION ## ##
$calculated_amount = $backordered_amount * $percent;
// Adding a negative fee to cart amount (Including taxes)
$cart->add_fee( __('Deposit calculation', 'woocommerce'), $calculated_amount, true );
}
Code goes in function.php file of your active child theme (or active theme). It should work.

WooCommerce custom code deleting item as soon as it's added to cart

I am trying to set up a custom coupon code so that customers can add an add-on product to their cart, only if their cart total is $50 or more.
I am using Allow add to cart for specific products based on cart total in WooCommerce answer code that allows or denies adding the product depending on their cart total and this is working great.
My issue is that I have another bit of code that is supposed to delete the addon item if it's in the cart and the cart total is no longer within the threshold.
In my case I have the threshold set to $50, and the addon product costs $10.
In testing I've found that when the cart total is $60 or more, everything works fine. I can even remove a couple of items from the cart and the addon item will stay until the total is under the threshold, then it gets removed as well.
However if the cart total is anywhere between $50 and $60 when I go to add the addon item, the addon item is immediately deleted as soon as it's added.
I would expect the order of operations to go
Checks the cart total, finds that it is above $50
Allows me to add the addon item
Checks the cart total with the addon item included, finds that it is now above $60
Allows the addon to stay
Based on Add or remove specific cart Item based on WooCommerce cart total answer code, here is the code I'm using:
add_action( 'woocommerce_before_calculate_totals', 'add_or_remove_cart_items', 10, 1 );
function add_or_remove_cart_items( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ONLY for logged users (and avoiding the hook repetition)
if ( ! is_user_logged_in() && did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$threshold_amount = 50; // The threshold amount for cart total
$addon_product_id = 7039; // ID of the addon item
$addon_product_cost = 10; // Cost of addon item
$cart_items_total = 0; // Initializing
$threshold_amount_with_addon = $threshold_amount + $addon_product_cost;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// Check if the free product is in cart
if ( $cart_item['data']->get_id() == $addon_product_id ) {
$addon_item_key = $cart_item_key;
}
// Get cart subtotal incl. tax from items (with discounts if any)
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
// If cart total is below the defined amount and addon product is in cart, we remove it.
if ( $cart_items_total < $threshold_amount_with_addon && isset($addon_item_key) ) {
$cart->remove_cart_item( $addon_item_key );
return;
}
}
I can't for the life of me figure out what is going wrong. Any help would be much appreciated.
Below, we exclude the Add-On item from subtotal calculation so we don't need to add the Add-On price to threshold amount (so we keep your steps 1, 2 and 4).
The revisited code:
add_action( 'woocommerce_before_calculate_totals', 'add_or_remove_cart_items', 10, 1 );
function add_or_remove_cart_items( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ONLY for logged users, avoiding the hook repetition
if ( ! is_user_logged_in() || did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$addon_product_id = 7039; // ID of the addon item
$threshold_amount = 50; // The threshold amount
$cart_items_total = 0; // Initializing
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// For Add-On product: Check if it is in cart
if ( in_array( $addon_product_id, [$cart_item['product_id'], $cart_item['variation_id']] ) ) {
$addon_item_key = $cart_item_key;
}
// For other items: add their line total including taxes to items subtotal
else {
// Sum dicounted line total incl. taxes to get other items subtotal
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// If cart total is below the defined amount and addon product is in cart, we remove it.
if ( $cart_items_total < $threshold_amount && isset($addon_item_key) ) {
$cart->remove_cart_item( $addon_item_key );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Auto add a variable quantity of specific product based on WooCommerce cart subtotal

I'm trying to add a gift product to a shopping cart based upon the total cost spent by a customer. It's for a restaurant that sells gift vouchers.
The scheme runs as follows: for every £50 that a customer spends in a single transaction, they automatically receive a £10 gift voucher for free. So, if they spend £100 on gift vouchers, they receive 2x £10 gift vouchers for free (and so on).
To keep things as simple as possible, we're limiting denominations of gift vouchers (£25 - £250 increasing in £25 denominations).
I don't particularly want to pay for/install another plugin that will need to be updated/managed, etc. If I'm honest, it's only for the Christmas period so a snippet of code to do this would be far better.
The way I see it working is that a customer adds the vouchers to the cart and when they go to the cart it shows they've also got the additional 'free' vouchers in there too.
I've found some code online and made some changes to it. The code is as follows:
function auto_add_specific_product_to_cart() {
// select product ID
$product_id = 1428;
// if cart empty, add it to cart
if ( WC()->cart->get_cart_total() <= 99 ) {
WC()->cart->add_to_cart( $product_id, 1 ); }
else if ( WC()->cart->get_cart_total() <= 149 ) {
WC()->cart->add_to_cart( $product_id, 2 ); }
else if ( WC()->cart->get_cart_total() <= 199 ) {
WC()->cart->add_to_cart( $product_id, 3 ); }
else if ( WC()->cart->get_cart_total() <= 249 ) {
WC()->cart->add_to_cart( $product_id, 4 ); }
}
I'm having problems with it right, left and centre. It keeps adding the free vouchers to the shopping cart so eventually customers end up with 20 or 30 vouchers there; the PHP for recognising the different thresholds (50 to 99, 100 to 149, etc) aren't working properly. I'm probably making this far too complicated and not thinking it through but a bit of help would be great.
I've found plenty of code online for discounting products but nothing that gives something away for free.
Here a variable quantity of a "specific product voucher" will be auto added to cart based on cart subtotal.
The code below is based on Add free gifted product for a minimal cart amount in WooCommerce answer code. The code automate the generation of cart subtotal thresholds (min and max amounts) and the related quantity of the voucher product to be added to cart.
The number set in $max_quantity variable, determines the number of iterations on the FOR loop (so the number of different generated thresholds and the max quantity of voucher product that can be added to cart).
// Auto add a quantity of voucher product based on cart subtotal
add_action( 'woocommerce_before_calculate_totals', 'auto_add_voucher_product_based_on_subtotal' );
function auto_add_voucher_product_based_on_subtotal( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Settings
$voucher_product_id = 37; // Voucher product Id
$max_quantity = 20; // Here set the max item quantity (for voucher product)
$min_subtotal = 50; // Starting threshold min amount
$cart_subtotal = 0; // Initializing
// Loop through cart items (first loop)
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// When voucher product is is cart
if ( $voucher_product_id == $cart_item['product_id'] ) {
$voucher_key = $cart_item_key;
$voucher_qty = $cart_item['quantity'];
// $cart_item['data']->set_price(0); // (optional) set the price to zero
} else {
$cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax']; // Get subtotal
}
}
// If voucher product is not already in cart, add it
if ( ! isset($voucher_key) && $cart_subtotal >= $min_subtotal ) {
$cart->add_to_cart( $voucher_product_id );
}
// Check vouvher product quantity and adjust it depending on the subtotal amount.
else {
// Loop dynamically through subtotal threshold min and max amounts setting the right quantity
// $i is the min amount, $j the max amount and $q the related quantity to check
for ( $i = $min_subtotal, $j = 100, $q = 1; $q < $max_quantity; $i += 50, $j += 50, $q++ ) {
if ( $cart_subtotal >= $i && $cart_subtotal < $j && $voucher_qty != $q ) {
$cart->set_quantity( $voucher_key, $q );
}
}
if ( $cart_subtotal >= $i && $voucher_qty != $q ) {
$cart->set_quantity( $voucher_key, $q );
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Cart item discount based on quantity in Woocommerce 3

My WP site sells customized t-shirts. The customization plugin makes each customized shirt a line item in the woocommerce cart. If there are 2 shirts ordered of one design (quantity of 2 on that line item) I want to discount. But if there is just 1 item per line I dont want to discount.
I found this solution
Adding a discount by cart items conditionally based on the item quantity
But this seems to change the product price in the db, so after the discount kicks in for say 2 blue shirts because there were 2 ordered on 1 line, if I add a 3rd shirt on a separate line it also gets the discount, which I dont want.
Since woocommerce version 3+ the linked answer code doesn't work. It needs something different and can even be done in a better way.
The code will apply a cart item discount based on the cart item quantity. In this code example, it will apply a discount of 5% on the cart item, when the quatity is equal or more than 2 (two).
The cart item unit price displayed is always the real product price. The discount will be effective and displayed on the cart item subtotal.
Additionally the product name will be appended with a discount mention.
The code:
add_filter('woocommerce_add_cart_item_data', 'add_items_default_price_as_custom_data', 20, 3 );
function add_items_default_price_as_custom_data( $cart_item_data, $product_id, $variation_id ){
$product_id = $variation_id > 0 ? $variation_id : $product_id;
## ----- YOUR SETTING ----- ##
$discount_percentage = 5; // Discount (5%)
// The WC_Product Object
$product = wc_get_product($product_id);
// Only for non on sale products
if( ! $product->is_on_sale() ){
$price = (float) $product->get_price();
// Set the Product default base price as custom cart item data
$cart_item_data['base_price'] = $price;
// Set the Product discounted price as custom cart item data
$cart_item_data['new_price'] = $price * (100 - $discount_percentage) / 100;
// Set the percentage as custom cart item data
$cart_item_data['percentage'] = $discount_percentage;
}
return $cart_item_data;
}
// Display the product original price
add_filter('woocommerce_cart_item_price', 'display_cart_items_default_price', 20, 3 );
function display_cart_items_default_price( $product_price, $cart_item, $cart_item_key ){
if( isset($cart_item['base_price']) ) {
$product = $cart_item['data'];
$product_price = wc_price( wc_get_price_to_display( $product, array( 'price' => $cart_item['base_price'] ) ) );
}
return $product_price;
}
// Display the product name with the discount percentage
add_filter( 'woocommerce_cart_item_name', 'append_percetage_to_item_name', 20, 3 );
function append_percetage_to_item_name( $product_name, $cart_item, $cart_item_key ){
if( isset($cart_item['percentage']) && isset($cart_item['base_price']) ) {
if( $cart_item['data']->get_price() != $cart_item['base_price'] )
$product_name .= ' <em>(' . $cart_item['percentage'] . '% discounted)</em>';
}
return $product_name;
}
add_action( 'woocommerce_before_calculate_totals', 'custom_discounted_cart_item_price', 20, 1 );
function custom_discounted_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
## ----- YOUR SETTING ----- ##
$targeted_qty = 2; // Targeted quantity
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// For item quantity of 2 or more
if( $cart_item['quantity'] >= $targeted_qty && isset($cart_item['new_price']) ){
// Set cart item discounted price
$cart_item['data']->set_price($cart_item['new_price']);
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To display the discounted product price instead of the original product price, just remove woocommerce_cart_item_price() function (and hook)…
Newest similar: Cart item quantity progressive percentage discount in Woocommerce 3

Cart add_fee() is not working in checkout page

In WooCommerce, I would like to make a discount without using coupons, and the discount calculation will be based on product price, with something like "take 3 products for the price of 2.
In function.php of my active theme I am using this code:
function promo () {
if (is_cart()) {
$woocommerce->cart->add_fee( __('des', 'woocommerce'), -50.00`enter code here`, true, '');
}
}
add_action ('woocommerce_cart_calculate_fees', 'promo');
My problem: This code doesn't work on checkout page.
If I force in review-order the discount appears, but the total value don't change. I think its not saving the fee.
How can I make it work (on checkout page)?
Thanks
This hook is made for cart fees (or discounts), so you have to remove if (is_cart()) { condition, that why it's not working…
Here is the correct functional code to achieve a "Buy 2 take 3" discount, that will make a discount based on line item quantity:
add_action('woocommerce_cart_calculate_fees' , 'discount_2_for_3', 10, 1);
function discount_2_for_3( $cart_object ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Initialising variable
$discount = 0;
// Iterating through cart items
foreach( $cart_object->get_cart() as $cart_item ){
// Getting item data from cart object
$item_id = $cart_item['product_id']; // Item Id or product ID
$item_qty = $cart_item['quantity']; // Item Quantity
$product_price = $cart_item['data']->price; // Product price
$line_total = $cart_item['line_total']; // Price x Quantity total line item
// THE DISCOUNT CALCULATION
if($item_qty >= 3){
// For each item quantity step of 3 we add 1 to $qty_discount
for($qty_x3 = 3, $qty_discount = 0; $qty_x3 <= $item_qty; $qty_x3 += 3, $qty_discount++);
$discount -= $qty_discount * $product_price;
}
}
// Applied discount "2 for 3"
if( $discount != 0 ){
// Note: Last argument is related to applying the tax (false by default)
$cart_object->add_fee( __('Des 2 for 3', 'woocommerce'), $discount, false);
}
}
This will work for simple products, but not for product variations…
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested and works.

Categories