Search code examples
phpwordpresswoocommercecartproduct-quantity

Set the minimum order quantity for Simple and Variable Products on WooCommerce


I'm new to WooCommerce and PHP, and I'm planning to add a field for simple and variable products in WooCommerce where I can control the minimum order quantity.

Based on this, for example, when it is set to 10, the WooCommerce shopping cart counter should be automatically changed to that number and the user cannot reduce the value for the order because the minimum order quantity has been set to 10.

So I want the lowest minimum order quantity (as only one minimum order quantity can be used for cart)

Here is my code:

/*Minimum Order - Simple & Variable Product*/
// Add minimum order field to product options
function add_minimum_order_field() {
    global $product_object;

    woocommerce_wp_text_input(
        array(
            'id' => 'minimum_order',
            'class' => 'wc_input_price short',
            'label' => 'Minimim Order',
            'desc_tip' => true,
            'description' => 'Set mimimum order for this product',
            'value' => get_post_meta($product_object->get_id(), 'minimum_order', true), // Populate the field with the saved value
        )
    );
}
add_action('woocommerce_product_options_pricing', 'add_minimum_order_field');

// Save minimum order field value
function save_minimum_order_field($product) {
    $minimum_order = isset($_POST['minimum_order']) ? wc_clean($_POST['minimum_order']) : '';
    $product->update_meta_data('minimum_order', $minimum_order);
}
add_action('woocommerce_admin_process_product_object', 'save_minimum_order_field');

// Add minimum order field to product variations
function add_minimum_order_field_to_variations($loop, $variation_data, $variation) {
    woocommerce_wp_text_input(
        array(
            'id' => 'minimum_order[' . $variation->ID . ']',
            'class' => 'wc_input_price short',
            'label' => 'Minimim Order',
            'desc_tip' => true,
            'description' => 'Set mimimum order for this variation',
            'value' => get_post_meta($variation->ID, 'minimum_order', true), // Populate the field with the saved value
        )
    );
}
add_action('woocommerce_variation_options_pricing', 'add_minimum_order_field_to_variations', 10, 3);

// Save minimum order field value for product variations
function save_minimum_order_field_for_variations($variation_id, $i) {
    $minimum_order = isset($_POST['minimum_order'][$variation_id]) ? wc_clean($_POST['minimum_order'][$variation_id]) : '';
    update_post_meta($variation_id, 'minimum_order', $minimum_order);
}
add_action('woocommerce_save_product_variation', 'save_minimum_order_field_for_variations', 10, 2);

// Validate minimum order on add to cart
function validate_minimum_order($passed, $product_id, $quantity) {
    $minimum_order = get_post_meta($product_id, 'minimum_order', true);

    if ($quantity < $minimum_order) {
        wc_add_notice(sprintf('the minimum order must be %s.', $minimum_order), 'error');
        $passed = false;
    }

    return $passed;
}
add_filter('woocommerce_add_to_cart_validation', 'validate_minimum_order', 10, 3);

But make it work as I expected as I need to get lowest minimum order quantity to be applied to the cart.

How to set the minimum order quantity for Simple and Variable Products based on the lowest minimum order quantity from cart items?


Solution

  • I have revisited your code as there were some mistakes.

    For a global minimum order total item quantity (based on the lowest minimum order), the validation needs to be made on the cart, but not on individual products on add to cart. So if the required (lowest) minimum order is not met, an error message will be displayed in cart, blocking checkout access.

    enter image description here

    Try the following:

    // Display a minimum order input field to product options pricing
    add_action('woocommerce_product_options_pricing', 'add_minimum_order_field');
    function add_minimum_order_field() {
    
        woocommerce_wp_text_input( array(
            'id'            => 'minimum_order',
            'type'          => 'number',
            'class'         => 'short',
            'label'         => 'Minimum order',
            'desc_tip'      => true,
            'description'   => 'Set minimum order for this product',
        ) );
    }
    
    // Display a minimum order input field to product variation options pricing
    add_action('woocommerce_variation_options_pricing', 'add_minimum_order_field_to_variations', 10, 3);
    function add_minimum_order_field_to_variations($loop, $variation_data, $variation) {
    
        woocommerce_wp_text_input( array(
            'id'            => 'minimum_order['.$loop.']',
            'type'          => 'number',
            'wrapper_class' => 'form-row form-row-wide',
            'class'         => 'short',
            'label'         => 'Minimum Order',
            'desc_tip'      => true,
            'description'   => 'Set minimum order for this variation',
            'value'         => get_post_meta($variation->ID, 'minimum_qty', true), 
        ) );
    }
    // Save minimum order field value for products
    add_action('woocommerce_admin_process_product_object', 'save_minimum_order_field');
    function save_minimum_order_field($product) {
        $minimum_order = isset($_POST['minimum_order']) ? esc_attr($_POST['minimum_order']) : '';
        $product->update_meta_data('minimum_order', $minimum_order);
    }
    
    // Save minimum order field value for product variations
    add_action('woocommerce_admin_process_variation_object', 'save_minimum_order_field_for_variations', 10, 2);
    function save_minimum_order_field_for_variations($variation, $i) {
        $minimum_order = isset($_POST['minimum_order'][$i]) ? esc_attr($_POST['minimum_order'][$i]) : '';
        $variation->update_meta_data('minimum_order', $minimum_order);
    }
    
    // Utility function: Get the lowest min order
    function get_lowest_minimum_order() {
        $data_array = []; // Initializing
    
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $item ) {
            $min_order = $item['data']->get_meta('minimum_order');
    
            if ( empty($min_order) && $item['variation_id'] > 0 ) {
                // if variation minimum order is not defined take the parent product minimum order  
                $min_order = get_post_meta($item['product_id'], 'minimum_order', true);
            }
    
            if ( ! empty($min_order) ) {
                $data_array[] = $min_order;
            }
        }
        return min($data_array);
    }
    
    // Cart items validation
    add_action( 'woocommerce_check_cart_items', 'minimum_order_cart_items_validation' );
    function minimum_order_cart_items_validation() {
        $minimum_order    = get_lowest_minimum_order();
        $cart_total_count = WC()->cart->get_cart_contents_count();
    
        if ( ! empty($minimum_order) && $cart_total_count < $minimum_order ) {
            wc_add_notice(sprintf('The minimum order total items quantity must be %s.', $minimum_order), 'error');
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work.


    If you want to set a minimum order total item quantity, based on the **HIGHEST minimum order, just change:

    return min($data_array);
    

    to:

    return max($data_array);