Check if product with category "A" is in the cart and apply a 10% discount to all products with category "B" in the cart: - woocommerce

I'm trying to add a 10% discount to all products that fall into category B when a product from category A is in the cart, this is what i've tried so far and from what I see there's not an obvious reason but the discount is not applied in the cart. It can be a total discount fee or a separate discount for each item.
add_action( 'woocommerce_before_calculate_totals', 'apply_category_discount_in_cart', 10, 1 );
function apply_category_discount_in_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$discount_amount = 0;
$category_A_in_cart = false;
// Loop through each item in the cart
foreach ( $cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
// Check if the product has category A
if ( has_term( 'categorya', 'product_cat', $product->get_id() ) ) {
$category_A_in_cart = true;
break;
}
}
// If a product with category A is found in the cart
if ( $category_A_in_cart ) {
// Loop through each item in the cart again
foreach ( $cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
// Check if the product has category B
if ( has_term( 'categoryb', 'product_cat', $product->get_id() ) ) {
$discount_amount += $cart_item['line_total'] * 0.1;
$cart_item['data']->set_price( $cart_item['data']->get_price() * 0.9 );
}
}
// Add the discount amount as a fee
$cart->add_fee( 'Discount', -$discount_amount, true );
}
}

Related

Remove percent coupon if discounted price of product is more than 10%

I need to remove / disable the coupon effect for products discounted by more than 10%.
At the moment I have something like this:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$excluded_categories = array( 'prod_category_name' );
// Initialize
$coupon_flag = false;
// Loop through applied coupons
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'percent_product' ) ) ) {
$coupon_flag = true;
break;
}
}
foreach( $cart->get_applied_coupons() as $coupon_code ) {
// Get the WC_Coupon object
$coupon = new WC_Coupon($coupon_code);
$coupon_amount = $coupon->get_amount(); // Get coupon amount
}
if ( $coupon_flag ) {
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get product ID in
$product_id = $cart_item['product_id'];
// NOT contains the definite term
if ( ! has_term( $excluded_categories, 'product_cat', $product_id ) ) {
// Get regular price
$regular_price = $cart_item['data']->get_regular_price();
// Get promo price
$promo_price = $cart_item['data']->get_price();
// Zniżka
$discount = 100 - (($promo_price * 100) / $regular_price);
$percentage = 10;
$percent_price = $regular_price - ($regular_price * ($percentage / 100));
if ($discount > $coupon_amount ) {
//$coupon->set_amount(0);
$cart->remove_coupon( 'coupon_name' );
}
if ( $percent_price < $promo_price ) {
$cart_item['data']->set_price( $regular_price );
} else {
$cart_item['data']->set_price( $promo_price );
}
}
}
}
}
At the moment, the code removes the coupon for the entire cart:
$cart->remove_coupon( 'coupon_name' );
Is there an option to remove the discount for the selected product from the cart?
I need something like:
$cart_item['data']->remove_coupon( 'coupon_name' );
Thank you so much!
Ok I added filter and it works perfect =)
add_filter( 'woocommerce_coupon_is_valid_for_product', 'exclude_product_from_product_promotions_frontend', 9999, 4 );
function exclude_product_from_product_promotions_frontend( $valid, $product, $coupon, $values ) {
$regular_price = $product->get_regular_price();
$promo_price = $product->get_price();
$discount = 100 - (($promo_price * 100) / $regular_price);
$coupon_amount = 10;
if ($discount > $coupon_amount ) {
$valid = false;
}
return $valid;
}

Change product sale price to regular price in WooCommerce cart when a coupon is applied, but exclude certain categories

When a coupon is applied (belonging to a certain type) I change the product discount price to the regular price via:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $cart_object) {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$coupon = False;
if ($coupons = WC()->cart->get_applied_coupons() == False )
$coupon = False;
else {
foreach ( WC()->cart->get_applied_coupons() as $code ) {
$coupons1 = new WC_Coupon( $code );
if ($coupons1->type == 'percent_product' || $coupons1->type == 'percent')
$coupon = True;
}
}
if ($coupon == True)
foreach ( $cart_object->get_cart() as $cart_item )
{
$price = $cart_item['data']->regular_price;
$cart_item['data']->set_price( $price );
}
}
But if I have a category excluded, the code freaks out because it changes the price from sale to regular in the cart and does not add a discount.
How to work around this so that the excluded category does not change to the regular price?
To exclude certain categories you can use has_term() when loop through the cart items
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$excluded_categories = array( 63, 15, 'categorie-1' );
// Initialize
$coupon_flag = false;
// Loop through applied coupons
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'percent_product' ) ) ) {
$coupon_flag = true;
break;
}
}
// True
if ( $coupon_flag ) {
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get product ID in
$product_id = $cart_item['product_id'];
// NOT contains the definite term
if ( ! has_term( $excluded_categories, 'product_cat', $product_id ) ) {
// Get regular price
$regular_price = $cart_item['data']->get_regular_price();
// Set new price
$cart_item['data']->set_price( $regular_price );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );

Discount for a specific product category in WooCommerce cart based on quantity and multiples

The discount I currently have essentially says
If 6 products within a specific category are in the cart --- discount the total price of $10
This piece of the code works fine. My issue is, this does not work
If there are 7 products, the 7th product being from a different category.
My goal is to give the discount no matter how many products are in the cart so long as there are 6 products within "Category A".
The following code works so long as there is 6 products in the "discounted category" or there is 1 product with a quantity of 6 etc. It falls apart when I add a product from another category. Feel free to rip it apart.
add_action( 'woocommerce_before_calculate_totals', 'this_item_free' );
function this_item_free() {
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$valid_product_category_id = array('soup-mix');
$has_category = false;
$count = WC()->cart->get_cart_contents_count();
foreach ( WC()->cart->get_cart() as $product ) {
$quantity = $product['quantity'];
$price = $product['data']->get_price();
}
if ( has_term( $valid_product_category_id, 'product_cat', $product['product_id'],
$product['quantity'] ) ) {
$has_category = true;
$cart_total = floatval( preg_replace( '#[^\d.]#', '', WC()->cart->get_cart_total() ) );
if($count == 6 && $has_category = true){
add_action( 'woocommerce_cart_calculate_fees', 'discount_based_on_total', 25, 1 );
function discount_based_on_total( $cart ) {
$total = $cart->cart_contents_total;
$discount = 9.95;
$cart->add_fee( __('discount', 'woocommerce'), -$discount );
wc_add_notice( apply_filters( 'discount_applied', 'You just got a free soup!') );
}
}
}
}
Your code contains some unnecessary steps and what you want to achieve can be obtained with just the woocommerce_cart_calculate_fees action hook
My answer contains:
Give a discount no matter how many products are in the cart so long as there are 6 products or there is 1 product with a quantity of 6, etc.. within "Category A".
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
/* SETTINGS */
// Specific categories
$specific_categories = array( 'Categorie-A' );
// Discount
$discount = 10;
// Min quantity
$minimun_quantity = 6;
/* END SETTINGS */
// Counter
$current_quantity = 0;
// Loop though each cart item
foreach ( $cart->get_cart() as $cart_item ) {
// Get product id
$product_id = $cart_item['product_id'];
// Has certain category
if ( has_term( $specific_categories, 'product_cat', $product_id ) ) {
// Quantity
$product_quantity = $cart_item['quantity'];
// Add to total
$current_quantity += $product_quantity;
}
}
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
To apply the discount per 6 products (6 = $10, 12 = $20, 18 = $30, etc..)
Replace
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
With
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Modulo
$mod = $current_quantity % $minimun_quantity;
// Times it fit
$times = ( $current_quantity - $mod ) / $minimun_quantity;
// Discount * times
$discount = $discount * $times;
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}

