Диагностика проблемы: почему важно менять доступность товара автоматически
В интернет-магазинах на WooCommerce часто возникает задача динамически изменять доступность товара в зависимости от его популярности и текущих заказов. Например, если товар заказывают слишком часто и склад истощается, нужно автоматически помечать его как "нет в наличии" или "под заказ". Ручное управление статусами при большом ассортименте и высоком трафике ведёт к ошибкам и недовольству клиентов.
Типичные симптомы, что нужно автоматизировать смену доступности:
- Товары остаются доступными, когда их фактически нет на складе
- Невозможно быстро обновлять статусы при изменении количества заказов
- Появляется много отменённых заказов из-за несоответствия статусов
Пошаговое решение: как автоматически менять доступность товаров по количеству заказов
1. Определяем критерии для изменения статуса
Например, если количество заказов товара за последние 7 дней превысило заданный порог, меняем статус на "нет в наличии" или "под заказ".
2. Подключаемся к событию обновления заказа
Используем хук woocommerce_order_status_changed для отслеживания изменений статусов заказов.
3. Считаем количество заказанных товаров за период
Пример функции для подсчёта заказов по ID товара за последние 7 дней:
function count_product_orders_last_7_days($product_id) {
global $wpdb;
$date = date('Y-m-d H:i:s', strtotime('-7 days'));
$query = $wpdb->prepare(
"SELECT SUM(oi.meta_value) FROM {$wpdb->prefix}woocommerce_order_items AS oi
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS oim ON oi.order_item_id = oim.order_item_id
INNER JOIN {$wpdb->posts} AS p ON p.ID = oi.order_id
WHERE oim.meta_key = '_product_id' AND oim.meta_value = %d
AND p.post_type = 'shop_order'
AND p.post_status IN ('wc-completed', 'wc-processing')
AND p.post_date > %s
AND EXISTS (
SELECT 1 FROM {$wpdb->prefix}woocommerce_order_itemmeta AS qty_meta
WHERE qty_meta.order_item_id = oi.order_item_id AND qty_meta.meta_key = '_qty'
)",
$product_id,
$date
);
$result = $wpdb->get_var($query);
return intval($result);
}Примечание: в данном примере важно использовать правильные join и фильтры по статусу заказа.
4. Меняем статус товара по результатам подсчёта
Пример функции для обновления статуса товара:
function update_product_availability($product_id, $threshold) {
$orders_count = count_product_orders_last_7_days($product_id);
$product = wc_get_product($product_id);
if (!$product) return;
if ($orders_count >= $threshold) {
// Меняем статус на 'нет в наличии'
$product->set_stock_status('outofstock');
$product->save();
} else {
// Возвращаем в наличие
$product->set_stock_status('instock');
$product->save();
}
}5. Запускаем проверку при изменении заказа
add_action('woocommerce_order_status_changed', 'check_and_update_product_availability', 10, 4);
function check_and_update_product_availability($order_id, $old_status, $new_status, $order) {
$threshold = 10; // например, порог 10 заказов за 7 дней
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
update_product_availability($product_id, $threshold);
}
}Проверка результата после внедрения
- Создайте тестовый заказ с товарами, количество которых близко к порогу.
- Измените статус заказа на "завершён" или "обрабатывается" и проверьте, что статус товара обновился.
- Перейдите в админку WooCommerce → Товары → нужный продукт и убедитесь, что поле "Наличие" изменилось на "нет в наличии" или "в наличии" в зависимости от количества заказов.
- Также можно проверить на фронтенде, как отображается статус товара.
Частые ошибки и как их исправить
- Неверные запросы к базе данных: неправильные JOIN или WHERE условия приводят к некорректному подсчёту. Рекомендуется тестировать SQL-запрос отдельно и использовать
$wpdb->prepareдля безопасности. - Отсутствие проверки существования продукта: перед вызовом методов продукта проверяйте, что объект не
null. - Ошибка в хукe: неверно переданы параметры или приоритет, из-за чего функция не срабатывает. Используйте правильный синтаксис и проверяйте, что хук срабатывает через логи.
- Проблемы с кэшированием: если на сайте работает кэш, изменения видны не сразу. Очистите кэш или отключите его для тестов.
Практические советы по производительности и безопасности
- Оптимизируйте SQL-запросы, особенно если база большая. Используйте индексы по полям
post_dateиpost_status. - Кэшируйте результаты подсчётов, например, сохраняйте в transient на 5-10 минут, чтобы не запускать запрос при каждом обновлении заказа.
- Ограничьте доступ к этим функциям, чтобы никто из пользователей не мог напрямую менять статусы товаров через нестандартные запросы.
- Логируйте изменения статусов для отладки и мониторинга, особенно при автоматизации управления складом.
Сравнение подходов: плагин vs. кастомный код
| Метод | Преимущества | Недостатки |
|---|---|---|
| Использование плагина (например, WooCommerce Stock Manager) | Простая настройка, готовый интерфейс, поддержка обновлений | Может не иметь гибких условий, нагрузка на сайт, платные функции |
| Кастомный код (как в статье) | Максимальная гибкость, точечное решение, интеграция под задачи | Требует навыков разработки, нужно тестировать и поддерживать |