@vanechka_ivan

Изменение типа цены в зависимости от общей суммы корзины Woocommerce?

Если общая сумма корзины составляет более 2000р. то товары в корзине считаются по оптовой цене. Она добавляется кастомно через functions.php.
Я примерно представляю себе логику алгоритма, но не очень хорошо разбираюсь в php. Заранее буду благодарен
  • Вопрос задан
  • 420 просмотров
Пригласить эксперта
Ответы на вопрос 1
@vanechka_ivan Автор вопроса
На просторах интернета я нашел код который меняет цену товара на фиксированную без каких-либо условий.
И вышло что-то на подобии этого:
// Adding a wholesale price for items
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {
    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

   // Get order subtotal
    $order_subtotal = WC()->cart->get_cart_subtotal();
   
    if ( $order_subtotal >= 2000 ) {
        foreach ( $cart->get_cart() as $item ) {
       // Значение set_price нужно будет заменить на id кастомной цены, если всё заработает
        $item['data']->set_price( 150.6 );
        }
    }
}

Тут для проверки роботоспосоности я просто изменяю цену товаров к корзине на фиксированную.

Но при сохранении functions.php с этим кодом, сайт выдаёт ошибку при попытке добвления товара к корзину. Это происходит если я сравниваю подытог корзины с нужной мне суммой (при условии 1 == 1 всё работает). Также я не уверен что правильно получаю значение $order_subtotal.
Даже при условии что код заработает как должет, будет ли присваиваться определённому товару конкретно его кастомная цена.

UPD:
Я начал проверять значение $order_subtotal через echo, но мне постоянно выдавало что оно равно 0 (нуль или ноль?). Не понимая что присходит я немного впал в отчаянне. Но. НО. После я заметил что в add_action написано woocommerce_before_calculate_totals. Хахахах. Всё было так просто. Там написано before. Это BEFORE. Т.е до подсчёта суммы. Лёгкими нажатиями своими пальчиками я заменил этот никчёмный "before" на нужный мне "after". И боги, оно заработало. Я начал видеть правильный мне подытог корзины.
После я понял что если получать нужное мне значение через использывание get_cart_subtotal(), то я получаю сумму в виде строки со знаком валюты, а если использывать get_subtotal() мы получаем уже тип float, который можно использывать для конструкции if.
Сейчас код имеет такой вид:
// Adding a wholesale price for items
add_action( 'woocommerce_after_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {
    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_after_calculate_totals' ) >= 2 )
        return;

    if ( WC()->cart->get_subtotal() >= 2000 ) {
        foreach ( $cart->get_cart() as $item ) {
        $item['data']->set_price( 150.6 );
        }
    }
}


P.S Пока редактировал текст заметил что когда подытог становится больше чем нужно (т.е условие выполняется) и товар преобретает нужную цену, конечый итог считает по старой цене. Буду думать дальше
P.S 2 Я понял почему так происходит. Я задаю условие при котором цена товара задаётся уже после подсчёта суммы корзины и поэтому он считает по стандартному прайсу.

UPS 2
Дыыыы. Оно работает так как надо. Так как хотел того именно я.
Код:
// Adding a wholesale price for items
add_action( 'woocommerce_after_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {
    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_after_calculate_totals' ) >= 2 )
        return;
    // Adding a custom price for items
    if ( WC()->cart->get_subtotal() >= 2000 ) {
        foreach ( $cart->get_cart() as $item ) {
        $item['data']->set_price( 150.6 );
        }
    }
    // Recount cart total
    WC()->cart->calculate_totals();
    // Wrong minimum amount protection
    if ( WC()->cart->get_subtotal() < 2000 ) {
        foreach ( $cart->get_cart() as $item ) {
        $regular_price = $item['data']->get_regular_price();
        $item['data']->set_price( $regular_price );
        }
    }
    // Recount cart total
    WC()->cart->calculate_totals();
}


А теперь по порядку. Во первых я не знал как пересчитать итоговую стоимость корзины с изменёнными ценами. у мена была идея которой я придерживался. Уже и не хочу думать как я бы это сделал, потому что уже голова болит от этого. Но суть именно в том как я начал это делать. Я добавил переменную $ca = WC()->cart->calculate_totals(). В попытках проверить не виснит ли сайт от такой логики при перезагрузки я не увидил сообщение о том что "Возникла ошибка. Поробуйте в другой раз." (Это уже очень радовало). Я решил попробывать изменить количесто товара. И именно тут я заметил что корзина пересчитывает итогувую сумму по новой, заданной мной, цене. ОоОООООООО. Я перекрестился и сказал чпасибо себе за то что я такой классный. После я оставил только WC()->cart->calculate_totals(), что также работало исправно.
Понимая что смена цены работает только в одну сторону, я добавил вторую конструкцию if только с обратным условием. Фиксированную цену заменил на
$regular_price = $item['data']->get_regular_price()
и также добавил перерасчет суммы корзины после.
Это моя лична маленькая победа над которой я очень горжусь, ведь до этого момента я не имел дело с php от слова вообще. Осталось только добавить оптовую цену, указать её в моём мальком коде и всё. На этом мои мучения закончены.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы