How To Force A Minimum Order Quantity In WooCommerce

Sometimes you want to force users and potential customers to order a minimum quantity of certain products. Might it be a minimum quantity of car tiers or maybe some design lamps that come in sets. Unfortunately, WooCommerce does not offer this functionality out of the package. In this article, we will teach you how to force a minimum order quantity in WooCommerce.

Create custom product data meta box

The first thing we need is a customer product data meta box for the product itself so we can save the number of products we want the user to purchase at a minimum. For this, we will create a custom meta box that can be found from the Product data area in “Inventory”.

// Add custom field to the inventory tab in the product data meta box
function action_woocommerce_product_options_stock_status() {        
    woocommerce_wp_text_input(
        array(
            'id'                => '_min_qty',
            'placeholder'       => __( '0', 'woocommerce' ),
            'label'             => __( 'Minimum order quantity', 'woocommerce' ),
            'desc_tip'          => true,
            'description'       => __( 'Number of products user must order at minimum.', 'woocommerce' ),
            'type'              => 'number',
            'custom_attributes' => array(
                'step' => 'any',
            ),
        )
    );
}
add_action( 'woocommerce_product_options_stock_status', 'action_woocommerce_product_options_stock_status', 10, 0 );

// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
    // Isset
    if ( isset( $_POST['_min_qty'] ) ) {        
        // Update
        $product->update_meta_data( '_min_qty', sanitize_text_field( $_POST['_min_qty'] ) );
    }
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );

With this piece of code, we will create a custom meta box as shown in the picture.

Adding the functionality

The second part we need to add is the functionality to check the items in the cart. In the first part, we loop through all the items in the cart to find out what items we have in the cart and how many we have them.

function get_cart_quantity_variable_product( $child_ids ) { 
    // Get cart items quantities
    $cart_item_quantities = WC()->cart->get_cart_item_quantities();
    
    // Counter
    $qty = 0;
    
    // Loop through the childIDs
    foreach ( $child_ids as $child_id ) {
        // Checks if the given key or index exists in the array
        if ( array_key_exists( $child_id, $cart_item_quantities ) ) {
            // Addition
            $qty += $cart_item_quantities[$child_id];
        }
    }
    
    return $qty;
}

function action_woocommerce_check_cart_items() {    
    // Will increment
    $i = 0;
    
    // Will hold information about products that have not met the minimum order quantity
    $bad_products = array();
    
    // Will hold information about which product ID has already been checked so that this does not happen twice (especially applies to products with variants)
    $already_checked = array();
    
    // Loop through cart items
    foreach( WC()->cart->get_cart() as $cart_item ) {
        // Get IDs
        $product_id = $cart_item['product_id'];
        $variation_id = $cart_item['variation_id'];
        
        // NOT in array, already checked? Continue
        if ( ! in_array( $product_id, $already_checked ) ) {            
            // Push to array
            $already_checked[] = $product_id;
            
            // Get the parent variable product for product variation items
            $product = $variation_id > 0 ? wc_get_product( $product_id ) : $cart_item['data'];
            
            // Get meta
            $min_qty = $product->get_meta( '_min_qty', true );
            
            // NOT empty & minimum quantity is greater than or equal to 2 (1 never needs to be checked)
            if ( ! empty( $min_qty ) && $min_qty >= 2 ) {               
                // Get current quantity in cart
                $cart_qty = $cart_item['quantity'];
                
                // Product type = variable & cart quantity is less than the minimum quantity
                if ( $product->get_type() == 'variable' && ( $cart_qty < $min_qty ) ) {                 
                    // Get childIDs in an array
                    $child_ids = $product->get_children();

                    // Call function, get total quantity in cart for a variable product
                    $cart_qty = get_cart_quantity_variable_product( $child_ids );               
                }
                
                // Cart quantity is less than the minimum quantity
                if ( $cart_qty < $min_qty ) {
                    // The product ID
                    $bad_products[$i]['product_id'] = $product_id;
                    
                    // The variation ID (optional)
                    //$bad_products[$i]['variation_id'] = $variation_id;                    
                    
                    // The Product quantity already in the cart for this product
                    $bad_products[$i]['in_cart'] = $cart_qty;
                    
                    // Get the minimum required for this product
                    $bad_products[$i]['min_req'] = $min_qty;
                    
                    // Increment $i
                    $i++;
                }
            }
        }
    }

Create the error message

After checking all the items and their quantities we will show an error message depending if there are enough products or not. We will also be removing the checkout button to ensure users are unable to click to checkout before fixing the error. This means the user needs to either add more products that have minimum order quantity or remove that specific product from their cart to proceed to checkout.

// Error message to inform the customer, about the minimum quantity per order.
    if ( is_array( $bad_products) && count( $bad_products ) > 0 ) { 
        // Clear all other notices          
        wc_clear_notices();
        
        foreach( $bad_products as $bad_product ) {
            // Displaying an error notice
            wc_add_notice( sprintf(
                __( '%s requires a minimum quantity of %d. You currently have %d in cart', 'woocommerce' ),
                get_the_title( $bad_product['product_id'] ),
                $bad_product['min_req'],
                $bad_product['in_cart'],
            ), 'error' );
        }
        
        // Optional: remove proceed to checkout button
        remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
    }
}   
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );

