Диагностика задачи: почему нужны разные складские запасы для подразделений
В типовом WooCommerce все товары хранятся в единой базе с одним запасом. Если у вас несколько складов или магазинов (офлайн и онлайн, региональные точки), это создаёт проблему: нельзя управлять остатками раздельно. Клиенты могут купить товар, который на конкретном складе отсутствует, что ведёт к ошибкам в заказах и недовольству.
Чтобы решить эту задачу, необходимо реализовать учёт запасов по подразделениям внутри WooCommerce, сохраняя при этом удобство работы с товарами.
Варианты решения управления запасами по подразделениям
Основные подходы:
- Плагины для мультискладского учёта — расширяют WooCommerce, добавляя поля и логику;
- Кастомные метаполя и хуки — самостоятельная реализация управления запасами с помощью кода;
- Отдельные товары или магазины для каждого склада — менее удобно, но возможно;
Рассмотрим практическую реализацию на базе кастомных метаполей и хуков, чтобы контролировать остатки в разных подразделениях.
Пошаговое решение: кастомный учёт складских запасов по подразделениям
1. Добавляем метаполя для складских запасов
Для каждого товара создадим метаполя для хранения остатков на складах. Например, склад 1 и склад 2.
function add_custom_stock_fields() {
woocommerce_wp_text_input(
array(
'id' => '_stock_warehouse_1',
'label' => __('Stock Warehouse 1', 'woocommerce'),
'desc_tip' => 'true',
'description' => __('Enter stock quantity for Warehouse 1', 'woocommerce'),
'type' => 'number',
'custom_attributes' => array('min' => '0')
)
);
woocommerce_wp_text_input(
array(
'id' => '_stock_warehouse_2',
'label' => __('Stock Warehouse 2', 'woocommerce'),
'desc_tip' => 'true',
'description' => __('Enter stock quantity for Warehouse 2', 'woocommerce'),
'type' => 'number',
'custom_attributes' => array('min' => '0')
)
);
}
add_action('woocommerce_product_options_inventory_product_data', 'add_custom_stock_fields');2. Сохраняем введённые значения
function save_custom_stock_fields($post_id) {
$stock_1 = isset($_POST['_stock_warehouse_1']) ? intval($_POST['_stock_warehouse_1']) : 0;
$stock_2 = isset($_POST['_stock_warehouse_2']) ? intval($_POST['_stock_warehouse_2']) : 0;
update_post_meta($post_id, '_stock_warehouse_1', $stock_1);
update_post_meta($post_id, '_stock_warehouse_2', $stock_2);
}
add_action('woocommerce_process_product_meta', 'save_custom_stock_fields');3. Перекрываем логику проверки остатка товара
По умолчанию WooCommerce использует _stock. Чтобы проверять остаток для нужного склада, нужно указать склад при оформлении заказа, а затем на этапе проверки и списания делать выбор нужного поля.
Пример для выбора склада в корзине через пользовательское поле (например, select с выбором склада):
add_action('woocommerce_before_cart', function() {
echo '<label for="select_warehouse">Выберите склад:</label>';
echo '<select id="select_warehouse" name="select_warehouse">';
echo '<option value="warehouse_1">Склад 1</option>';
echo '<option value="warehouse_2">Склад 2</option>';
echo '</select>';
});Обработка выбранного склада и корректировка проверки остатков:
add_filter('woocommerce_product_is_in_stock', 'check_stock_by_warehouse', 10, 2);
function check_stock_by_warehouse($is_in_stock, $product) {
if (is_admin()) return $is_in_stock; // не трогаем админку
$warehouse = isset($_POST['select_warehouse']) ? sanitize_text_field($_POST['select_warehouse']) : 'warehouse_1';
$stock = 0;
if ($warehouse === 'warehouse_1') {
$stock = intval(get_post_meta($product->get_id(), '_stock_warehouse_1', true));
} elseif ($warehouse === 'warehouse_2') {
$stock = intval(get_post_meta($product->get_id(), '_stock_warehouse_2', true));
} else {
return $is_in_stock;
}
return $stock > 0;
}4. Обновление запасов при заказе
add_action('woocommerce_order_status_processing', 'reduce_stock_by_warehouse', 10, 1);
function reduce_stock_by_warehouse($order_id) {
$order = wc_get_order($order_id);
$warehouse = 'warehouse_1'; // здесь можно получить из заказа или сессии
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$qty = $item->get_quantity();
$stock_key = ($warehouse === 'warehouse_1') ? '_stock_warehouse_1' : '_stock_warehouse_2';
$current_stock = intval(get_post_meta($product_id, $stock_key, true));
update_post_meta($product_id, $stock_key, max(0, $current_stock - $qty));
}
}Проверка результата после внедрения
- В админке товара заполните поля «Stock Warehouse 1» и «Stock Warehouse 2» разными значениями.
- На странице корзины выберите склад через селект и добавьте товар в корзину, убедитесь, что проверка остатков учитывает выбранный склад.
- Оформите заказ и после смените статус на «Обрабатывается» — проверьте, что запасы нужного склада уменьшились.
- Попробуйте добавить товар с нулевым остатком на выбранном складе — должен быть запрет на добавление.
Частые ошибки и как исправить
- Запасы не уменьшаются после заказа: проверьте, что хук
woocommerce_order_status_processingсрабатывает и что склад выбирается корректно. - Выбранный склад не передаётся в корзину: убедитесь, что поле выбора склада отправляется и сохраняется через сессию или пользовательские данные.
- Неверная проверка остатков: проверьте, что фильтр
woocommerce_product_is_in_stockне конфликтует с другими плагинами и правильно получает метаполя.
Практические советы по производительности и безопасности
- Кэшируйте значения складских запасов в transient или объектном кэше на время сессии пользователя, чтобы не нагружать базу при каждом просмотре товара.
- Валидация и санитизация пользовательских данных обязательна — используйте
sanitize_text_fieldиintval. - Разграничьте права доступа к метаполям — только администраторы могут редактировать запасы складов.
- Для упрощения управления и избежания ошибок рассмотрите интеграцию с плагином Clearfy Pro (https://wpshop.ru/plugins/clearfy?utm_source=wp-shablon.ru&utm_medium=article&utm_campaign=woocommerce-kak-pravilno-nastroit-raznye-skaldskie-zapasy-v-podrazdeleniyah-magazina) для дополнительной оптимизации базы и очистки дублей метаданных.
Сравнение вариантов реализации мультискладского учёта
| Подход | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Плагины мультискладского учёта | Готовое решение, поддержка, интеграция с WooCommerce | Стоимость, возможные конфликты, избыточность | Сложные задачи, многоскладовость |
| Кастомные метаполя и хуки | Гибкость, точное подстроение под задачу | Требует разработки, тестирования | Небольшое число складов, уникальные требования |
| Отдельные товары/магазины | Простота реализации | Дублирование данных, неудобство управления | Минимальные требования, экспериментальные проекты |