Проблема: почему остатки товаров не обновляются автоматически в WooCommerce
В стандартной установке WooCommerce при продаже товара его остаток должен автоматически уменьшаться. Однако в некоторых случаях, особенно при кастомных решениях, импортах или нестандартных сценариях продажи, количество на складе не обновляется, что ведёт к неверным данным и ошибкам при оформлении заказов.
Основные причины:
- Отключён параметр управления запасами в настройках WooCommerce.
- Использование кастомных процессов оформления заказа, которые не вызывают стандартные хуки WooCommerce.
- Конфликты с плагинами, которые вмешиваются в обработку заказов.
- Ошибки в коде, который вручную изменяет статус заказа без обновления остатков.
Как проверить текущие настройки и работу обновления остатков
Для начала убедитесь, что управление запасами включено:
WooCommerce > Настройки > Товары > Управление запасами > Включить управление запасамиДалее проверьте в карточке товара, что у него установлен тип продукта "простой" или "вариативный" с включённым управлением запасами.
Для теста создайте новый заказ в админке, оформите продажу товара с наличием на складе 10 штук и посмотрите, уменьшится ли количество после смены статуса заказа на "завершён".
Если остаток не меняется, значит, механизм обновления не работает корректно.
Пошаговое решение: автоматическое обновление остатков с использованием хуков
WooCommerce обновляет остаток при смене статуса заказа на "завершён". Если у вас кастомная логика оформления, добавьте следующий код в functions.php вашей темы или в собственный плагин:
add_action('woocommerce_order_status_completed', 'custom_reduce_stock_on_order_completed');
function custom_reduce_stock_on_order_completed($order_id) {
if (!$order_id) return;
$order = wc_get_order($order_id);
if (!$order) return;
// Проверяем, обновлялись ли уже остатки для этого заказа
if (get_post_meta($order_id, '_stock_reduced', true)) return;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if ($product && $product->managing_stock()) {
$qty = $item->get_quantity();
wc_update_product_stock($product, $qty, 'decrease');
}
}
update_post_meta($order_id, '_stock_reduced', 'yes');
}Этот код гарантирует уменьшение остатка только один раз при смене статуса на "завершён", что исключает двойное списание.
Что делать, если используется кастомный статус заказа?
Если у вас нестандартный статус, например "выполнен_проверено", замените хук на:
add_action('woocommerce_order_status_выполнен_проверено', 'custom_reduce_stock_on_order_completed');Или используйте универсальный хук для смены статуса:
add_action('woocommerce_order_status_changed', 'custom_stock_update_on_status_change', 10, 4);
function custom_stock_update_on_status_change($order_id, $old_status, $new_status, $order) {
if ($new_status === 'completed') {
// Ваша логика уменьшения запасов (как выше)
}
}Проверка результата после внедрения кода
- Создайте тестовый заказ с товаром, у которого управляются запасы.
- Установите статус заказа на "Завершён" через админку WooCommerce.
- Проверьте обновление остатка товара в каталоге WooCommerce.
- Убедитесь, что после повторного смены статуса остаток не уменьшился повторно (проверка idempotentности).
Частые ошибки и как их исправить
- Остаток не меняется после смены статуса: Проверьте, включено ли управление запасами в настройках WooCommerce и в карточке товара.
- Двойное списание остатков: Добавьте проверку мета-поля, чтобы не уменьшать запасы повторно.
- Код не срабатывает при нестандартных статусах: Используйте хуки для кастомных статусов или универсальные хуки
woocommerce_order_status_changed. - Конфликты с плагинами: Отключите временно сторонние плагины и проверьте работу обновления запасов.
Практические советы по безопасности и производительности
- Не используйте прямые SQL-запросы для изменения остатков — доверяйте API WooCommerce (
wc_update_product_stock), чтобы корректно обновлять кэш и триггеры. - Добавляйте проверку idempotentности, чтобы избежать ошибок при многократном вызове обработчика.
- При массовом импорте используйте
wc_update_product_stockс осторожностью, чтобы не задать неверные остатки. - Для масштабируемых магазинов тестируйте нагрузку и используйте кеширование, чтобы не нагружать сервер лишними событиями.
Сравнение вариантов обновления остатков в WooCommerce
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Стандартное управление WooCommerce | Надёжно, автоматически при смене статуса | Не работает с кастомными сценариями | Для стандартных магазинов |
| Кастомный код на хуках (пример выше) | Гибко, контролируемо, можно подстроить под любые статусы | Требует поддержки и тестирования | При кастомных процессах |
| Ручное обновление через SQL | Быстрое обновление на уровне базы | Риск ошибок, пропуск кэширования, конфликт с WooCommerce | Крайний случай, при массовых правках |