skip to Main Content

I have a code in WooCommerce that once you buy products with the ID:
1561, 1919, 1568, 1562, 1563, 1564, 1565, 1566, 1567
So, the second product is NIS 10.

The product on which the discount applies is only the product with ID 1561
The code works well, but as soon as I want to have multiple promotions, it doesn’t work.

For example:
If you buy two products then I want the customer to be able to get product 1561 twice for NIS 10
If you buy five products, then I want the customer to be able to receive five times the product 1561 for NIS 10
And so on…

add_action('woocommerce_before_calculate_totals', 'change_second_item_price', 10, 1);

function change_second_item_price($cart) {
    if (is_admin() && !defined('DOING_AJAX')) {
        return;
    }

    $discounted_product_id = 1561;
    $new_regular_price = 10; // NIS 10

    // Initialize count for the target products
    $target_product_count = 0;

    // Loop through cart items
    foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
        $product_id = $cart_item['product_id'];

        // Check if the product is one of the target products
        if (in_array($product_id, array(1561, 1919, 1568, 1562, 1563, 1564, 1565, 1566, 1567))) {
            $target_product_count += $cart_item['quantity'];

            // Check if it's the discounted product and change the regular price
            if ($product_id == $discounted_product_id && $target_product_count >= 2) {
                $cart_item['data']->set_regular_price($new_regular_price);
                $cart_item['data']->set_price($new_regular_price); // Also set the current price to the regular price
                break; // Stop the loop after changing the regular price for the second item of the discounted product
            }
        }
    }
}

2

Answers


  1. I think you need to first calculate the amount of max discounted product count, and then set the price for the appropriate product:

    add_action('woocommerce_before_calculate_totals', 'change_second_item_price', 10, 1);
    
    function change_second_item_price($cart) {
        if (is_admin() && !defined('DOING_AJAX')) {
            return;
        }
    
        $discounted_product_id = 1561;
        $new_regular_price = 10; // NIS 10
    
        // Initialize count for the target products
        $target_product_count = 0;
    
        // Loop through cart items
        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            $product_id = $cart_item['product_id'];
    
            // Check if the product is one of the target products
            if (in_array($product_id, array(1561, 1919, 1568, 1562, 1563, 1564, 1565, 1566, 1567))) {
                $target_product_count += $cart_item['quantity'];
            }
        }
    
        // Loop through cart items again, to find the discounted product
        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            $product_id = $cart_item['product_id'];
    
                // Check if it's the discounted product and change the regular price
            if ($product_id == $discounted_product_id && $target_product_count >= $cart_item['quantity']) {
                $cart_item['data']->set_regular_price($new_regular_price);
                $cart_item['data']->set_price($new_regular_price); // Also set the current price to the regular price
            }
        }
    }
    

    Keep in mind that this allows customers to always buy 1561 for NIS 10. I think that’s your intention, but I’m not sure.

    Login or Signup to reply.
  2. In the following code, will change the price of a specific cart item (with a minimal quantity of 2), enabled, based and calculated from some defined products count (cart items count).

    You will need to define in the first function:

    • The product ID to be discounted, the active normal price and the desired discounted price.
    • The targeted products IDs that will allow the discount
    // Utility function: Get the discounted product price
    function get_discounted_product_price( $cart_items ) {
        $targeted_products_ids  = array(1919, 1568, 1562, 1563, 1564, 1565, 1566, 1567); 
        $product_id_to_discount = 1561;
        $current_price          = 20; // Here define the product active price
        $discounted_price       = 10; // Here define the discounted price
    
        $targeted_count = $discounted_count = $discounted_key = false; // Initialize variables
    
        // Loop through cart items: Count items
        foreach ( $cart_items as $item_key => $item ) {
            // count targeted products 
            if ( in_array($item['product_id'], $targeted_products_ids) ) {
                $targeted_count += $item['quantity'];
            }
            // count targeted products 
            elseif ( $item['product_id'] == $product_id_to_discount ) {
                $discounted_count += $item['quantity'];
                $discounted_key    = $item_key;
            }
        }
    
        // Calculate new discounted price
        if ( $targeted_count > 1 && $discounted_count > 1 ) {
            $difference_count = $targeted_count - $discounted_count;
    
            if ( $difference_count >= 0 ) {
                $new_price = $discounted_price;
            } else {
                $difference_count = -$difference_count;
                $new_price = (($discounted_price * $targeted_count) + ($current_price * $difference_count)) / $discounted_count;
            }
            return array('key' => $discounted_key, 'price' => floatval($new_price));
        }
        return false;
    }
    
    // change specific cart item price
    add_action( 'woocommerce_before_calculate_totals', 'change_cart_item_price', 100, 1 );
    function change_cart_item_price( $cart ) {
        if ( is_admin() && ! defined('DOING_AJAX') )
            return;
    
        $cart_items = $cart->get_cart();
        $data = get_discounted_product_price( $cart_items );
    
        if ( ! $data ) 
            return;
    
        $cart_items[$data['key']]['data']->set_price($data['price']);
    }
    
    // For minicart: change cart item displayed price html
    add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price_html', 10, 3 );
    function filter_cart_item_price_html( $price_html, $cart_item, $cart_item_key ) {
        $data = get_discounted_product_price( WC()->cart->get_cart() );
    
        if ( isset($data['key']) && $data['key'] === $cart_item_key ) {
            $args = array( 'price' => $data['price'] );
    
            if ( WC()->cart->display_prices_including_tax() ) {
                $product_price = wc_get_price_including_tax( $cart_item['data'], $args );
            } else {
                $product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
            }
            return wc_price( $product_price );
        }
        return $price_html;
    }
    

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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search