4

I have created a 'BOGOF' (buy one get one free) coupon, using the normal woocommerce coupon method.

The coupon gives the user 100% percentage discount on 1 other item in the cart.


Coupon settings

General:

  • Discount type: Percentage discount Coupon

  • amount: 100

Usage limits:

  • Limit usage to X items: 1

When used:

  • Coupon applies 100% to a random item in the cart (default behavior, I guess)

Desired:

  • It needs to take 100% off the cheapest item in the cart.

With the following code I try to achieve my goal, unfortunately without the desired result

function filter_woocommerce_coupon_get_discount_amount( $discount, $discounting_amount, $cart_item, $single, $instance ) { 
    $price_array = array();

    foreach( $cart_item as $item ) {
        echo $item->price;
        if($item->price > 0){
            array_push($price_array, $item->price);
        }
    }

    $lowestPrice = min($price_array);

    if( $lowestPrice < $discount ){
        $discount = $lowestPrice; 
    }

    return $discount; 
}    
add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_woocommerce_coupon_get_discount_amount', 10, 5 );
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Char
  • 318
  • 2
  • 17

3 Answers3

6

First there is a big mistake in your code as $cart_item variable hook argument is the current cart item but not the cart items array...

The following will apply a coupon discount of 100% on the cheapest cart item (commented code):

add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_wc_coupon_get_discount_amount', 10, 5 );
function filter_wc_coupon_get_discount_amount( $discount_amount, $discounting_amount, $cart_item, $single, $coupon ) { 
    // Define below your existing coupon code
    $coupon_code = 'BOGOF';

    // Only for a defined coupon code
    if( strtolower( $coupon_code ) !== $coupon->get_code() ) 
        return $discount_amount;

    $items_prices = [];
    $items_count  = 0;

    // Loop through cart items
    foreach( WC()->cart->get_cart() as $key => $item ){
        // Get the cart item price (the product price)
        if ( wc_prices_include_tax() ) {
            $price = wc_get_price_including_tax( $item['data'] );
        } else {
            $price = wc_get_price_excluding_tax( $item['data'] );
        }

        if ( $price > 0 ){
            $items_prices[$key] = $price;
            $items_count       += $item['quantity'];
        }
    }

    // Only when there is more than one item in cart
    if ( $items_count > 1 ) {
        asort($items_prices);  // Sorting prices from lowest to highest

        $item_keys = array_keys($items_prices);
        $item_key  = reset($item_keys); // Get current cart item key

        // Targeting only the current cart item that has the lowest price
        if ( $cart_item['key'] == $item_key ) {
            return reset($items_prices); // return the lowest item price as a discount
        }
    } else {
        return 0;
    }
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Thank you so so much Loic! This has really helped me. I am also aware that I am terrible at structuring my questions so thank you so much for re-wording it for me :-D – Char Apr 29 '20 at 11:48
  • Any chance somebody can explain me how to fix a user-determined discount code? I only want to apply 10% on the cheapest item but I can't find a solution... – Niels Apr 24 '21 at 17:09
1

If you want use your own discount not only 100% replace return reset($items_prices); to the return $discount_amount;

ZHR
  • 11
  • 1
0

I made a rather small tweak to this - I noticed that if I had lots of items in my cart, it would give a 100% discount to MULTIPLE of the cheapest product. So if a user had, so 10 t-shirts at £10 each, it was giving a £100 discount. I modified this slightly below, which might help someone in the future:

add_filter('woocommerce_coupon_get_discount_amount', 'tfcc_cheapest_free', 10, 5);
function tfcc_cheapest_free($discount, $discounting_amount, $cart_item, $single, $coupon) {
    // IF TYPE MATCHES PERFORM CUSTOM CALCULATION
    if ($coupon->type == 'cheapest_free'){

      $items_prices = [];
          $items_count  = 0;

          // Loop through cart items
          foreach( WC()->cart->get_cart() as $key => $item ){
              // Get the cart item price (the product price)
              if ( wc_prices_include_tax() ) {
                  $price = wc_get_price_including_tax( $item['data'] );
              } else {
                  $price = wc_get_price_excluding_tax( $item['data'] );
              }

              if ( $price > 0 ){
                  $items_prices[$key] = $price;
                  $items_count       += $item['quantity'];
              }
          }

          // Only when there is more than one item in cart
          if ( $items_count > 1 ) {
              asort($items_prices);  // Sorting prices from lowest to highest

              $item_keys = array_keys($items_prices);
              $item_key  = reset($item_keys); // Get current cart item key

              // Targeting only the current cart item that has the lowest price
              if ( $cart_item['key'] == $item_key ) {
                  return reset($items_prices)/$cart_item['quantity']; // return the lowest item price as a discount
              }
          } else {
              return 0;
          }

    }

}
Rob1982
  • 63
  • 3