Thanks to LoicTheAztec I have almost perfect code:
// Free gifted product for specific cart subtotal and no "summer" coupon
add_action( 'woocommerce_before_calculate_totals', 'check_free_gifted_product' );
function check_free_gifted_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Settings
$free_product_id = 90;
$targeted_subtotal = 20;
$coupon_code = "summer"; // coupon code
$cart_subtotal = 0; // Initializing
// Loop through cart items (first loop)
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// When free product is is cart
if ( $free_product_id == $cart_item['product_id'] ) {
$free_key = $cart_item_key;
$free_qty = $cart_item['quantity'];
$cart_item['data']->set_price(0); // Optionally set the price to zero
} else {
$cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// If subtotal match and free product is not already in cart, add it
if ( ! isset($free_key) && $cart_subtotal >= $targeted_subtotal && ! $cart->has_discount( $coupon_code ) ) {
$cart->add_to_cart( $free_product_id );
}
// If subtotal doesn't match or coupon "summer" is applied and free product is already in cart, remove it
elseif ( ( $cart_subtotal < $targeted_subtotal || $cart->has_discount( $coupon_code ) ) && isset($free_key) ) {
$cart->remove_cart_item( $free_key );
}
}
// Display free gifted product price to zero on minicart
add_filter( 'woocommerce_cart_item_price', 'change_minicart_free_gifted_item_price', 10, 3 );
function change_minicart_free_gifted_item_price( $price_html, $cart_item, $cart_item_key ) {
$free_product_id = 90;
if( $cart_item['product_id'] == $free_product_id ) {
return wc_price( 0 );
}
return $price_html;
}
But unfortunately, I have a variant that I didn't specify in Remove free product if specific coupon is applied to cart in WooCommerce previous post and this is fundamental.
If I use another coupon in the above code which is not "summer" but "abc" which has a 100% discount, it also removes the "winter" product for free, some coupons are enough for me to remove "winter" and not everything. Example:
User purchases the product "fish" (id 123) and exceeds €40, receives "winter" as a gift for 0, adds coupon "abc" and gets everything for free ("fish" + "winter")
User B buys the product "fish" (id 123) and exceeds €40, gets "winter" free cost 0, but when he adds the coupon "summer" he only gets the first product ("fish") free but "winter" is taken away.
I need both options.
Here are screenshots for clarification:
Hello, maybe I fixed it, it's not very elegant but it works:
add_action( 'woocommerce_before_calculate_totals', 'check_free_gifted_product' );
function check_free_gifted_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
$free_product_id = 32717;
$targeted_subtotal = 20;
$coupon_codes = array( "abc", "summer", "123" ); // coupon codes
$cart_subtotal = 0; // Initializing
// Loop through cart items (first loop)
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// When free product is is cart
if ( $free_product_id == $cart_item['product_id'] ) {
$free_key = $cart_item_key;
$free_qty = $cart_item['quantity'];
$cart_item['data']->set_price(0); // Optionally set the price to zero
} else {
$cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// If subtotal match and free product is not already in cart, add it
if ( ! in_array( 'abc', $cart->get_applied_coupons() ) &&
! in_array( 'summer', $cart->get_applied_coupons() ) &&
! in_array( '123', $cart->get_applied_coupons() ) &&
! isset( $free_key ) && $cart_subtotal >= $targeted_subtotal ) {
$cart->add_to_cart( $free_product_id );
}
// If coupon "abc" or "summer" is applied and free product is already in cart, remove it
elseif ( ( in_array( 'abc', $cart->get_applied_coupons() ) || in_array( 'abc', $cart->get_applied_coupons() ) ||in_array( '123', $cart->get_applied_coupons() ) ) && isset( $free_key ) ) {
$cart->remove_cart_item( $free_key );
}
}
// Display free gifted product price to zero on minicart
add_filter( 'woocommerce_cart_item_price', 'change_minicart_free_gifted_item_price', 10, 3 );
function change_minicart_free_gifted_item_price( $price_html, $cart_item, $cart_item_key ) {
$free_product_id = 32717;
if( $cart_item['product_id'] == $free_product_id ) {
return wc_price( 0 );
}
return $price_html;
}