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

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

На крупных интернет-магазинах на WooCommerce часто накапливаются неоплаченные заказы, которые занимают место в базе данных и могут влиять на аналитические отчёты и производительность. Особенно это актуально, если магазин принимает предоплату или использует отложенные платежи.

Проблема: WooCommerce по умолчанию не удаляет неоплаченные заказы, оставляя их в базе навсегда. Это приводит к:

  • засорению таблиц базы данных, увеличению её размера;
  • неактуальной статистике и запутанным отчётам продаж;
  • возможным проблемам с резервным копированием и восстановлением;
  • нагрузке при работе с заказами в админке.

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

SELECT post_status, COUNT(*) FROM wp_posts WHERE post_type = 'shop_order' AND post_status IN ( 'wc-pending', 'wc-on-hold' ) GROUP BY post_status;

Если количество таких заказов постоянно растёт, пора автоматизировать их удаление.

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

1. Определяем статусы и сроки

Чаще всего нужно удалять заказы с статусами wc-pending (ожидает оплаты) и wc-on-hold (ожидает подтверждения) старше определённого времени, например 7 дней для wc-pending и 30 дней для wc-on-hold.

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

Добавьте следующий код в functions.php вашей темы или в отдельный плагин:

function wc_delete_old_unpaid_orders() {
    $statuses = [
        'wc-pending' => 7, // дней
        'wc-on-hold' => 30,
    ];

    foreach ($statuses as $status => $days) {
        $date = date('Y-m-d H:i:s', strtotime('-' . $days . ' days'));

        $args = [
            'post_type'      => 'shop_order',
            'post_status'    => $status,
            'date_query'     => [
                [
                    'column' => 'post_date',
                    'before' => $date,
                ],
            ],
            'fields'         => 'ids',
            'posts_per_page' => -1,
        ];

        $orders = get_posts($args);

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

3. Запускаем функцию по расписанию через WP-Cron

Добавьте в functions.php следующий код для регистрации ежедневного задания:

if (!wp_next_scheduled('wc_delete_old_unpaid_orders_event')) {
    wp_schedule_event(time(), 'daily', 'wc_delete_old_unpaid_orders_event');
}

add_action('wc_delete_old_unpaid_orders_event', 'wc_delete_old_unpaid_orders');

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

Если функция реализована в плагине, обязательно отмените расписание при деактивации:

function wc_delete_old_unpaid_orders_deactivation() {
    wp_clear_scheduled_hook('wc_delete_old_unpaid_orders_event');
}
register_deactivation_hook(__FILE__, 'wc_delete_old_unpaid_orders_deactivation');

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

  • В админке WooCommerce перейдите в Заказы, отфильтруйте по статусам Ожидает оплаты и Ожидает подтверждения. Заказы старше указанных сроков должны исчезнуть.
  • Запустите вручную функцию для теста, добавив временные значения сроков (например, 0 дней) и проверьте наличие удалённых заказов.
  • Выполните SQL-запрос из раздела диагностики для сравнения количества заказов до и после.

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

  • Заказы не удаляются: проверьте, что событие WP-Cron запущено (можно использовать плагин WP Crontrol). Убедитесь, что функция подключена и хук зарегистрирован.
  • Удаляются не все нужные заказы: проверьте правильность статусов и даты в date_query. Важно, чтобы дата сравнивалась с post_date, который соответствует дате создания заказа.
  • Удаление влияет на связанные данные: использование wp_delete_post($order_id, true) удаляет все связанные метаданные и записи. Если нужна мягкая очистка, замените true на false.
  • Высокая нагрузка при удалении большого количества заказов: разбейте процесс на чанки с использованием пагинации 'posts_per_page' => 100 и удаляйте партиями.

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

  • Всегда тестируйте код на копии сайта перед запуском в продакшн.
  • Резервируйте базу данных перед массовым удалением заказов.
  • Используйте транзакции или логирование, если планируете сложную очистку с учётом пользовательских данных.
  • Для больших магазинов с десятками тысяч заказов настройте удаление через WP-CLI или внешние cron-задачи, чтобы не перегружать WP-Cron.
  • Для удобства мониторинга можно добавить уведомления по email при удалении заказов, например, количество удалённых записей.

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

МетодПлюсыМинусыКомпромисс
Плагин (например, WP Clear Unpaid Orders)Простота установки, интерфейс настройкиДополнитель нагрузка, ограниченная кастомизацияИспользовать для небольших сайтов
WP-Cron с пользовательской функцией (код выше)Гибкость, точные настройки под задачиТребует навыков, возможны ошибки в кодеЛучший выбор для разработчиков
WP-CLI скрипты для удаленияВысокая производительность, контрольТребует SSH доступа, ручной запуск или внешний cronОптимально для крупных проектов
Как закрыть дубли страниц от индексации в WordPress без поломки SEO
22.08.2026