Диагностика проблемы: почему скидки применяются к нежелательным товарам
В WooCommerce часто возникает задача настроить скидки так, чтобы они не распространялись на товары с определёнными атрибутами. Например, если у вас есть категория "Подарочные сертификаты" или товары с атрибутом "Не участвует в акциях", вы хотите исключить их из всех правил скидок, чтобы избежать потерь.
Стандартные купоны WooCommerce и большинство плагинов для скидок не поддерживают фильтрацию по атрибутам товаров, только по категориям или тегам. Это приводит к тому, что скидка применяется ко всем товарам в корзине, что нежелательно.
Пошаговое решение: исключение товаров из скидок по атрибутам через кастомный фильтр
1. Добавляем фильтр на вычисление скидок в корзине
Для исключения товаров с определённым атрибутом из скидок нужно использовать хук woocommerce_coupon_get_discount_amount, который позволяет контролировать сумму скидки на каждом товаре.
2. Пример кода для исключения товаров с атрибутом "exclude_from_discount"
add_filter('woocommerce_coupon_get_discount_amount', 'exclude_products_by_attribute_from_discount', 10, 5);
function exclude_products_by_attribute_from_discount($discount, $discounting_amount, $cart_item, $single, $coupon) {
if (empty($cart_item['data'])) {
return $discount;
}
$product = $cart_item['data'];
$attributes = $product->get_attributes();
// Проверяем, есть ли атрибут exclude_from_discount
if (isset($attributes['exclude_from_discount'])) {
// Получаем значения атрибута
$values = wc_get_product_terms($product->get_id(), 'pa_exclude_from_discount', array('fields' => 'names'));
if (!empty($values)) {
// Если атрибут установлен, скидка не применяется
return 0;
}
}
return $discount;
}Обратите внимание, что для работы этого кода необходимо, чтобы атрибут имел системное имя pa_exclude_from_discount, а у товаров, которые нужно исключить, был установлен этот атрибут с любым значением.
Проверка результата после внедрения
- Добавьте в корзину товар с атрибутом
exclude_from_discountи другой товар без этого атрибута. - Примените купон со скидкой, который действует на всю корзину.
- Убедитесь, что скидка не применяется к товару с атрибутом, а к остальным товарам — применяется.
- Если скидка применяется ко всем товарам, проверьте правильность написания атрибута и его системное имя.
Частые ошибки и их исправление
- Неправильное имя атрибута: В WooCommerce системные имена атрибутов начинаются с
pa_. Убедитесь, что атрибут называется именноpa_exclude_from_discount, а не простоexclude_from_discount. - Атрибут не присвоен товарам: Проверьте, что товары действительно имеют этот атрибут и он заполнен.
- Кеширование корзины: Очистите кеш и проверьте в режиме инкогнито, чтобы изменения применились корректно.
- Конфликты с другими плагинами скидок: Иногда сторонние плагины переопределяют логику скидок. Попробуйте временно отключить другие плагины для диагностики.
Практические советы по производительности и безопасности
- Код добавляйте в дочернюю тему или в плагин типа Code Snippets, чтобы не потерять при обновлении.
- Хук
woocommerce_coupon_get_discount_amountвызывается часто, поэтому код должен быть максимально оптимизирован: избегайте лишних запросов к базе. - Для массовых сайтов с большим количеством товаров лучше кэшировать результаты проверки атрибутов в сессии или transient.
Сравнение вариантов решения задачи
| Метод | Преимущества | Недостатки |
|---|---|---|
Использование хука woocommerce_coupon_get_discount_amount | Полный контроль над скидками, гибкость, нет сторонних плагинов | Требует навыков программирования, нужно тестировать на конфликты |
| Плагины для расширенных скидок (например, WooCommerce Dynamic Pricing) | Простота настройки через UI, много настроек | Платные решения, возможны конфликты, нагрузка на сайт |
| Фильтрация по категориям товаров | Простая реализация через стандарт WooCommerce | Не подходит, если нужно исключать по атрибутам, не категориям |