Временная глобальная скидка на все товары в WooCommerce

Что мне нужно:

Мы планируем начать кампанию. Мы хотим предоставить временную скидку 10% на каждый товар, который мы продаем на нашем сайте, в течение следующих 30 дней. Мы хотим отображать как обычную цену, так и цену со скидкой на всех страницах магазина.

  • У нас около 200 000 товаров.
  • Наша продукция не имеет вариаций.

Требования:

  • На все товары должна быть скидка 10%.
  • Скидка должна быть видна и активна для всех посетителей.
  • Скидка должна применяться автоматически без каких-либо действий пользователя.
  • И обычная цена, и цена со скидкой должны быть видны всем посетителям сайта.
  • Скидку можно будет легко удалить через 30 дней.
  • Решение не должно использовать какие-либо дополнительные плагины, кроме WooCommerce. Мы стараемся свести к минимуму использование сторонних плагинов.
  • Изменения во внешнем интерфейсе должны быть минимальными или вообще отсутствовать.

Среда:

  • Наш магазин построен на WooCommerce 8.1.
  • Использование W3 Total Cache с Redis.
  • Размещено на выделенном сервере с Ubuntu Server 22.04. Запуск Apache 2.4 с PHP 8.1 и MySQL 8.

Что я пробовал и не помогло:

  • Использование плагина. Все плагины, которые я пробовал, имеют проблемы (или требуют слишком много ручного нажатия) при обработке 200 000 продуктов.
  • Создание coupon и его программное применение на странице Cart. Это фактически сделало часть скидки. Однако потребовались некоторые изменения в теме, чтобы показать пользователям новую цену со скидкой.

Вопрос:

Как это сделать?

В качестве отправной точки вы должны найти что-нибудь полезное в этих темах.

LoicTheAztec 29.09.2023 02:02

Спасибо @LoicTheAztec, на первый взгляд кажется, что большинство из них посвящены скидкам на странице Cart. Это один из вариантов, о котором я думал в сочетании с автоматически применяемым купоном. Но при таком варианте нам придется найти другое решение, чтобы отображать скидки на страницах магазина, и некоторые из наших фильтров могут работать, а могут и не работать.

sotirov 29.09.2023 02:27

На данный момент я тестирую другое решение. Просматриваем все продукты и обновляем их _sale_price и _price данными из _regular_price. А когда акция закончится, я почищу данные, как в этом посте stackoverflow.com/questions/28048702/…

sotirov 29.09.2023 02:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
162
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Обновлено (разрешено использование продуктов с нулевой ценой и сброс существующих цен продажи).

Вместо того, чтобы перезаписывать цены на продукты, как вы предлагаете в своем комментарии, вы можете использовать следующее, чтобы добавить временную глобальную скидку, которая сохранит исходную цену продукта с общей ценой продажи со скидкой 10%:

// Below define the discount rate
function discount_rate(){
    return 0.9; // 10% discount
}

add_filter('woocommerce_product_get_price', 'custom_price_discount', 20, 2);
add_filter('woocommerce_product_variation_get_price', 'custom_price_discount', 20, 2);
function custom_price_discount( $price, $product ) {
    if ( $price > 0 ) {
        return floatval($product->get_regular_price()) * discount_rate();
    }
    return $price;
}

add_filter('woocommerce_product_get_sale_price', 'custom_sale_price_discount', 20, 2);
add_filter('woocommerce_product_variation_get_sale_price', 'custom_sale_price_discount', 20, 2); 
function custom_sale_price_discount( $price, $product ) {
    return $product->get_price();
}
  
add_filter('woocommerce_product_is_on_sale', 'custom_product_is_on_sale', 20, 2);
function custom_product_is_on_sale( $is_on_sale, $product ) {
    return $product->get_price() > 0 ? true : false;
}

function remove_zero_prices( $prices ) {
    foreach( $prices as $key => $price ) {
        if ( $price > 0 ) {
            continue;
        }
        unset($prices[$key]);
    }
    return $prices;
}

add_filter( 'woocommerce_get_price_html', 'custom_dynamic_sale_price_html', 20, 2 );
function custom_dynamic_sale_price_html( $price_html, $product ) {
    if ( $product->is_type('variable') ) {
        $prices     = $product->get_variation_prices( true );
        $reg_prices = remove_zero_prices( $prices['regular_price'] );

        if ( count($reg_prices) > 0 ) {
            return wc_format_sale_price( wc_price( end($reg_prices) ), wc_price( reset($reg_prices) * discount_rate() ) ) . $product->get_price_suffix();
        } 
    }
    return $price_html;
}

Код находится в файле function.php вашей дочерней темы (или в плагине). Протестировано и работает. Это может работать с вашим очень большим каталогом.

Как я это сделал:

  • Выставление всех продуктов на продажу путем обновления их _sale_price и _price данными из _regular_price, умноженными на 0.9 (10%).
  • Когда акция закончится, вручную удалю _sale_price и обновлю _price на _regular_price, выполнив SQL-запросы.

Предупреждение: эти решения не работают с вариациями!

Добавьте скидку ко всем товарам

Если товары не продаются, у них нет _sale_price мета_ключа в таблице базы данных wp_postmeta. Чтобы добавить их, мы можем просмотреть все продукты и использовать update_post_meta. При работе с большими базами данных я предлагаю разделить обновление на более мелкие пакеты. В приведенном ниже коде я использовал 1000 для каждой партии. Если вы хотите получить запрос по всем вашим продуктам одновременно, замените 'posts_per_page' => 1000 на 'posts_per_page' => -1.

Внимание: этот код не будет работать должным образом, если какой-либо из ваших продуктов уже имеет _sale_price!

// Get the products that don't have '_sale_price'
$args = array(
    'post_type'      => 'product',
    'posts_per_page' => 1000,
    'meta_query'     => array(
        'relation' => 'AND',
        array(
            'key'     => '_sale_price',
            'compare' => 'NOT EXISTS',
        ),
        array(
            'key'     => '_regular_price',
            'value'   => '',
            'compare' => '!='
        ),
    ),
);
$products = query_posts( $args );

// Loop through queried products
foreach ($products as $post) {
    $product = wc_get_product( $post->ID );

    // Discount by 10% and round to 2 decimal places
    $discount = 10;
    $newprice = round($product->get_regular_price() * ((100-$discount) / 100), 2);

    // Update product's prices
    update_post_meta( $product->get_id(), '_sale_price', $newprice );
    update_post_meta( $product->get_id(), '_price', $newprice );
}

Удалить скидку

Я использую SQL-запросы, потому что это быстро и просто. Если вы ищете альтернативный способ сделать это, проверьте этот пост: Удалить цену продажи из всех продуктов в администраторе WooCommerce

Предупреждение: эти SQL-запросы удалят все существующие цены продажи!

Удалить все товары' _sale_price:

DELETE FROM `wp_postmeta` WHERE meta_key = '_sale_price';

Обновите товары _price, указав значения _regular_price:

UPDATE wp_postmeta as price 
    INNER JOIN wp_postmeta as regular_price ON 
        price.post_id = regular_price.post_id AND 
        regular_price.meta_key = "_regular_price" AND
        price.meta_key = "_price"
    SET price.meta_value = regular_price.meta_value;

Использованная литература:

Другие вопросы по теме