wpmoney.ru wordpress WP Money

Как запретить изменение цен товара в WooCommerce после оформления заказа

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

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

Проверить, есть ли проблема, можно в административном разделе «Заказы»: сравните цену товара в заказе и текущую цену товара в каталоге. Если они отличаются, это потенциальная проблема.

Пошаговое решение: блокируем изменения цены товара после оформления заказов

1. Копируем текущую цену в метаполе при оформлении заказа

Для сохранения цены, по которой товар был куплен, при создании заказа используем хук woocommerce_checkout_create_order_line_item:

add_action('woocommerce_checkout_create_order_line_item', 'save_product_price_in_order_item_meta', 10, 4);
function save_product_price_in_order_item_meta($item, $cart_item_key, $values, $order) {
    $product = $item->get_product();
    if ($product) {
        $price = $product->get_price();
        $item->update_meta_data('_original_product_price', $price);
    }
}

2. Запрещаем изменение цены товара в админке после оформления заказов

Чтобы избежать изменения цены товара, если на него есть заказы, запретим редактирование цены в админке. Для этого используем фильтр 'woocommerce_product_data_tabs' и проверяем наличие заказов с этим товаром.

add_filter('woocommerce_product_data_tabs', 'disable_price_edit_if_orders_exist', 10, 1);
function disable_price_edit_if_orders_exist($tabs) {
    global $post;
    if (!$post) return $tabs;

    $product_id = $post->ID;
    $orders = wc_get_orders(array(
        'limit' => 1,
        'status' => array('processing', 'completed', 'on-hold'),
        'product_id' => $product_id
    ));

    if (!empty($orders)) {
        if (isset($tabs['general'])) {
            unset($tabs['general']['fields']['_regular_price']);
            unset($tabs['general']['fields']['_sale_price']);
            // Если не сработает, можно скрыть через JS или CSS
        }
    }
    return $tabs;
}

Однако WooCommerce не предоставляет прямого способа убрать поля цены через фильтр, поэтому дополнительно можно отключить возможность сохранения цен через хук save_post_product:

add_action('save_post_product', 'prevent_price_update_if_orders_exist', 10, 3);
function prevent_price_update_if_orders_exist($post_ID, $post, $update) {
    if (!$update) return;

    $orders = wc_get_orders(array(
        'limit' => 1,
        'status' => array('processing', 'completed', 'on-hold'),
        'product_id' => $post_ID
    ));
    if (!empty($orders)) {
        // Запретим обновление цены
        remove_action('save_post_product', 'woocommerce_process_product_meta');
        // Либо перезапишем цену старой
        $old_product = wc_get_product($post_ID);
        if ($old_product) {
            update_post_meta($post_ID, '_regular_price', $old_product->get_regular_price());
            update_post_meta($post_ID, '_price', $old_product->get_price());
        }
    }
}

3. Обновляем цену в заказах только в исключительных случаях

Если по бизнес-логике нужно менять цену в уже оформленных заказах, делайте это вручную и только с согласия бухгалтерии, иначе лучше полностью запретить.

Проверка результата

  • Оформите тестовый заказ с товаром.
  • Попробуйте изменить цену товара в админке — изменение должно не сохраниться или быть заблокировано.
  • Проверьте, что в заказе сохранена оригинальная цена в метаполе _original_product_price.
  • Запустите отчеты WooCommerce, чтобы убедиться, что данные по заказам не изменились.

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

  • Цена меняется в базе, но не в заказах: это штатное поведение, цена в заказе сохранена отдельно, поэтому обновлять цену товара нельзя задним числом.
  • Поля цены не скрываются в админке: WooCommerce не всегда позволяет убрать стандартные поля через фильтры, используйте CSS или JavaScript в админке для скрытия.
  • Функция блокировки сохранения цены не срабатывает: убедитесь, что код подключен в плагине или functions.php и что нет конфликтов с другими плагинами, которые тоже изменяют цены.

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

  • Для проверки наличия заказов используйте параметры с лимитом 1, чтобы не загружать лишние данные.
  • Кешируйте результаты запросов наличия заказов, если эта проверка вызывается часто.
  • Храните оригинальную цену товара в метаполе заказа — это предотвратит ошибки при анализе данных.
  • Внедряйте проверку и блокировку изменения цены на уровне бизнес-логики, а не только на уровне интерфейса.

Сравнение подходов: плагин vs. код vs. компромисс

ПодходПлюсыМинусыКомпромисс
Плагин (например, «Prevent Price Change After Order»)Простота установки, поддержка, тестированиеМожет быть платным, нагрузка на сайтИспользовать проверенные плагины с хорошими отзывами
Код в functions.php или плагинеПолный контроль, легковесность, гибкостьНужны навыки разработки, поддержка вручнуюПисать чистый и оптимизированный код, тестировать на тестовом сайте
Компромисс (частичное ограничение, уведомление админа)Гибкость, информирование о рискахНе полная защита, возможны ошибкиИспользовать уведомления с возможностью отмены изменений
×

AI-плагин от WPShop.ru

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

пишет статьи

готовит SEO

генерирует изображения

и еще кое-что...
WPGPT
Плагин, который наполняет ваш сайт WordPress
Узнать больше