В интернет-магазинах на базе WooCommerce часто возникает задача резервирования товара на время оформления заказа. Это позволяет избежать ситуации, когда несколько клиентов одновременно оформляют заказ на один и тот же товар, а склад не успевает обновлять остатки мгновенно. Сегодня мы разберем, как создать автоматический скрипт для резервирования товаров в WooCommerce, используя хуки и собственный функционал.
Зачем нужно резервирование товаров в WooCommerce
Резервирование товара — это механизм, который блокирует определенное количество единиц товара сразу после попадания его в корзину или начала оформления заказа. Это помогает:
- Избежать перепродажи при высокой нагрузке;
- Повысить лояльность клиентов, которые видят, что товар гарантированно будет для них;
- Оптимизировать складские процессы и улучшить работу с запасами.
Однако WooCommerce по умолчанию не имеет встроенного механизма для резервирования товаров, поэтому нам придется реализовать его самостоятельно.
Основные этапы создания механизма резервирования
Для реализации нам потребуется:
- Отследить добавление товара в корзину и заблокировать нужное количество;
- Отследить удаление товара из корзины или отмену заказа и разблокировать товар;
- Установить таймаут резервирования, чтобы товар не блокировался бесконечно;
- Обновлять остатки товара с учетом резерва.
Отслеживание добавления товара в корзину
Для начала создадим функцию wporders_reserve_product_on_add_cart, которая будет срабатывать при добавлении товара в корзину. В ней мы уменьшим доступный запас товара на количество, которое добавили в корзину.
function wporders_reserve_product_on_add_cart($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) {
$reserved = (int) get_transient('wporders_reserved_' . $product_id) ?: 0;
$reserved += $quantity;
set_transient('wporders_reserved_' . $product_id, $reserved, 15 * MINUTE_IN_SECONDS); // резерв на 15 минут
}
add_action('woocommerce_add_to_cart', 'wporders_reserve_product_on_add_cart', 10, 6);Здесь мы используем функцию set_transient для хранения количества зарезервированных товаров с таймаутом 15 минут. Это значит, что если покупатель не завершит оформление заказа за это время, резерв автоматически снимется.
Снятие резерва при удалении из корзины
Если пользователь удаляет товар из корзины или отменяет заказ, нужно разблокировать резерв. Для этого создадим функцию wporders_release_product_on_remove_cart:
function wporders_release_product_on_remove_cart($cart_item_key, $cart) {
$cart_item = $cart->get_cart_item($cart_item_key);
if (!$cart_item) return;
$product_id = $cart_item['product_id'];
$quantity = $cart_item['quantity'];
$reserved = (int) get_transient('wporders_reserved_' . $product_id) ?: 0;
$reserved = max(0, $reserved - $quantity);
set_transient('wporders_reserved_' . $product_id, $reserved, 15 * MINUTE_IN_SECONDS);
}
add_action('woocommerce_remove_cart_item', 'wporders_release_product_on_remove_cart', 10, 2);<Это позволяет корректно обновлять резерв при изменениях корзины.
Учёт резерва при отображении доступного количества
Теперь нам нужно изменить отображение доступного количества товара на сайте, чтобы учесть резерв. Для этого воспользуемся фильтром woocommerce_get_availability:
function wporders_adjust_stock_availability($availability, $product) {
$product_id = $product->get_id();
$reserved = (int) get_transient('wporders_reserved_' . $product_id) ?: 0;
$stock_quantity = $product->get_stock_quantity();
$available_stock = max(0, $stock_quantity - $reserved);
if ($available_stock <= 0) {
$availability['availability'] = __('Товар временно недоступен', 'wporders');
$availability['class'] = 'out-of-stock';
} else {
$availability['availability'] = sprintf(__('%d в наличии (с учётом резерва)', 'wporders'), $available_stock);
$availability['class'] = 'in-stock';
}
return $availability;
}
add_filter('woocommerce_get_availability', 'wporders_adjust_stock_availability', 10, 2);Таким образом, покупатели видят актуальный остаток товара с учётом резервирования.
Автоматическое снятие резерва по таймауту
Таймаут резервирования установлен через set_transient, поэтому если пользователь не активен и не завершил заказ, резерв будет автоматически снят через 15 минут. Это предотвращает бесконечную блокировку товара.
Расширение функционала: интеграция с заказами
Чтобы резервирование корректно работало при создании и завершении заказа, нужно добавить обработчики для обновления резерва:
- При успешном создании заказа резерв снимается, так как товар продан.
- При отмене или возврате заказа резерв снимается и товар возвращается в доступ.
Пример функции для снятия резерва при создании заказа:
function wporders_release_reserve_on_order_created($order_id) {
$order = wc_get_order($order_id);
if (!$order) return;
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
$reserved = (int) get_transient('wporders_reserved_' . $product_id) ?: 0;
$reserved = max(0, $reserved - $quantity);
set_transient('wporders_reserved_' . $product_id, $reserved, 15 * MINUTE_IN_SECONDS);
}
}
add_action('woocommerce_thankyou', 'wporders_release_reserve_on_order_created');Также желательно добавить обработку отмен и возвратов через хуки woocommerce_order_status_cancelled и woocommerce_order_status_refunded.
Рекомендации по использованию и доработке
Данная реализация подойдет для магазинов со средней нагрузкой. Для крупных проектов стоит рассмотреть:
- Хранение резерва в отдельной таблице базы данных для более точного контроля;
- Использование AJAX для обновления остатка в реальном времени;
- Расширение таймаута или настройку через админку;
- Интеграцию с плагинами кэширования и оптимизации, например, Clearfy Pro, чтобы избежать конфликтов.
Если вы используете тему Reboot или Root, можно интегрировать визуальные индикаторы резерва для улучшения UX.
Выводы и полезные ссылки
Резервирование товаров в WooCommerce значительно повышает качество обслуживания клиентов и помогает избежать проблем с остатками. Приведённый пример — базовая основа, которую можно доработать под конкретные задачи и особенности магазина.
Если хотите расширить функционал автоматизации заказов, обратите внимание на плагины My Popup для уведомлений и ABC Pagination для улучшения навигации в списках товаров.