If we update the cart with the minimum required amount of product will be able to see the checkout button and proceed to checkout normally.

Conclusion

In conclusion, creating a minimum quantity requirement is not easy. It takes time a bit of time and effort to build the logic for WooCommerce as well as the error message to ensure users know what’s happening.

Here is the full code one more time so you can easily copy and paste it to your functions.php as needed.

// Add custom field to the inventory tab in the product data meta box
function action_woocommerce_product_options_stock_status() {        
    woocommerce_wp_text_input(
        array(
            'id'                => '_min_qty',
            'placeholder'       => __( '0', 'woocommerce' ),
            'label'             => __( 'Minimum order quantity', 'woocommerce' ),
            'desc_tip'          => true,
            'description'       => __( 'Number of products user must order at minimum.', 'woocommerce' ),
            'type'              => 'number',
            'custom_attributes' => array(
                'step' => 'any',
            ),
        )
    );
}
add_action( 'woocommerce_product_options_stock_status', 'action_woocommerce_product_options_stock_status', 10, 0 );

// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
    // Isset
    if ( isset( $_POST['_min_qty'] ) ) {        
        // Update
        $product->update_meta_data( '_min_qty', sanitize_text_field( $_POST['_min_qty'] ) );
    }
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );



function get_cart_quantity_variable_product( $child_ids ) { 
    // Get cart items quantities
    $cart_item_quantities = WC()->cart->get_cart_item_quantities();
    
    // Counter
    $qty = 0;
    
    // Loop through the childIDs
    foreach ( $child_ids as $child_id ) {
        // Checks if the given key or index exists in the array
        if ( array_key_exists( $child_id, $cart_item_quantities ) ) {
            // Addition
            $qty += $cart_item_quantities[$child_id];
        }
    }
    
    return $qty;
}

function action_woocommerce_check_cart_items() {    
    // Will increment
    $i = 0;
    
    // Will hold information about products that have not met the minimum order quantity
    $bad_products = array();
    
    // Will hold information about which product ID has already been checked so that this does not happen twice (especially applies to products with variants)
    $already_checked = array();
    
    // Loop through cart items
    foreach( WC()->cart->get_cart() as $cart_item ) {
        // Get IDs
        $product_id = $cart_item['product_id'];
        $variation_id = $cart_item['variation_id'];
        
        // NOT in array, already checked? Continue
        if ( ! in_array( $product_id, $already_checked ) ) {            
            // Push to array
            $already_checked[] = $product_id;
            
            // Get the parent variable product for product variation items
            $product = $variation_id > 0 ? wc_get_product( $product_id ) : $cart_item['data'];
            
            // Get meta
            $min_qty = $product->get_meta( '_min_qty', true );
            
            // NOT empty & minimum quantity is greater than or equal to 2 (1 never needs to be checked)
            if ( ! empty( $min_qty ) && $min_qty >= 2 ) {               
                // Get current quantity in cart
                $cart_qty = $cart_item['quantity'];
                
                // Product type = variable & cart quantity is less than the minimum quantity
                if ( $product->get_type() == 'variable' && ( $cart_qty < $min_qty ) ) {                 
                    // Get childIDs in an array
                    $child_ids = $product->get_children();

                    // Call function, get total quantity in cart for a variable product
                    $cart_qty = get_cart_quantity_variable_product( $child_ids );               
                }
                
                // Cart quantity is less than the minimum quantity
                if ( $cart_qty < $min_qty ) {
                    // The product ID
                    $bad_products[$i]['product_id'] = $product_id;
                    
                    // The variation ID (optional)
                    //$bad_products[$i]['variation_id'] = $variation_id;                    
                    
                    // The Product quantity already in the cart for this product
                    $bad_products[$i]['in_cart'] = $cart_qty;
                    
                    // Get the minimum required for this product
                    $bad_products[$i]['min_req'] = $min_qty;
                    
                    // Increment $i
                    $i++;
                }
            }
        }
    }
 
 // Error message to inform the customer, about the minimum quantity per order.
    if ( is_array( $bad_products) && count( $bad_products ) > 0 ) { 
        // Clear all other notices          
        wc_clear_notices();
        
        foreach( $bad_products as $bad_product ) {
            // Displaying an error notice
            wc_add_notice( sprintf(
                __( '%s requires a minimum quantity of %d. You currently have %d in cart', 'woocommerce' ),
                get_the_title( $bad_product['product_id'] ),
                $bad_product['min_req'],
                $bad_product['in_cart'],
            ), 'error' );
        }
        
        // Optional: remove proceed to checkout button
        remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
    }
}   
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );

 

Have questions or confused about something WordPress Related? Join Our Discord Server & ask a Question

Leave a Comment

Your email address will not be published.

Scroll to Top