Adding a discount by cart items conditionally based on the item quantity - php

I have set up a Woocommerce shop and wish to set up a specific discount on all products based on multiples of 12 (a box). I've tried many discount plugins but haven't found what I am looking for.
For example, if I order 12 of product X, I get a 10% discount. If I order 15 of product X, I get a 10% discount on the first 12, and the last three are full price. If I order 24, then that 10% discount applies to all 24 of product X.
The closest I have found is this: Discount for Certain Category Based on Total Number of Products
But this is applied as a discount (actually a negative fee) at the end, and I'd like to display the discount in the cart next to the product, like normal discounts.
I also need this discount to be disabled if a product is already on sale.
Thanks.

This code will not work in Woocommerce 3+…
See: Cart item discount based on quantity in Woocommerce 3:
Yes this is also possible, making a custom calculation for each cart item and replacing individually their price (matching your conditions and calculations), using a custom function hooked in woocommerce_before_calculate_totals action hook.
This is the code:
add_action( 'woocommerce_before_calculate_totals', 'custom_discounted_cart_item_price', 10, 1 );
function custom_discounted_cart_item_price( $cart_object ) {
$discount_applied = false;
// Set Here your targeted quantity discount
$t_qty = 12;
// Iterating through each item in cart
foreach ( $cart_object->get_cart() as $item_values ) {
## Get cart item data
$item_id = $item_values['data']->id; // Product ID
$item_qty = $item_values['quantity']; // Item quantity
$original_price = $item_values['data']->price; // Product original price
// Getting the object
$product = new WC_Product( $item_id );
// CALCULATION FOR EACH ITEM
// when quantity is up to the targetted quantity and product is not on sale
if( $item_qty >= $t_qty && !$product->is_on_sale() ){
for($j = $t_qty, $loops = 0; $j <= $item_qty; $j += $t_qty, $loops++);
$modulo_qty = $item_qty % $t_qty; // The remaining non discounted items
$item_discounted_price = $original_price * 0.9; // Discount of 10 percent
$total_discounted_items_price = $loops * $t_qty * $item_discounted_price;
$total_normal_items_price = $modulo_qty * $original_price;
// Calculating the new item price
$new_item_price = ($total_discounted_items_price + $total_normal_items_price) / $item_qty;
// Setting the new price item
$item_values['data']->price = $new_item_price;
$discount_applied = true;
}
}
// Optionally display a message for that discount
if ( $discount_applied )
wc_add_notice( __( 'A quantity discount has been applied on some cart items.', 'my_theme_slug' ), 'success' );
}
This make exactly the discount that you are expecting separately for each item in cart (based on it's quantity) and not for items that are in sale. But you will not get any label (text) indicating a discount in the line items of cart.
Optionally I display a notice when a discount is applied to some cart items…
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

Woocommerce - Apply 10% discount to the lowest priced product in the cart based on several conditions

I'm struggled with one problem and the problem is as it follows. In our store users could create a package from 3 products. I need to apply a 10% discount to 2 products in cart.
PRODUCT required to get a discount = 10 euros
PRODUCT = 15 euros - you could get a discount from this product
PRODUCT = 12 euros - you could get a discount from this product
Discount should apply always to required product and the lowest price product 2 or 3.
Cart examples
If there is product 1, 2 and 3 in cart you will get a 10% discount to product number 1 and product number 3.
If there is a product number 1 and 3 in cart you will get a 10% discount to the both of them
If there is a product number 1 and 2 in cart you will get a 10% discount to the both of them
If there is a product number 1 only, product number 2 only, product number 3 only, then no discount is applied to your cart
If there is some of the combinations and other products which are not these 3 mentioned products above, the discount will be applied only for the mentioned products as it follows from cart examples above.
If there are more sets - if you want to order 2 products from (product number 1 and product number 2) or (product number 1 and product number 3) you have to add always 1 more to the both of them to get another 10% sale from another set so quantity will be 2/2. If theres quantity 2 (ID1)/1 (ID2) no discount will be applied for the second set only for the first one.
My code so far but I'm totally lost
function apply_discount_ten( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Product ID needs to be in cart to get a discount
$product_id = 2530;
// Products in cart
$products_in_cart = count( $cart->get_cart() );
//Set conditions
if ( $products_in_cart && (matched_cart_items($product_id)) {
// Set array
$product_prices = array();
// Loop though cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Product
$product = $cart_item['data'];
// Get price
$product_price = $product->get_price();
// Push
$product_prices[] = $product_price;
}
// Sort: low to high
asort( $product_prices );
// Number of products receive a discount
$products_receive_discount = What to do here;
// Set variable
$total = 0;
// Loop trough
foreach ( array_slice( $product_prices, 0, $products_receive_discount ) as $product_price ) {
// Calculate
$total += $product_price;
}
// Calculate discount
$discount = ( $total * 10 ) / 100;
// Add fee
$cart->add_fee( 'Discount', $discount, true );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'apply_discount_ten', 10, 1 );
Thank you in advance

Woocommerce coupon discount when item price is less than the discount amount

From my understanding of how woocommerce_coupon_get_discount_amount works. The discount is calculated as to how much it would discount each item in the cart. For example, if you had 4 items in the cart at $10, and you were to discount one item to be free. Then you would return $2.50 to each product in the cart. Thus discounting one of the products by 100%.
However, let's say that you had a product in the cart that was $1, then instead of discounting $10, the discount applied would be $8.50. Making the discount incorrect.
For this above example the coupon would be calculated as so:
add_filter('woocommerce_coupon_get_discount_amount', 'mb_wcchpi_cpn_disc', 10, 5);
function mb_wcchpi_cpn_disc($discount, $discounting_amount, $cart_item, $single, $coupon)
{
//IF CUSTOM COUPON TYPE
if ($coupon->type == 'most_expensive_coupon') {
//Gets the most expensive item in the cart
$mostExpensiveItem = FindMaxPricedItem($multiple_products);
//Get the price of the most expensive item in the cart
$maxPrice = $mostExpensiveItem['price'];
//GET THE COUPON DISCOUNT AMOUNT
$amt = floatval($coupon->amount);
//GET THE DISCOUNT AMOUNT
$discount = ($amt / 100) * $maxPrice;
//GET THE ITEMS IN THE CART
$itemCount = WC()->cart->cart_contents_count;
//DISTRIBUTE EQUALLY ACROSS ALL ITEMS IN CART
$discount = $discount / $itemCount;
}
return $discount;
}
How would one handle the edge case of having an item in the cart that is less than the discount amount? Is there a different action than woocommerce_coupon_get_discount_amount to be used for applying a coupon to the cart total instead of per item? Is there a different formula I should be using to come up with the discount?

Coupon with 2 different percentage discounts based on product category in Woocommerce

I am looking for a Woocommerce hook that will help to change the discount percentage based on 2 different product category restrictions when a specific coupon is applied.
For example if customer add a specific coupon I will like to:
If a cart item is from product category A then it will give 10% discount on that item.
if it's in product category B it will give 20% discount on that item
Update total cart price
Is there any hook that could be available to achieve this? Any available action hook or filter hook?
This is my code so far:
add_filter( 'woocommerce_get_discounted_price', 'apply_coupon', 10);
function apply_coupon($price) {
global $woocommerce;
$product=$woocommerce->cart->product;
if(has_term( 'duplex-blinds', 'A' ,$product->id)){
get_product_cart_price;
10% DISCOUNT
}
if(has_term( 'duplex-blinds', 'A' ,$product->id)){
20% DISCOUNT
}
upadte total_discunt_incart($new_discount);
upadte new_price_in_cart($new_price);
upadte new_price_in_checkout($new_price);
return $price;
}
The important thing is i need to modify the total cart price , total checkout price , total discount price and discount price need to send to Paypal.
My shop have many hooks that's why woo commerce default coupon calculation is going to wrong. And i noticed that in cart page discount price is coming correctly based on the custom product value, but it not get updated from the original cart amount, so the total price remain the same.
But in checkout page discount price is calculated based on the product original price not the product custom price so the discount is coming wrong and also it is not minimize from the total price also...
The following is a completely different way to make that works… This answer code will enable a coupon code with 2 different discounts percentage based on 2 specific product categories.
Lest say for example that your related product categories are:
For the coupon discount of 10%, the product category slug will be 'hoodies'
For the coupon discount of 20%, the product category slug will be 't-shirts'
(you can use product category Ids, slugs or Names in the code)
That will need 2 Steps:
Coupon settings (Set correctly your coupon code):
Discount type: Percentage
Amount: 10
Restrictions > Product categories (names displayed): "Hoodies" and "T shirts"
You can have other settings if you need
The settings inside the code function:
Coupon code: set your coupon code in lowercase
The 't-shirts' product category slug (for 20% of discount).
Now Here comes the code (where you will add your settings):
add_filter( 'woocommerce_coupon_get_discount_amount', 'alter_shop_coupon_data', 20, 5 );
function alter_shop_coupon_data( $round, $discounting_amount, $cart_item, $single, $coupon ){
## ---- Your settings ---- ##
// Related coupons codes to be defined in this array (you can set many)
$coupon_codes = array('10percent');
// Product categories at 20% (IDs, Slugs or Names) for 20% of discount
$product_category20 = array('hoodies'); // for 20% discount
$second_percentage = 0.2; // 20 %
## ---- The code: Changing the percentage to 20% for specific a product category ---- ##
if ( $coupon->is_type('percent') && in_array( $coupon->get_code(), $coupon_codes ) ) {
if( has_term( $product_category20, 'product_cat', $cart_item['product_id'] ) ){
$original_coupon_amount = (float) $coupon->get_amount();
$discount = $original_coupon_amount * $second_percentage * $discounting_amount;
$round = round( min( $discount, $discounting_amount ), wc_get_rounding_precision() );
}
}
return $round;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Here is an illustrated real working example (with screen shots):
The 1st cart item (from 'hoodies' product category) get 10% of discount $40 x 10% = $4
The 2nd cart item (from 't-shirts' product category) get 20% of discount $30 x 20% = $6
So the total discount is $4 + $6 = $10 … That works!
I using this code, but it give 100% on the 20% category, but the code you provide does work if you change the 0.2 to 0.02
$second_percentage = 0.2; // 20 %
change too:
$second_percentage = 0.02; // 20 %
or:
$second_percentage = 0.015; // 15 %
If you need 15% discount

Adding a custom cart negative fee tax issue in woocommerce

I have a shipping discount in my woocommerce site, I would like to show it on cart page and checkout page, for that I used add_fee() method.
WC()->cart->add_fee( 'Shipping Discount', -20, false );
It subtract 20 from total amount, but when I go to check order in orders inside admin it gives discount on tax too according to tax rate I configured. Is there any alternative to add discount
How can I do this in woocommerce?
For negative cart fee there is a bug related to taxes as they are applied on all tax classes even if the it's not taxable.
Now you can make a custom global cart discount This way where you will be able to define the type of discount you want, the discount amount and the source price to be discounted.
This code will display the he correct cart discounted gran total
Once submitted this discounted gran total will be passed to the order.
The code:
// Apply a discount globally on cart
add_filter( 'woocommerce_calculated_total', 'discounted_calculated_total', 10, 2 );
function discounted_calculated_total( $total, $cart ){
$amount_to_discount = $cart->cart_contents_total;
$percentage = 10; // 10% of discount
$discounted_amount = $amount_to_discount * $discount / 100;
$new_total = $total - $discounted_amount;
return round( $new_total, $cart->dp );
}
Code goes in function.php file of the active child theme (or active theme).
Tested and works.
You should need to make some additional code to display the discount amount (in cart and checkout pages and order-view) and to pass it in the order as meta data and so on…

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