Артём Мáлков

Дробное количество товара в WooCommerce

6 апр47 комм

На данный момент существует большое количество разнообразных интернет-магазинов. Одни продают электронные товары (ключи для игр, книги, фильмы и прочее), другие же реализуют материальную продукцию – стулья, столы, различную технику. Все эти товары продаются поштучно, что вполне логично для такого типа товаров. Но если вы продаете обои, различные сыпучие материалы или, например, чай, то там в распоряжении покупателя должна быть не только сама продукция, но и ее определенная единица. Например, 10 метров, 300 граммов и прочее.

По умолчанию, в CMS WordPress, а именно в её дополнении WooCommerce нет поддержки дробного количества товаров, и готовых плагинов, решая эту задачу, я также не смог найти, за исключением нескольких, которые во много усложняют процесс реализации.

А зачем, собственно, усложнять, когда можно сделать все как никогда просто? Для реализации этой задачи вам потребуется воспользоваться несколькими несложными функциями. А именно:

function fractional_amount($args, $product) {
	
	if(!is_cart()) {
		
		$args['input_value'] = 0.5; // Стартовое значение для карточки товара
	
	}
	
	$args['min_value'] = 0.5; // Минимальное значение
	$args['step'] = 0.5; // Шаг
	
	return $args;

}

add_filter('woocommerce_quantity_input_args', 'fractional_amount', 10, 2);

для переопределения стартового и минимального значения, а также шага в товаре и корзине,

// Удаление и добавление своего фильтра проверки чисел

remove_filter('woocommerce_stock_amount', 'intval');
add_filter('woocommerce_stock_amount', 'floatval');

для того, чтобы переопределить проверку на целое число и добавить возможность указания дробного.

Функцию вы настраиваете в зависимости от ваших задач, и по итогу весь код вставляете в низ файла functions.php, который находится в папке вашей темы.

Дополнительно, если вы используете AJAX-добавление товаров в корзину, вставьте следующую функцию:

function fractional_amount_ajax($args, $product) {
	
	$args['quantity'] = 0.5; // Минимальное значение
	
	return $args;

}

add_filter('woocommerce_loop_add_to_cart_args', 'fractional_amount_ajax', 10, 2);

Она позволит вам переопределить минимальное количество товара, которое будет добавлено, соответственно, через AJAX.

Дробное количество вариативного товара в WooCommerce

На самом деле, все описанное выше работает для всех типов товаров, единственный нюанс – это при выборе вариации товара, минимальное его значение устанавливается стандартное (единица).

Чтобы поправить это, используйте следующую функцию:

function fractional_amount_variation($data, $product, $variation) {
	
	$data['min_qty'] = 0.5; // Минимальное значение
	
	return $data;

}

add_filter('woocommerce_available_variation', 'fractional_amount_variation', 10, 3);

Вставляется все так же в файл functions.php вашей темы.

Дробное количество товара для определенной категории в WooCommerce

Помимо того, что на вашем сайте можно сделать выбор дробного количества товара, данную функцию можно ограничить конкретной категорией.

Для этого во всех функциях код, за исключением строки с return, вы оборачиваете в:

if(has_term(15, 'product_cat', $product->id)) {

	// Код функции

}

Здесь 15 – это ID категории, для которой мы делаем дробное количество. Отрицание (для всех, кроме) будет выглядеть следующим образом:

if(!has_term(15, 'product_cat', $product->id)) {

	// Код функции

}

Пример всех описанных выше функций на примере категории с ID = 15:

function fractional_amount($args, $product) {
	
	if(has_term(15, 'product_cat', $product->id)) {

		if(!is_cart()) {
		
			$args['input_value'] = 0.5; // Стартовое значение для карточки товара
	
		}
	
		$args['min_value'] = 0.5; // Минимальное значение
		$args['step'] = 0.5; // Шаг

	}
	
	return $args;

}

add_filter('woocommerce_quantity_input_args', 'fractional_amount', 10, 2);


function fractional_amount_ajax($args, $product) {
	
	if(has_term(15, 'product_cat', $product->id)) {

		$args['quantity'] = 0.5; // Минимальное значение

	}
	
	return $args;

}

add_filter('woocommerce_loop_add_to_cart_args', 'fractional_amount_ajax', 10, 2);


