Диагностика проблемы с автоматическими письмами при отмене товара
В WooCommerce по умолчанию при изменении статуса заказа или его позиций пользователю могут автоматически отправляться уведомления. Однако в случае отмены или удаления отдельного товара из заказа часто требуется отключить автоматическую отправку писем, чтобы не путать клиента лишними уведомлениями.
Основная проблема: стандартные хуки WooCommerce не предусматривают отдельное событие для отмены товара внутри заказа, и изменение статуса заказа запускает уведомления для всего заказа целиком.
Пошаговое решение: как отключить и настроить уведомления
1. Отключаем автоматическую отправку писем при обновлении заказа
Для контроля писем при изменении заказа используем фильтр woocommerce_email_enabled_{email_id}. Например, чтобы отключить письмо о смене статуса заказа customer_completed_order, используйте:
add_filter('woocommerce_email_enabled_customer_completed_order', 'disable_completed_email_for_partial_cancel', 10, 2);
function disable_completed_email_for_partial_cancel($enabled, $order) {
// Логика отключения
return false; // Отключаем всегда (пример)
}Но это слишком грубо — нам нужно реагировать именно на отмену товаров.
2. Отслеживаем отмену товара и предотвращаем отправку письма
Для этого используем хук woocommerce_order_item_quantity_changed, который вызывается при изменении количества товара в заказе.
add_action('woocommerce_order_item_quantity_changed', 'check_item_cancellation_and_disable_email', 10, 3);
function check_item_cancellation_and_disable_email($item_id, $quantity, $old_quantity) {
if ($quantity == 0 && $old_quantity > 0) {
// Товар отменён
add_filter('woocommerce_email_enabled_customer_completed_order', '__return_false');
}
}Данный код отключит письмо о завершении заказа, если произошло уменьшение количества товара до нуля.
3. Более точечное отключение писем — через свой флаг
Чтобы не отключать письма ко всем заказам, добавим мета-поле флаг «отмена товара»:
add_action('woocommerce_order_item_quantity_changed', 'flag_order_for_no_email', 10, 3);
function flag_order_for_no_email($item_id, $quantity, $old_quantity) {
if ($quantity == 0 && $old_quantity > 0) {
$order_id = wc_get_order_item_meta($item_id, '_order_id', true);
if (!$order_id) {
$item = wc_get_order_item($item_id);
$order_id = $item->get_order_id();
}
update_post_meta($order_id, '_skip_email_on_partial_cancel', 'yes');
}
}
add_filter('woocommerce_email_enabled_customer_completed_order', 'conditionally_disable_email', 10, 2);
function conditionally_disable_email($enabled, $order) {
if (get_post_meta($order->get_id(), '_skip_email_on_partial_cancel', true) === 'yes') {
// Отключаем письмо
return false;
}
return $enabled;
}Как проверить, что решение работает
- Создайте тестовый заказ в WooCommerce с несколькими товарами.
- Измените количество одного товара на 0 через админку (отмена товара в заказе).
- Сохраните заказ и проверьте, не отправилось ли письмо о завершении заказа (customer_completed_order) на email клиента.
- Если письмо не пришло — решение работает.
- Для теста можно включить логирование писем или использовать плагин Email Log.
Частые ошибки и их исправление
- Письма продолжают отправляться несмотря на фильтр: причина — фильтр не применился, т.к. добавлен после инициализации писем. Решение — приоритет фильтра должен быть минимальным (например, 10), и добавляйте фильтр до отправки письма.
- Неверное получение ID заказа из item ID: используйте метод
$item->get_order_id()вместоwc_get_order_item_meta(), чтобы избежать ошибок. - Отмена товара не фиксируется: убедитесь, что изменение количества происходит через интерфейс WooCommerce, а не напрямую в базе или сторонними плагинами, иначе хук
woocommerce_order_item_quantity_changedне вызовется.
Практические советы по безопасности и производительности
- Не отключайте уведомления полностью для всех заказов — это ухудшит UX.
- Используйте мета-поля для флагов и очищайте их после выполнения действия, чтобы не накапливать мусор.
- Логируйте действия для отладки, но отключайте логи в продакшене.
- Тестируйте на staging-среде, чтобы не сломать важные уведомления.
Сравнение вариантов решения задачи отключения писем
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Отключение письма полностью через фильтр | Простой фильтр возвращает false для email | Просто реализовать | Отключает письмо для всех заказов, не учитывает частичную отмену |
| Отслеживание изменения количества товара + флаг | Использование хука woocommerce_order_item_quantity_changed и мета-поля | Точечное отключение, не мешает другим письмам | Сложнее реализовать, требует понимания API |
| Использование сторонних плагинов для управления письмами | Плагины с настройками триггеров писем | Интерфейс, удобство | Может быть избыточно и влиять на производительность |