Как запретить удаление товаров в WooCommerce после покупки

Диагностика проблемы: почему нужно запретить удаление товаров после продажи

В WooCommerce стандартно отсутствует ограничение на удаление товаров из админки, вне зависимости от того, были ли они проданы. Это может привести к потере данных о продажах, нарушению отчетности и проблемам с налоговой документацией. Особенно важно для магазинов с большим объемом заказов сохранить историю проданных товаров.

Пошаговое решение: запрет удаления товаров с заказами в WooCommerce

1. Проверка, был ли товар продан

Для начала нужно написать функцию, которая проверит, есть ли у товара завершённые заказы. Проверка будет происходить по статусу заказов completed или processing.

function has_product_sales($product_id) {
    global $wpdb;
    $query = $wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_order_items AS order_items
         
         INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS itemmeta ON order_items.order_item_id = itemmeta.order_item_id
         
         INNER JOIN {$wpdb->prefix}posts AS posts ON order_items.order_id = posts.ID
         
         WHERE posts.post_type = 'shop_order'
         AND posts.post_status IN ('wc-completed','wc-processing')
         AND itemmeta.meta_key = '_product_id'
         AND itemmeta.meta_value = %d",
        $product_id
    );
    $count = $wpdb->get_var($query);
    return $count > 0;
}

2. Запрет удаления товара через фильтр WordPress

Используем хук user_has_cap, чтобы снять право удаления товара, если он был продан.

add_filter('user_has_cap', function($allcaps, $caps, $args, $user) {
    if (isset($args[0]) && in_array($args[0], ['delete_post', 'delete_product'])) {
        $post_id = $args[2];
        $post_type = get_post_type($post_id);
        if ($post_type === 'product' && has_product_sales($post_id)) {
            $allcaps['delete_post'] = false;
            $allcaps['delete_product'] = false;
        }
    }
    return $allcaps;
}, 10, 4);

3. Блокировка удаления через Ajax и Bulk Actions

WooCommerce и WordPress позволяют удалять товары через массовые действия и AJAX-запросы. Для надежной защиты добавим проверку на уровне pre_delete_post.

add_action('pre_delete_post', function($post_id) {
    if (get_post_type($post_id) === 'product' && has_product_sales($post_id)) {
        wp_die('Удаление товара, который был продан, запрещено.');
    }
});

Проверка результата после внедрения

  • Попробуйте удалить товар, который не имел продаж — удаление должно пройти.
  • Попробуйте удалить товар, который продавался — должно появиться сообщение об ошибке и удаление не произойдет.
  • Проверьте массовое удаление (Bulk Actions) в списке товаров — товары с продажами не должны удаляться.

Частые ошибки и как их исправить

  • Ошибка: Товары с продажами удаляются.
    Причина: Кеширование ролей и прав в WordPress.
    Решение: После добавления фильтра сбросьте кеш прав пользователей с помощью wp_cache_flush() или повторного входа в админку.
  • Ошибка: Сообщение об ошибке не отображается при удалении через Bulk Actions.
    Причина: Ajax-запросы не всегда выводят wp_die() корректно.
    Решение: Для полного контроля создайте дополнительный фильтр для handle_bulk_actions-edit-product и возвращайте ошибку там.
  • Ошибка: Удаление не блокируется для пользовательских ролей.
    Причина: Фильтр user_has_cap может не охватывать все права.
    Решение: Проверьте, что все роли, имеющие право удалять товары, корректно обрабатываются фильтром.

Практические советы по безопасности и производительности

  • Оптимизация запроса: Используйте индексы на таблицах woocommerce_order_items и woocommerce_order_itemmeta для ускорения проверки продаж.
  • Кеширование результатов: При больших магазинах кешируйте результат has_product_sales() через Transients или объектный кеш, чтобы не нагружать базу при каждом запросе.
  • Журналирование попыток удаления: Для безопасности можно добавить логирование попыток удаления товаров с продажами через error_log() или сторонние решения.
  • Тестирование на staging-сервере: Перед внедрением на живом сайте обязательно проверяйте совместимость с установленными плагинами и темой.

Сравнение вариантов реализации блокировки удаления товаров с продажами

МетодПлюсыМинусыПример
Фильтр user_has_capБлокирует удаление на уровне прав пользователя, предотвращает появление кнопки удаленияНе всегда блокирует AJAX и Bulk Actions полностьюВторой код из статьи
Хук pre_delete_postОстанавливает удаление в любом случае, включая AJAX и массовые действияСообщение об ошибке не всегда красиво отображаетсяТретий код из статьи
Плагин для контроля прав (например, User Role Editor)Удобный UI для настройки правНе решает логику проверки продаж, нужна доп. кастомизацияНеобходимо доработать
Как сделать автоматическое сохранение изменений в WordPress для кастомных типов записей
18.01.2026
Как удалить и заблокировать спам в комментариях WordPress
20.03.2026
Как создать динамический фильтрованный список постов в WordPress с помощью WP_Query
02.02.2026
Как создать и использовать каскадные шаблоны в WordPress для гибкой настройки сайта
05.03.2026
Как удалить комментарии по автору в WordPress
22.01.2026