1

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' );
    }
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399

1 Answers1

2

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.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Using the 2020 theme, the price of the free product does not change into 0 when added to cart. –  Jul 10 '20 at 14:56
  • I get the same result with Storefront. Everything works, except the price of 0 for the free product. –  Jul 10 '20 at 15:02
  • @OscarSmith Sorry Updated, that is the correct working code version… – LoicTheAztec Jul 10 '20 at 15:44
  • Sorry, but it's still the same. –  Jul 10 '20 at 15:51
  • 1
    My sincere apology. I was editing the wrong theme's `functions.php` file (switching between 2020 and Storefront for testing). I'm sorry. It's working as intended now. Thank you. –  Jul 10 '20 at 15:57
  • @OscarSmith You are welcome, no problem… As you are now Happy, I am happy too :) – LoicTheAztec Jul 10 '20 at 16:17