Диагностика проблемы: зачем нужны подразделения в WooCommerce
Многие владельцы WooCommerce сталкиваются с необходимостью управлять товарами на нескольких складах или в разных физических магазинах. По умолчанию WooCommerce не поддерживает разделение запасов по подразделениям, что приводит к неточной информации о наличии товаров, проблемам с логистикой и неудобствам для покупателей.
Основные признаки, что вам нужна настройка подразделений:
- Несколько складов или пунктов выдачи;
- Разные остатки товара на каждом складе;
- Необходимость отображать наличие товара в зависимости от местоположения покупателя;
- Управление запасами отдельно для каждого подразделения.
Пошаговое решение: как организовать подразделения в WooCommerce
1. Выбор подхода: плагин или кастомный код
Существует несколько решений:
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Плагин WooCommerce Multi Locations Inventory | Расширяет стандартный функционал запасов, добавляет возможность хранить остатки по локациям | Быстрая установка, готовый функционал, поддержка | Платный, может грузить сайт |
| Кастомные метаполя и фильтрация наличия | Создание пользовательских полей для складов и модификация логики WooCommerce | Полный контроль, бесплатно | Требует навыков разработки, время на поддержку |
2. Настройка метаполей для складов (примеры кода)
Добавим метаполя для хранения остатков по складам в карточке товара:
add_action('woocommerce_product_options_inventory_product_data', 'add_custom_warehouse_fields');
function add_custom_warehouse_fields() {
woocommerce_wp_text_input(array(
'id' => '_stock_warehouse_1',
'label' => __('Stock Warehouse 1', 'woocommerce'),
'desc_tip' => 'true',
'description' => __('Quantity in warehouse 1', 'woocommerce'),
'type' => 'number',
'custom_attributes' => array('step' => '1', 'min' => '0'),
));
woocommerce_wp_text_input(array(
'id' => '_stock_warehouse_2',
'label' => __('Stock Warehouse 2', 'woocommerce'),
'desc_tip' => 'true',
'description' => __('Quantity in warehouse 2', 'woocommerce'),
'type' => 'number',
'custom_attributes' => array('step' => '1', 'min' => '0'),
));
}
add_action('woocommerce_process_product_meta', 'save_custom_warehouse_fields');
function save_custom_warehouse_fields($post_id) {
$stock1 = isset($_POST['_stock_warehouse_1']) ? intval($_POST['_stock_warehouse_1']) : 0;
update_post_meta($post_id, '_stock_warehouse_1', $stock1);
$stock2 = isset($_POST['_stock_warehouse_2']) ? intval($_POST['_stock_warehouse_2']) : 0;
update_post_meta($post_id, '_stock_warehouse_2', $stock2);
}3. Логика отображения наличия и продажи товаров по складам
Для примера, добавим фильтр, который будет показывать наличие с учётом выбранного склада (через GET-параметр):
add_filter('woocommerce_get_availability', 'filter_stock_by_warehouse', 10, 2);
function filter_stock_by_warehouse($availability, $product) {
$warehouse = isset($_GET['warehouse']) ? sanitize_text_field($_GET['warehouse']) : 'warehouse_1';
$stock_key = '_stock_' . $warehouse;
$stock_qty = intval(get_post_meta($product->get_id(), $stock_key, true));
if ($stock_qty > 0) {
$availability['availability'] = sprintf(__('In stock: %d pcs (Warehouse %s)', 'woocommerce'), $stock_qty, substr($warehouse, -1));
$availability['class'] = 'in-stock';
} else {
$availability['availability'] = __('Out of stock', 'woocommerce');
$availability['class'] = 'out-of-stock';
}
return $availability;
}4. Обновление запасов при покупке
Чтобы корректно списывать запасы с нужного склада, нужно перехватить событие добавления заказа:
add_action('woocommerce_order_status_completed', 'reduce_stock_from_selected_warehouse');
function reduce_stock_from_selected_warehouse($order_id) {
$order = wc_get_order($order_id);
$warehouse = isset($_GET['warehouse']) ? sanitize_text_field($_GET['warehouse']) : 'warehouse_1';
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$qty = $item->get_quantity();
$stock_key = '_stock_' . $warehouse;
$current_stock = intval(get_post_meta($product_id, $stock_key, true));
$new_stock = max(0, $current_stock - $qty);
update_post_meta($product_id, $stock_key, $new_stock);
}
}Проверка результата после внедрения
Чтобы проверить работу, откройте страницу товара с параметром ?warehouse=warehouse_1 или ?warehouse=warehouse_2. Наличие и остаток должны соответствовать указанным в метаполях.
Создайте тестовый заказ, завершите его, затем проверьте, что остаток на выбранном складе уменьшился на количество товара в заказе.
Частые ошибки и как исправить
- Запасы не уменьшаются после заказа: проверьте, что хук
woocommerce_order_status_completedдействительно срабатывает. Возможно, статус заказа не меняется на «завершён» автоматически. - Наличие отображается некорректно: убедитесь, что параметр
warehouseпередаётся в URL и совпадает с ключами метаполей. - Метаполя не сохраняются: проверьте, что функции сохранения вызываются и нет ошибок в PHP-логе.
- Проблемы с кешированием: очистите кеш сайта и браузера, а также отключите кеширование страниц для теста.
Практические советы по безопасности и производительности
- Валидация и санитизация входящих данных обязательна — используйте
sanitize_text_fieldиintvalдля данных из$_GETи$_POST. - Храните данные по складам в метаполях с префиксом, чтобы избежать конфликтов.
- Для большого количества складов и товаров лучше использовать специализированный плагин с оптимизированной базой данных.
- Минимизируйте количество запросов к базе, кэшируя данные на уровне объекта, если возможно.