phpwordpresswoocommercehook-woocommerce

WooCommerce - Buy 10, get 3 free - only the cheapest 3 are free


I have a client currently who sell line-marking paint, and they want an offer on their site that works in the following way:

If a customer purchases 10+ paints (they can mix and match), they will receive 3 free, but only the cheapest 3, free...

An example is like the below:

I am struggling to accomplish this in WooCommerce, despite trying for longer than I would like to admit!!!

I hope the above makes sense!

Any help or direction would be greatly appreciated!

EDIT:

The code I have so far is below. It returns an array of the cheapest products in the cart, in order, and with their quantities. The issue is that I need to apply the discount to only 3 products, so if the first product in the array only has a quantity of 2, I also need to apply it to the second cheapest... and so on...

function get_cheapest_x_products_in_cart($cat_id)
{

global $woocommerce;
$cat_products = [];
$cheapest_products;


// Add all cart items with correct category to array ($cat_products)
foreach( WC()->cart->get_cart() as $cart_item ) {
    if( has_term( $cat_id, 'product_cat', $cart_item['product_id'])) {
        $product = wc_get_product( $cart_item['product_id'] );
        $price = $product->get_regular_price();
        $cat_products[
            $cart_item['product_id'] ] = [
            'price' => floatval($price),
            'quantity' => $cart_item['quantity'],
        ];
     }
}

  uasort($cat_products, "sort_this");

$cheapest_three_products = array_slice($cat_products, 0, 3, true);
return $cheapest_three_products;

}

Solution

  • Below in this custom function hooked in woocommerce_cart_calculate_fees action hook, customer will get a discount based on the sum of the cheapest 3 items price for each 10 items in cart.

    You will have to define a product category, and optionally you will get a custom notice, when the discount is applied…

    Here is the code:

    add_action( 'woocommerce_cart_calculate_fees', 'free_cheapest_3_each_10_items', 10, 1 );
    function free_cheapest_3_each_10_items( $wc_cart ) {
        if ( is_admin() && ! defined('DOING_AJAX') ) return;
    
        // HERE define your product category (or categories) in the array (IDs slugs or names)
        $cat_id = array('paints');
        $prices = array();
        $cat_id = array('clothing');
        $discount = $items_count = 0;
    
        foreach ( $wc_cart->get_cart() as $cart_item ){
            $sale_price = $cart_item['data']->get_sale_price();
            // Only for the defined product category(ies) and no items in sale
            if( has_term( $cat_id, 'product_cat', $cart_item['product_id']) && ( empty($sale_price) || $sale_price == 0 ) ) {
                for( $i = 0; $i < $cart_item['quantity']; $i++){
                    $prices[] = floatval( $cart_item['data']->get_regular_price() );
                    $items_count++;
                }
            }
        }
    
        if( $items_count >= 10 ){
            // Ordering prices
            asort($prices);
    
            // Get the occurence number for 3 free items each 10 items
            for( $i = 0, $j = -1; $i < $items_count; $i++ )
                if( $i % 10 == 0 ) $j++;
    
            $count = $j*3;
    
            // Get the 3 free items for each 10 items in cart (for the defined product category(ies))
            $free_cheapest_items = array_slice($prices, 0, $count, true);
    
            // Calculate the discount amount
            foreach( $free_cheapest_items as $item_price )
                $discount -= $item_price;
    
            // The discount
            if( $discount != 0 ){
                $wc_cart->add_fee( "Bulk discount", $discount, true );
    
                // Displaying a custom notice (optional)
                wc_clear_notices();
                wc_add_notice( __("You get $count free items for the $items_count items in cart"), 'notice');
            }
        }
    }
    

    Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

    Tested on WooCommerce 3 and works.