Product Minimum Quantity and Step per Product

Allows you to set minimum quantity and increment step for each product in WooCommerce.

PHP
 /**
 * Snippet Name:     Product Minimum Quantity and Step per Product
 * Snippet Author:   coding-bunny.com
 * Description:      Allows you to set minimum quantity and increment step for each product in WooCommerce.
 * Version:          1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

function cbedd_add_qty_fields_to_product() {
    global $post;

    $min_qty  = get_post_meta( $post->ID, '_cbedd_min_qty', true );
    $qty_step = get_post_meta( $post->ID, '_cbedd_qty_step', true );

    woocommerce_wp_text_input( array(
        'id'                => '_cbedd_min_qty',
        'label'             => __( 'Minimum Order Quantity', 'cbedd' ),
        'desc_tip'          => true,
        'description'       => __( 'Set the minimum quantity allowed for this product.', 'cbedd' ),
        'type'              => 'number',
        'custom_attributes' => array(
            'min'  => '1',
            'step' => '1',
        ),
        'value'             => esc_attr( $min_qty ),
    ) );

    woocommerce_wp_text_input( array(
        'id'                => '_cbedd_qty_step',
        'label'             => __( 'Quantity Step', 'cbedd' ),
        'desc_tip'          => true,
        'description'       => __( 'Set the increment/decrement step for this product.', 'cbedd' ),
        'type'              => 'number',
        'custom_attributes' => array(
            'min'  => '1',
            'step' => '1',
        ),
        'value'             => esc_attr( $qty_step ),
    ) );
}
add_action( 'woocommerce_product_options_inventory_product_data', 'cbedd_add_qty_fields_to_product' );

function cbedd_save_qty_fields( $post_id ) {
    if ( ! isset( $_POST['woocommerce_meta_nonce'], $_POST['_cbedd_min_qty'], $_POST['_cbedd_qty_step'] ) ) {
        return;
    }

    $min_qty = isset( $_POST['_cbedd_min_qty'] ) ? absint( $_POST['_cbedd_min_qty'] ) : '';
    if ( $min_qty > 0 ) {
        update_post_meta( $post_id, '_cbedd_min_qty', $min_qty );
    } else {
        delete_post_meta( $post_id, '_cbedd_min_qty' );
    }

    $qty_step = isset( $_POST['_cbedd_qty_step'] ) ? absint( $_POST['_cbedd_qty_step'] ) : '';
    if ( $qty_step > 0 ) {
        update_post_meta( $post_id, '_cbedd_qty_step', $qty_step );
    } else {
        delete_post_meta( $post_id, '_cbedd_qty_step' );
    }
}
add_action( 'woocommerce_process_product_meta', 'cbedd_save_qty_fields' );

function cbedd_filter_min_qty( $min_value, $product ) {
    $product_min = get_post_meta( $product->get_id(), '_cbedd_min_qty', true );
    if ( $product_min && is_numeric( $product_min ) && $product_min > 0 ) {
        $min_value = absint( $product_min );
    }
    return $min_value;
}
add_filter( 'woocommerce_quantity_input_min', 'cbedd_filter_min_qty', 10, 2 );

function cbedd_filter_qty_step( $step, $product ) {
    $product_step = get_post_meta( $product->get_id(), '_cbedd_qty_step', true );
    if ( $product_step && is_numeric( $product_step ) && $product_step > 0 ) {
        $step = absint( $product_step );
    }
    return $step;
}
add_filter( 'woocommerce_quantity_input_step', 'cbedd_filter_qty_step', 10, 2 );

function cbedd_validate_cart_item_quantity( $passed, $product_id, $quantity ) {
    $min_qty  = get_post_meta( $product_id, '_cbedd_min_qty', true );
    $qty_step = get_post_meta( $product_id, '_cbedd_qty_step', true );

    if ( $min_qty && is_numeric( $min_qty ) && $min_qty > 0 && $quantity < $min_qty ) {
        wc_add_notice(
            sprintf(
                esc_html__( 'The minimum order quantity for %1$s is %2$d.', 'cbedd' ),
                get_the_title( $product_id ),
                absint( $min_qty )
            ),
            'error'
        );
        $passed = false;
    }

    if ( $qty_step && is_numeric( $qty_step ) && $qty_step > 0 ) {
        $min = $min_qty && $min_qty > 0 ? $min_qty : 1;
        if ( ( $quantity - $min ) % $qty_step !== 0 ) {
            wc_add_notice(
                sprintf(
                    esc_html__( 'Please order %1$s in quantities of %2$d.', 'cbedd' ),
                    get_the_title( $product_id ),
                    absint( $qty_step )
                ),
                'error'
            );
            $passed = false;
        }
    }

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

function cbedd_cleanup_on_product_delete( $post_id ) {
    if ( get_post_type( $post_id ) === 'product' ) {
        delete_post_meta( $post_id, '_cbedd_min_qty' );
        delete_post_meta( $post_id, '_cbedd_qty_step' );
    }
}
add_action( 'before_delete_post', 'cbedd_cleanup_on_product_delete' );

How To Implement This Solution?

Leave a Reply