function fractional_amount_variation($data, $product, $variation) {
	
	if(has_term(15, 'product_cat', $product->id)) {

		$data['min_qty'] = 0.5; // Минимальное значение

	}
	
	return $data;

}

add_filter('woocommerce_available_variation', 'fractional_amount_variation', 10, 3);

Если вам нужно указать не одну категорию, а несколько, ID (в моем случае – 15) замените на массив значений:

[15, 25, 30]

каждое из которых – ID нужной вам категории.

Рекомендуем к просмотру
Разрешаем добавление только одного товара в корзину в WooCommerce
Хаки
Делаем обязательные/необязательные поля в оформлении заказа в WooCommerce
Хаки
Изменяем количество товаров на странице WooCommerce
Хаки
47
комментариев
Форма комментирования этого поста скрыта. Авторизуйтесь, чтобы расширить привилегии гостевого посещения и получить необходимую помощь от сообщества Pandoge.
    • 1
    1
      •  Пользователь
    2 сен в 20:37

    Большое спасибо за Ваш труд! Все получилось сделать.

    Но столкнулся с проблемой округления остатков товара.

    Синхронизация товара происходит через мой склад+mswoo.

    Допустим количество товара 23,5. при обновлении остатков происходит округление до 23.

    Как можно решить эту проблему? Нужно как-то запретить округление остатков.....

    За ранее спасибо!

    • 3
    1
      •  Пользователь
    31 мар в 20:05

    Артём большое спасибо за Ваш труд! Подскажите пожалуйста, как сделать так же для отдельного продукта? Так как целой в категории есть товары с разным шагом их продаваемого количества, например, на развес и в упаковке. Заранее спасибо!

      • 1
      1066
        •  Команда Pandoge
      изменено 6 апр в 01:34

      Руслан Ли, здравствуйте!

      Условие для одного товара:

      if($product->id == 15) {
      
      	// Код функции
      
      }

      15 - ID товара.

      Условие для нескольких товаров (и в том числе, для одного, более универсальный вариант):

      if(in_array($product->id, [15, 17, 19])) {
      
      	// Код функции
      
      }

      15, 17, 19 - массив с ID товаров.

    • 1
    5
      •  Проверенный
    6 ноя в 14:35

    Артём огромное спасибо, отличная статья. Но есть один нюанс, при изменении шага с 0.5 на 0.1 на странице товара начинает отображаться количество товара с огромным кол-вом лишних знаков. Подскажите пожалуста куда копать?

    https://100tex.com.ua/shop/tkani/velvet/miss/

      • 1
      1066
        •  Команда Pandoge
      6 ноя в 17:37

      Юрий Ш, по ссылке, кажется, всё нормально. В каком браузере повторяется?

      • 1
      5
        •  Проверенный
      6 ноя в 19:54

      Артём Мáлков, Браузер Chrome и Opera. Когда стоит шаг 0,5 всё работает нормално, но когда шаг стоит 0,1 то очерёдность выглядет так (0,5 > 0.6 > 0.7 > 0.79999999999 > 0.89999999 > 0,99999999 > 1,099999999 > 1.2 > 1.3 > 1.4000001 > 1.5000002 > 1.6000003 .... и т.д.

      • 1
      1066
        •  Команда Pandoge
      изменено 7 ноя в 19:04

      Юрий Ш, возможно дело в скрипте темы - /wp-content/themes/porto/js/woocommerce-theme.min.js

      Попробуйте произвести в нём такие замены.

      1.

      t.val(i):t.val(o+parseFloat(r))

      на

      t.val(i.toFixed(1)):t.val((o+parseFloat(r)).toFixed(1))

      2.

      t.val(a):o>0&&t.val(o-parseFloat(r))

      на

      t.val(a.toFixed(1)):o>0&&t.val((o-parseFloat(r)).toFixed(1))

      Добавляемое

      .toFixed(1)

      это оставляемое количество знаков после точки.

      • 1
      5
        •  Проверенный
      8 ноя в 14:46

      Артём Мáлков, Заменил, ничего не поменялось.

      • 1
      1066
        •  Команда Pandoge
      изменено 8 ноя в 16:01

      Юрий Ш, я не вижу изменений на сайте. Вероятно, у вас какой-то плагин кэширует файлы. Почистите кэш, должно решить проблему.

      • 1
      5
        •  Проверенный
      8 ноя в 17:59

      Артём Мáлков, файл .min генерируется с другого файла может в нём нужно что-то изменить чтобы заработало?

      https://drive.google.com/file/d/1FVlo-pSDieU78eFDq1AfZafOuWgx45J9/view?usp=sharing

      • 1
      1066
        •  Команда Pandoge
      изменено 9 ноя в 00:35

      Юрий Ш, пробовали очистить кэш сайта?

      • 1
      5
        •  Проверенный
      10 ноя в 22:29

      Артём Мáлков, да пробовал.

      • 1
      1066
        •  Команда Pandoge
      11 ноя в 11:06

      Юрий Ш, я вижу, что файлы в кэше по прежнему старые. У вас установлен плагин WP Rocket - в нём чистили кэш? Дополнительно нужно очистить его в теме сайта.

    • 1
    1
      •  Пользователь
    24 авг в 16:54

    Артем спасибо большое, отличная статья. Все работает, за исключение одного и не пойму куда копать:

    На странице оформление заказа не меняется дробное число, то есть всегда стоит минимальное, хотя на самом деле там другое число. ТО есть все считается правильно, сумма правильная, но отображается не правильное число

    вот скрин - https://ibb.co/LdNZsy7

    вот код

    function fractional_amount($args, $product) {
    	
    	if(has_term(15, 'product_cat', $product->id)) {
    
    		if(has_term(15, 'product_cat', $product->id)) {
    		
    			$args['input_value'] = 0.3; // Стартовое значение для карточки товара
    	
    		}
    	
    		$args['min_value'] = 0.3; // Минимальное значение
    		$args['step'] = 0.1; // Шаг
    
    	}
    	
    	return $args;
    
    }
    
    add_filter('woocommerce_quantity_input_args', 'fractional_amount', 10, 2);
    
    
    // Удаление и добавление своего фильтра проверки чисел
    
    remove_filter('woocommerce_stock_amount', 'intval');
    add_filter('woocommerce_stock_amount', 'floatval');
      • 1
      1066
        •  Команда Pandoge
      26 авг в 14:58

      Павел Капотов, здравствуйте!

      1. Зачем два одинаковых условия?

      if(has_term(15, 'product_cat', $product->id)) {
      
      		if(has_term(15, 'product_cat', $product->id)) {

      2. Вы убрали важное условие из статьи (Исключить стартовое значение со страницы корзины):

      if(!is_cart()) {

      Итоговый вариант должен быть таким:

      function fractional_amount($args, $product) {
      		
      		if(has_term(15, 'product_cat', $product->id)) {
      			
      			if(!is_cart()) {
      
      				$args['input_value'] = 0.3; // Стартовое значение для карточки товара
      
      			}
      		
      			$args['min_value'] = 0.3; // Минимальное значение
      			$args['step'] = 0.1; // Шаг
      
      		}
      		
      		return $args;
      
      	}
      
      	add_filter('woocommerce_quantity_input_args', 'fractional_amount', 10, 2);
      
      
      	// Удаление и добавление своего фильтра проверки чисел
      
      	remove_filter('woocommerce_stock_amount', 'intval');
      	add_filter('woocommerce_stock_amount', 'floatval');
    • 2
    4
      •  Пользователь
    31 мар в 13:59

    Добрый день!

    Можете подсказать, всё работает, но при открытии корзины в шаблоне, там остаются целые числа и шаг "1".

      • 3
      1066
        •  Команда Pandoge
      6 апр в 00:47

      vit, здравствуйте!

      Обновили статью

      • 2
      4
        •  Пользователь
      9 апр в 17:47

      Артём Мáлков, Спасибо! Это супер просто.

    • 2
    1
      •  Пользователь
    16 ноя в 11:09

    Здравствуйте. Всё работает. Но есть пара моментов:

    1. при изменении количества товара (шаг 0.1), добавляются лишние знаки после запятой (1.2000000000000002). Не понимаю как исправить. Но в корзине отображается корректно.

    2. Еще нужно, чтобы можно было указывать значения через запятую. По дефолту дробная часть отделяется точкой, но так же надо сделать чтобы можно было самому писать количество, при этом указывая через запятую. В данный момент, если указать через запятую, идет округление. Если дробь меньше 5, то будет число один (пример число выше), если больше, то уже 2.

    Буду признателен за помощь. Не один день ломаю с эти голову, ничего не получается

    • 1
    1
      •  Пользователь
    15 авг в 19:55

    Здравствуйте, всё круто работает, но нигде не нашёл решения проблемы.

    У меня в одной категории есть товары, которые содержат и дробные и целые значения.

    Нашёл решение как сделать не дробной категории, но как сделать в категории с дробными значениями, товары с целым значением?

      • 1
      1066
        •  Команда Pandoge
      22 авг в 21:34

      Дмитрий Антуфьев, здравствуйте!

      Не совсем понял Ваш вопрос.

    • 4
    1
      •  Пользователь
    20 мая в 13:19

    Спасибо большое за этот урок. Но у меня тут возникла небольшая проблема. Когда нажимаешь купить на странице товара, все отлично. Но если в каталоге магазина, то добавляет в корзину только по одной единице товара.

    Помоги решить проблему. sweat Пожалуйста!

      • 3
      1066
        •  Команда Pandoge
      22 авг в 21:32

      Кирилл, проблема актуальна? Какие плагины установлены?

    • 2
    1
      •  Пользователь
    16 мая в 01:19

    Доброго дня, все работает, только

    вот эта надпись woocommerce_quantity<?php вверху магазина confuse

      • 1
      1066
        •  Команда Pandoge
      22 авг в 21:31

      Антон на Море, здравствуйте!

      Вероятнее всего допустили ошибку при вставке кода.

    • 1
    2
      •  Пользователь
    7 мая в 13:13

    Привет.

    А как сделать данную надстройку только для определенных категории?

    Т.е. часть категорий должны продаваться поштучно, а часть категорий должны продаваться дробно.

      • 3
      1066
        •  Команда Pandoge
      9 мая в 12:40

      Василий, Здравствуйте! Попробуйте так.

      Функцию:

      function min_decimal($val) {
      
          return 0.5; // Минимальное значение
      	
      }
      
      add_filter('woocommerce_quantity_input_min', 'min_decimal');

      замените на:

      function min_decimal($val, $product) {
      	
      	if(has_term(25, 'product_cat', $product->id)) {
      	
      		return 0.5; // Минимальное значение
      	
      	}
      	
      }
      
      add_filter('woocommerce_quantity_input_min', 'min_decimal', 10, 2);

      А:

      function step_decimal($val) {
      
          return 0.5; // Шаг
      	
      }
      
      add_filter('woocommerce_quantity_input_step', 'step_decimal');

      замените на:

      function step_decimal($val, $product) {
      	
      	if(has_term(25, 'product_cat', $product->id)) {
      		
      		return 0.5; // Шаг
      		
      	}
      	
      }
      
      add_filter('woocommerce_quantity_input_step', 'step_decimal', 10, 2);

      25 - ID категории.

      • 4
      2
        •  Пользователь
      12 мая в 12:36

      Артём Мáлков, странно, что мне не пришло уведомление о комментарии - хоть я и подписывался.

      В общем Спасибо! Работает.

    • 1
    3
      •  Проверенный
    26 окт в 14:42

    Артем Мáлков, спасибо большое за скрипты, поставил мин. 1, шаг 0,1 подскажите пожалуйста, на странице товара добавляется только один товар, но в корзине это минимальное значение можно убрать, чего не хотелось бы, как это можно исправить?

      • 1
      1066
        •  Команда Pandoge
      27 окт в 00:42

      Эрик Мурадян, Здравствуйте.

      Не совсем понял. В корзине минимальное значение - это 0. И есть выбрано количество 0, то товар удаляется из корзины.

      • 1
      3
        •  Проверенный
      27 окт в 20:15

      Артем Мáлков, но ведь стоит минимальное значение 1, а пользователь в корзине может уменьшать меньше единицы

      • 1
      1066
        •  Команда Pandoge
      27 окт в 22:08

      Эрик Мурадян, покажите пример сайта.

      • 1
      1066
        •  Команда Pandoge
      28 окт в 13:45

      Эрик Мурадян, вся проблема в том, минимум в 1 работает только в товаре. А в корзине минимум - 0. Но по скольку шаг у Вас 0,1 то и в корзине могут сделать меньше 1 до 0. Если предоставите FTP сайта - смогу помочь в решении этой проблемы.

      • 1
      1066
        •  Команда Pandoge
      29 окт в 17:49

      Эрик Мурадян, проверьте, должно работать.

      Сделал:

      1. Скопировал файл cart.php из /wp-content/plugins/woocommerce/templates/cart/ в /wp-content/themes/hestia/woocommerce/cart/

      2. В нем строку 113 заменил на 114.

      • 3
      3
        •  Проверенный
      30 окт в 08:07

      Артем Мáлков, спасибо большое

    • 2
    2
      •  Проверенный
    17 июл в 16:50

    Здравствуйте, Артем. Спасибо большое! Однако, вариативный товар невозможно выбрать 0,5, требует только от 1, однако шаг в 0,5 работает, правда начиная с 1,5. Не подскажете в какую сторону копать?

      • 3
      1066
        •  Команда Pandoge
      17 июл в 20:19

      Семен Кирилов, по хорошему бы, доступы к проблемному сайту, тогда точно смогу сказать в чем проблема.

      • 1
      2
        •  Проверенный
      18 июл в 11:23

      Здравствуйте, Артем. Спасибо за оперативность.Сайт в разработке на localhost. До момента выбора вариации товара (ткань метражом, рулоном и т.п.) минимальное значение срабатывает, но нужно выбрать вариацию чтобы добавить в корзину. - вот на этом шаге и выскакивает "Значение должно быть больше или равно 1"

    • 2
    3
      •  Пользователь
    17 июл в 09:07

    Добрый день.

    Хороший гайд, давно искал как сделать дробные значения. Но одна проблема - перестали работать кнопки увеличения и уменьшения количества товара (на карточке товара и в корзине).

      • 1
      1066
        •  Команда Pandoge
      17 июл в 20:16

      Ан Ку, нужно поправить шаг, всего скорее, с которым идет увеличение / уменьшение значения.

      Где именно это правится не подскажу, так как под рукой нет сайта с Woo.

      • 1
      3
        •  Пользователь
      1 авг в 09:42

      Попробовал менять значение шага, не помогло. Был бы очень признателен, если бы подсказали где править увеличение/уменьшение.cry

      • 3
      1066
        •  Команда Pandoge
      1 авг в 19:58

      Ан Ку,

      > Где именно это правится не подскажу, так как под рукой нет сайта с Woo.

      Можете предоставить доступы к вашему сайту (Админка + FTP), тогда хоть как-то смогу Вам помочь.

      • 2
      1066
        •  Команда Pandoge
      1 авг в 20:01

      Ан Ку, а вообще, разве функция:

      function step_decimal($val) {
      
      	return 0.5; // Шаг
      	
      }
      
      add_filter('woocommerce_quantity_input_step', 'step_decimal');

      не решила Вашу проблему?

      • 1
      3
        •  Пользователь
      2 авг в 10:48

      Функция проблему не решила. Попробовал сделать то же самое через плагин. Работает только в том случае, когда заменяешь свои кнопки +/- на кнопки из плагина (там есть чекбокс на замену стандартных своими).

      Не совсем понятно как отправить личное сообщение с доступами.

      • 1
      1066
        •  Команда Pandoge
      2 авг в 14:24

      Ан Ку, можете через комментарии, можете через форму обратной связи.

    • 1
    1
      •  Пользователь
    21 июн в 06:05

    Привет, Артем. У нас линолеум. Мы сложно реализовали подсчет длины*ширины*цены плагином с кучей костылей.

    Может вы подскажите, как упростить.

    Как сделать чтобы атрибуты умножались на поле "колво" , которое у нас как длина, и на цену(базовая/распродажная)

    Сейчас атрибуты просто плюсуются. Например у нас в атрибутах ширина линолеума, 3.5. Как атрибут умножить на длину, которую пользователь вводит?

    Сейчас сделано через плагин Woo Price, а от него одни беды на сайте. Куча глюков и прочих костылей. Разве нельзя сделать проще? Надо то чтобы умножалось на значение атрибута.

    При этом, у нас есть товар, атрибуты которого умножать не надо, типа обычный выбор цвета.

    То есть есть товар где следует умножать значение атрибута, а где нет.

      • 1
      1066
        •  Команда Pandoge
      21 июн в 15:36

      Ром, здравствуйте. Скоро на сайте будет статья, посвященная переоценке товаров в корзине. Думаю, что она сможет помочь с вашей проблемой.

Подняться наверх
«Pandoge» - помощник вебмастера