WooCommerce: автоматическое удаление закрытых заказов без оплаты

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

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

Часто такие заказы не имеют ценности и нужны только для отчетности периода, после чего их можно удалить.

Как определить, что заказы можно удалять

  • Статус заказа: cancelled, failed, иногда pending.
  • Дата создания: заказы старше определенного времени (например, 30 дней).
  • Отсутствие оплаты и активности (нет транзакций, нет изменения статуса).

Пошаговое решение: автоматическое удаление заказов с помощью WP-Cron

Реализуем cron-задачу, которая еженедельно удаляет заказы со статусом cancelled и failed, созданные более 30 дней назад.

1. Создаем функцию удаления заказов

function wponline_delete_old_unpaid_orders() {
    if ( ! class_exists( 'WooCommerce' ) ) {
        return; // WooCommerce не активен
    }

    $statuses_to_delete = array('cancelled', 'failed');
    $date_threshold = date('Y-m-d H:i:s', strtotime('-30 days'));

    $args = array(
        'post_type'      => 'shop_order',
        'post_status'    => $statuses_to_delete,
        'date_query'     => array(
            'before' => $date_threshold,
        ),
        'posts_per_page' => -1,
        'fields'         => 'ids',
    );

    $orders = get_posts($args);

    if (empty($orders)) {
        return;
    }

    foreach ($orders as $order_id) {
        wp_delete_post($order_id, true); // принудительно удаляем
    }
}

2. Регистрируем событие WP-Cron

function wponline_schedule_delete_old_orders() {
    if ( ! wp_next_scheduled( 'wponline_delete_old_orders_event' ) ) {
        wp_schedule_event( time(), 'weekly', 'wponline_delete_old_orders_event' );
    }
}
add_action('wp', 'wponline_schedule_delete_old_orders');

add_action('wponline_delete_old_orders_event', 'wponline_delete_old_unpaid_orders');

3. Очистка cron при деактивации плагина или темы

function wponline_clear_delete_old_orders_cron() {
    $timestamp = wp_next_scheduled('wponline_delete_old_orders_event');
    if ($timestamp) {
        wp_unschedule_event($timestamp, 'wponline_delete_old_orders_event');
    }
}
register_deactivation_hook(__FILE__, 'wponline_clear_delete_old_orders_cron');

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

  • В базе данных таблице wp_posts проверьте наличие заказов со статусом cancelled и failed старше 30 дней до и после запуска задачи.
  • Запустите вручную функцию wponline_delete_old_unpaid_orders() через wp-cli или временно вызвав её в шаблоне, чтобы проверить работу без ожидания cron.
  • Просмотрите логи сервера и error_log на предмет ошибок при удалении.

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

  • Заказы не удаляются: проверьте, активен ли WooCommerce и правильно ли заданы статусы в запросе.
  • Функция cron не запускается: убедитесь, что wp-cron.php вызывается (например, через системный cron), либо протестируйте вызов вручную.
  • Удаление не происходит из-за прав: убедитесь, что WordPress имеет права на удаление постов, и что не используются плагины, которые блокируют удаление заказов.
  • Удаляются не те заказы: проверьте параметры date_query и post_status в запросе, особенно формат даты.

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

  • Перед массовым удалением сделайте резервную копию базы данных.
  • Не запускайте удаление слишком часто — достаточно раз в неделю или месяц, чтобы не нагружать сервер.
  • Для крупных магазинов с большим объемом заказов используйте постраничное удаление (например, по 100 заказов за один запуск), чтобы избежать таймаутов.
  • Логируйте удаляемые заказы для возможности аудита и отката.

Расширенный пример с постраничным удалением и логированием

function wponline_delete_old_unpaid_orders_paginated($batch_size = 100) {
    if ( ! class_exists( 'WooCommerce' ) ) {
        return;
    }

    $statuses = array('cancelled', 'failed');
    $date_threshold = date('Y-m-d H:i:s', strtotime('-30 days'));

    $paged = 1;
    do {
        $args = array(
            'post_type'      => 'shop_order',
            'post_status'    => $statuses,
            'date_query'     => array('before' => $date_threshold),
            'posts_per_page' => $batch_size,
            'paged'          => $paged,
            'fields'         => 'ids',
        );

        $orders = get_posts($args);

        if (empty($orders)) {
            break;
        }

        foreach ($orders as $order_id) {
            if (wp_delete_post($order_id, true)) {
                error_log("Order deleted: $order_id");
            } else {
                error_log("Failed to delete order: $order_id");
            }
        }

        $paged++;
    } while (count($orders) == $batch_size);
}

Сравнение вариантов удаления заказов

МетодПлюсыМинусыРекомендации
WP-Cron с одной функцией удаления всех заказов Простота реализации, достаточно для небольших магазинов Риск таймаутов и нагрузки при большом объеме заказов Для магазинов с менее 1000 заказов
Постраничное удаление с логированием Безопасно работает с большими объемами, есть аудит Сложнее в реализации и отладке Рекомендуется для крупных магазинов
Удаление через сторонние плагины Готовые решения, интерфейс Может быть избыточным, нагрузка, риск конфликтов Если не хочется писать код
Как настроить автоматическое создание резервных копий в WordPress
20.12.2025
WooCommerce: автоматическое удаление заказов по статусу и дате
10.07.2026
Автоматическое удаление неактивных пользователей в WordPress
27.12.2025
Как создать настройки плагинов WordPress с использованием Settings API
09.01.2026
WooCommerce: автоматическое отключение способов оплаты при проблемах с интернет-соединением
20.06.2026