Add discount per certain number of products on the cheapest products in WooCommerce

I'm adding the discount rule for every 3 products: 3,6,9,12,15.. on the cart and it should apply to discount 50% only the cheapest products.
So if you have 9, only the 3 cheapest gets 50% off.
This code applies a discount to all products, so it should only be every 3 products
add_action('woocommerce_cart_calculate_fees', 'ts_add_custom_discount', 10, 1 );
function ts_add_custom_discount( $wc_cart ){
$discount = 0;
$product_ids = array();
$item_prices = array();
$in_cart = false;
foreach ( $wc_cart->get_cart() as $cart_item_key => $cart_item ) {
$cart_product = $cart_item['data'];
if ( has_term( 'get2', 'product_cat', $cart_product->get_id() ) ) { // get2 selected category
$in_cart = true;
}else {
$in_cart = true;
$product_ids[] = $cart_product->get_id();
$item_prices[$cart_product->get_id()] = $cart_product->get_price();
}
}
if( $in_cart ) {
$count_ids = count($product_ids);
asort( $item_prices ); //Sort the prices from lowest to highest
$cartQuantity = WC()->cart->cart_contents_count;
$count = 0;
if( $count_ids > 3 || $cartQuantity >= 3 ) {
foreach( $item_prices as $id => $price ) {
if( $count >= 1 ) {
break;
}
//$product = wc_get_product( $id );
//$price = $product->get_price();
$discount -= ($price * 50) /100;
$count++;
}
}
}
if( $discount != 0 ){
$wc_cart->add_fee( 'Discount', $discount, true );
}
}
I have attached a screenshot, you can see there is a red outline for every 3rd cheapest product.
This answer will apply a 50% discount per 3 products on the cheapest products. (explanation via comment tags added to the code)
So you get:
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
// Products in cart
$products_in_cart = count( $cart->get_cart() );
// Every so many products
$every = 3;
// When products in cart greater than or equal to every so many products
if ( $products_in_cart >= $every ) {
// 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 = floor( $products_in_cart / $every );
// 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 * 50 ) / 100;
// Discount
$cart->add_fee( __( 'Discount', 'woocommerce' ), -$discount, true );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );

Set 'Zero Tax' for subtotal under $110 - Woocommerce

I'm trying to setup no tax for orders under $110.
I bumped into this thread Set different Tax rates conditionally based on cart item prices in Woocommerce and tried it but doesn't seems to work when i add it on functions.php - Maybe because some of the codes are outdated?
Here's the revised code:
add_action( 'woocommerce_before_calculate_totals', 'change_cart_items_prices', 10, 1 );
function change_cart_items_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
foreach ( $cart->get_cart() as $cart_item ) {
// get product price
$price = $cart_item['data']->get_price();
// Set conditionaly based on price the tax class
if ( $price < 111 )
$cart_item['data']->set_tax_class( 'zero-rate' ); // below 111
if ( $price >= 111 )
$cart_item['data']->set_tax_class( 'standard' ); // Equal above 110
}
}
I believe Standard & Zero rates tax options in Woo commerce > Settings > Tax are setup correctly.
Got it working using this code:
add_action( 'woocommerce_before_calculate_totals', 'apply_conditionally_zero_tax_rate', 10, 1 );
function apply_conditionally_zero_tax_rate( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$defined_amount = 110;
$subtotal = 0;
// Loop through cart items (1st loop - get cart subtotal)
foreach ( $cart->get_cart() as $cart_item ) {
$subtotal += $cart_item['line_total'];
}
// Targeting cart subtotal up to the "defined amount"
if ( $subtotal > $defined_amount )
return;
// Loop through cart items (2nd loop - Change tax rate)
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_tax_class( 'zero-rate' );
}
}

Resources