0

Hey guys :) I'm trying to implement a custom discount rule to the cart. Basically there is WooCommerce and the site is selling t-shirts. There is a current promotion that if you buy 3 t-shirts, you have to pay only for 2 and the one with the lowest price you get for free. I created a custom function using the hook 'woocommerce_cart_calculate_fees' and so far it's working. Here is my code:

function iom_add_custom_discount( $wc_cart ){
    $discount = 0;
    $product_ids = array();
    $item_prices = array();
    $in_cart = true;

    foreach ( $wc_cart->get_cart() as $cart_item_key => $cart_item ) {
        $cart_product = $cart_item['data'];
        if ( has_term( 'detski-bodita', 'product_cat', $cart_product->get_id() ) ) {
            $in_cart = true;
        }else {
            $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
        
        $count = 0;
        if( $count_ids == 3 ) { 
           foreach( $item_prices as $id => $price ) {
                if( $count >= 1 ) {
                    break;
                }
                //$product = wc_get_product( $id );
                //$price = $product->get_price();
                $discount -= ($price * 100) / 100;
                $count++;
           }
       }

    } 

    if( $discount != 0 ){
        $wc_cart->add_fee( 'Discount', $discount, true  );
        # Note: Last argument in add_fee() method is related to applying the tax or not to the discount (true or false)
    }
}

Here is a screenshot of the cart page --> https://pasteboard.co/JkES3RD.png The discount is displayed and applied. The tricky part I can't get to is, how to make the price of the discounted product striked and display price 0.00 in the table and how to edit the function so in the mini cart still displays 3 products, but to show the discounted price of 2 products? Thanks so much in advance! :)

EDIT: Also, it appears that it only works if I have 3 different products in the cart. If I have 1 product with quantity 2 and 1 product with quantity 1 it's not working.. How to tweak the function to make it work?

0

after quite some headbanging I managed to make it somehow to work. Here is my code:

add_action( 'woocommerce_cart_calculate_fees', 'iom_add_custom_discount', 10, 1 );
function iom_add_custom_discount( $wc_cart ){
    $discount = 0;
    $product_ids = array();
    $product_ids_disc = array();
    $item_prices = array();
    $in_cart = false;
 
    foreach ( $wc_cart->get_cart() as $cart_item_key => $cart_item ) {
        $cart_product = $cart_item['data'];
 
        // here we check if the products in the cart are in category 'detski-bodita'.
        // since these are variation products, we check if their parents have the category.
        // if they do we add them the $in_cart boolean to true.
        if ( has_term( 'detski-bodita', 'product_cat', $cart_product->get_parent_id() ) ) {
            // var_dump(count($in_cart));
            $in_cart = true;
            $product_ids_disc[] = $cart_product->get_id();
            $item_prices[$cart_product->get_id()] = $cart_product->get_price(); 
        } else {
            $product_ids[] = $cart_product->get_id();
            $item_prices[$cart_product->get_id()] = $cart_product->get_price(); 
        }
    }
    // here we check if we have products with $in_cart boolean to true 
    // and if they are in category 'detski-bodita'
    if ( ( $in_cart ) && ( has_term( 'detski-bodita', 'product_cat', $cart_product->get_parent_id() ) ) ) {
        $count_ids = count($product_ids_disc); // We count the items we have
        asort( $item_prices ); // Sort the prices from lowest to highest
 
        $count = 0; // we add another counter for the products that will be discounted.
        // here we check if the minimum amount of products is met for the discount.
        if( $count_ids >= 3 ) { 
            foreach( $item_prices as $id => $price ) {
                if( $count >= 1 ) {
                    break;
                }
 
                //$product = wc_get_product( $id );
                //$price = $product->get_price();
                $discount -= ($price * 100) / 100; // this is the discount that we apply - 100%
                $count++; // increase the counter in order to stop after the max amount of discounted products
           }
       }
 
    }
 
    if( $discount != 0 ){
        $wc_cart->add_fee( 'Отстъпка', $discount, true  );
        # Note: Last argument in add_fee() method is related to applying the tax or not to the discount (true or false)
    }
}

I still have some problems I need to fix. The discount should only be applied if 3 items from the same category are in the cart. For example, the categories are t-shirts and hoodies. If I have 3 t-shirts in my cart, the discount should be applied. If I have 2 t-shirts and 1 hoodie the discount should not be applied. If I have 3 t-shirts and 1 hoodie the discount should be applied. But, it appears that my function only works if I have 3 different products from the same category in the cart. If I have 1 t-shirt with quantity 2 and 1 t-shirt with quantity 1, it’s not working, when it should apply the discount. Also, if I put 3 t-shirts in my cart and 1 hoodie, and then remove 1 t-shirt, the discount is still applied when it shouldn’t.. Any help will be greatly appreciated. Thanks! :)

1
  • As WPSE is a question and answer format I'd suggest string to organise the content from this answer into stuff that is an answer to the original question, then any other comments put those as comments, and if you have new questions start those as new questions. All this content here is not the right place, so you won't get many new answers/responses. – mozboz Aug 6 '20 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.