Skip to content
Advertisement

Multiple bulk dynamic pricing for WooCommerce products with specific product-tag

My intention is to add multiple bulk dynamic pricing for WooCommerce products with specific product-tag. I use the slug “petit-format” on my code.

Based on Bulk dynamic pricing for WooCommerce products with specific product-tag answer code, this is my attempt:

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

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;

    // count tag found
    $tag_found = 0;

    // Loop through cart items, count how many times tag occurs
    foreach ( $cart->get_cart() as $cart_item ) {
        // Get an instance of the WC_Product object
        $product = $cart_item['data'];

        // Get product id
        $product_id = $cart_item['product_id'];

        // if product has tag
        if( has_term( 'petit-format', 'product_tag', $product_id ) ) {

            // Get quantity from product in cart
            $quantity = $cart_item['quantity'];

            // if product quantity > 1
            if ( $quantity > 1) {
                $tag_found = $tag_found + $quantity;
            } else {
                $tag_found += 1;                
            }
        }
    }

    // Define discount rules and thresholds
    $threshold1 = 2; // Change price if items > 2
    $discount1 = 0.142857; // Reduce unit price by 5%
    
    $threshold2 = 3; // Change price if items > 3
    $discount2 = 0.285714; // Reduce unit price by 10%
    
    $threshold3 = 6; 
    $discount3 = 0.428571; 
    
    $threshold4 = 10; 
    $discount4 = 0.5; 
    
    $threshold5 = 20; 
    $discount5 = 0.571429; 
    
    $threshold6 = 50; 
    $discount6 = 0.607143; 
    
    $threshold7 = 100; 

    // if tag found >= $threshold
    if ( $tag_found >= $threshold1 ) {
        // Loop through cart items, add discount
        foreach ( $cart->get_cart() as $cart_item ) {
            // Get an instance of the WC_Product object
            $product = $cart_item['data'];

            // Get product id
            $product_id = $cart_item['product_id'];

            // if product has tag
            if( has_term( 'petit-format', 'product_tag', $product_id ) ) {
                // calculate new price
                $price = round( $cart_item['data']->get_price() * ( 1 - $discount1 ), 2 );

                // set new price
                $cart_item['data']->set_price( $price );
            }
        }
    }
    elseif ( $tag_found >= $threshold2 ) {
        // Loop through cart items, add discount
        foreach ( $cart->get_cart() as $cart_item ) {
            // Get an instance of the WC_Product object
            $product = $cart_item['data'];

            // Get product id
            $product_id = $cart_item['product_id'];

            // if product has tag
            if( has_term( 'petit-format', 'product_tag', $product_id ) ) {
                // calculate new price
                $price = round( $cart_item['data']->get_price() * ( 1 - $discount2 ), 2 );

                // set new price
                $cart_item['data']->set_price( $price );
            }
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 10, 1 );

But I only have the first discount that works, but the other one doesn’t.

So the $discount1 works, but the function doesn’t work with the second discount. Any advice?

My example is with only two discounts, but I need to create more than 10 discounts.

Advertisement

Answer

It is not necessary to go through the entire cart again per condition, apply it in reverse

  • Multiple discounts can be granted through the if/elseif/else conditions
  • I have used WC_Cart::get_cart_item_quantities() versus looping through the cart in the first foreach loop. Since this is faster

So you get

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

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
    
    // Settings
    $term = 'petit-format';
    $taxonomy = 'product_tag';

    // Initialize
    $counter = 0;

    // Loop through cart items, count how many times tag occurs
    foreach( WC()->cart->get_cart_item_quantities() as $product_id => $cart_item_quantity ) {
        // Contains the definite term
        if ( has_term( $term, $taxonomy, $product_id ) ) {
            // Add the cart item quantity from this certain product to the counter
            $counter += $cart_item_quantity;
        }
    }
    
    // Define discount rules and thresholds
    if ( $counter >= 1 ) {
        // Less than or equal to 2
        if ( $counter <= 2 ) {
            $discount = 0.05; // Reduce unit price by 5%
        // Between 2 and 10
        } elseif ( $counter > 2 && $counter <= 10 ) {
            $discount = 0.10; // Reduce unit price by 10%
        // Between 10 and 20
        } elseif ( $counter > 10 && $counter <= 20 ) {
            $discount = 0.20; // Reduce unit price by 20%
        // Between 20 and 50
        } elseif ( $counter > 20 && $counter <= 50 ) {
            $discount = 0.50; // Reduce unit price by 50%
        // Default
        } else {
            $discount = 0.05; // Reduce unit price by 5%            
        }

        // Loop through cart items, add discount
        foreach ( $cart->get_cart() as $cart_item ) {
            // Get product ID in
            $product_id = $cart_item['product_id'];

            // Contains the definite term
            if ( has_term( $term, $taxonomy, $product_id ) ) {
                // calculate new price
                $price = round( $cart_item['data']->get_price() * ( 1 - $discount ), 2 );

                // Set new price
                $cart_item['data']->set_price( $price );
            }
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement