// Add custom quantity setting fields to the admin product pages
add_action('woocommerce_product_options_pricing', 'wc_qty_add_product_field');
function wc_qty_add_product_field() {
global $product_object;
// Retrieve existing meta values
$values = $product_object->get_meta('_qty_args');
echo '<div class="options_group quantity hide_if_grouped">
<style>div.qty-args.hidden { display:none; }</style>';
// Checkbox to enable quantity settings
woocommerce_wp_checkbox(array(
'id' => 'qty_args',
'label' => __('Quantity settings', 'woocommerce'),
'value' => !empty($values) ? 'yes' : 'no',
'description' => __('Enable this to show and enable the additional quantity setting fields.', 'woocommerce'),
));
// Quantity arguments container
echo '<div class="qty-args hidden">';
// Minimum Quantity
woocommerce_wp_text_input(array(
'id' => 'qty_min',
'type' => 'number',
'label' => __('Minimum Quantity', 'woocommerce-max-quantity'),
'desc_tip' => true,
'description' => __('Set a minimum allowed quantity limit (a number greater than 0).', 'woocommerce'),
'custom_attributes' => array('step' => 'any', 'min' => '0'),
'value' => isset($values['qty_min']) ? (float) $values['qty_min'] : 0,
));
// Maximum Quantity
woocommerce_wp_text_input(array(
'id' => 'qty_max',
'type' => 'number',
'label' => __('Maximum Quantity', 'woocommerce-max-quantity'),
'desc_tip' => true,
'description' => __('Set the maximum allowed quantity limit (a number greater than 0). Value "-1" is unlimited', 'woocommerce'),
'custom_attributes' => array('step' => 'any', 'min' => '-1'),
'value' => isset($values['qty_max']) ? (float) $values['qty_max'] : -1,
));
// Quantity Step
woocommerce_wp_text_input(array(
'id' => 'qty_step',
'type' => 'number',
'label' => __('Quantity step', 'woocommerce-quantity-step'),
'desc_tip' => true,
'description' => __('Optional. Set quantity step (a number greater than 0)', 'woocommerce'),
'custom_attributes' => array('step' => 'any', 'min' => '0.01'), // Minimum step is 0.01 for decimal support
'value' => isset($values['qty_step']) ? (float) $values['qty_step'] : 0.1, // Default step value as 0.1
));
echo '</div></div>';
}
// Show/hide setting fields (admin product pages)
add_action('admin_footer', 'product_type_selector_filter_callback');
function product_type_selector_filter_callback() {
global $pagenow, $post_type;
if (in_array($pagenow, array('post-new.php', 'post.php')) && $post_type === 'product') :
?>
<script>
jQuery(function($) {
const toggleQtyArgs = function() {
$('div.qty-args').toggleClass('hidden', !$('#qty_args').is(':checked'));
};
toggleQtyArgs();
$('#qty_args').change(toggleQtyArgs);
});
</script>
<?php
endif;
}
// Save quantity setting fields values
add_action('woocommerce_admin_process_product_object', 'wc_save_product_quantity_settings');
function wc_save_product_quantity_settings($product) {
if (isset($_POST['qty_args'])) {
$product->update_meta_data('_qty_args', array(
'qty_min' => isset($_POST['qty_min']) && $_POST['qty_min'] > 0 ? (float) wc_clean($_POST['qty_min']) : 0,
'qty_max' => isset($_POST['qty_max']) ? (float) wc_clean($_POST['qty_max']) : -1,
'qty_step' => isset($_POST['qty_step']) && $_POST['qty_step'] > 0 ? (float) wc_clean($_POST['qty_step']) : 0.1, // Default step is set to 0.1
));
} else {
$product->delete_meta_data('_qty_args'); // Clear settings if not enabled
}
}
// Adjust quantity inputs on the front end
add_filter('woocommerce_quantity_input_args', 'filter_wc_quantity_input_args', 99, 2);
function filter_wc_quantity_input_args($args, $product) {
$values = $product->is_type('variation') ? wc_get_product($product->get_parent_id())->get_meta('_qty_args') : $product->get_meta('_qty_args');
if (!empty($values)) {
// Set min, max, and step values
$args['min_value'] = isset($values['qty_min']) ? (float) $values['qty_min'] : 0;
$args['max_value'] = isset($values['qty_max']) && $values['qty_max'] > 0 ? (float) $values['qty_max'] : null;
$args['step'] = isset($values['qty_step']) ? (float) $values['qty_step'] : 0.1; // Default step is set to 0.1
// Set initial input value if not on cart page
if (!is_cart()) {
$args['input_value'] = $args['min_value'];
}
}
return $args;
}
// Adjust add to cart quantity on shop and archives pages
add_filter('woocommerce_loop_add_to_cart_args', 'filter_loop_add_to_cart_quantity_arg', 10, 2);
function filter_loop_add_to_cart_quantity_arg($args, $product) {
$values = $product->get_meta('_qty_args');
if (!empty($values) && isset($values['qty_min']) && $values['qty_min'] > 0) {
$args['quantity'] = (float) $values['qty_min']; // Ensure quantity is set as float
}
return $args;
}
// Apply quantity settings for variable products
add_filter('woocommerce_available_variation', 'filter_wc_available_variation_price_html', 10, 3);
function filter_wc_available_variation_price_html($data, $product, $variation) {
$values = $product->get_meta('_qty_args');
if (!empty($values)) {
$data['min_qty'] = isset($values['qty_min']) ? (float) $values['qty_min'] : 0;
$data['max_qty'] = isset($values['qty_max']) && $values['qty_max'] > 0 ? (float) $values['qty_max'] : null;
// Adjust max_qty based on stock management settings
if ($variation->managing_stock() && !$variation->backorders_allowed()) {
$data['max_qty'] = min($variation->get_stock_quantity(), $data['max_qty']);
}
}
return $data;
}
I'm looking for a way to set a decimal product quantity for each product in my woocommerce store. I have used already found code as a basis ( Set quantity minimum, maximum and step at product level in Woocommerce ), as different products in my store have different min/max values and quantity increments. I improved the code by giving it the ability to count decimal digits. They are applied in the product settings page, in the product page, but now I have a problem that the selected product quantity in the shopping cart is rounded. I can't find a way to solve this problem, maybe someone has already encountered a similar problem? The code snippet above is improved code with decimals