Woocommerce. Изменение логики расчетов стоимости товара.

Доброго времени суток, друзья. В общем, смысл моего повествования изложен в заголовке. Для одного проекта возникла необходимость полностью поменять логику расчетов стоимости товаров в woocommerce. Компании для которой я реализовывал данный проект все расчеты ведутся через 1С версии 7 (Сееемь! Карл!) и эту логику нужно было использовать и в woocommerce.

Логика подсчета выглядит примерно таким образом. Есть некий товар и у этого товара есть БазоваяЦена, далее БЦ, (читай как себестоимость). Именно от этой стоимости нужно рассчитывать итоговую стоимость. На БЦ воздейстуют несколько модификаторов, которые ее меняют:

Наценка (Н) – модификатор, который увеличивает БЦ до РозничнойЦены (РЦ). В моем случае Н была 50% от БЦ.

Пользовательская Скидка (ПС) – модификатор, который уменьшает РЦ на определенный процент, который индивидуален для каждого пользователя. При регистрации на сайте пользователь получает скидку 3%. Изменять данную скидку может только менеджер магазина вручную. Максимально ПС может быть 15%.

Оптовая скидка (ОС) — модификатор, который уменьшает РЦ на определенный процент, который зависит от общей стоимости корзины. Например от 0р. до 2000р. скидка 0%, от 2000р. до 5000р. 3% и тд. Данная шкала скидок была предоставлена заказчиком.

ПС и ОС в общем результате складываются и уменьшают РЦ до Конечной Цены (КЦ).

Важное замечание!!! Поскольку скидки складываются, то общая скидка не должна быть больше 35%.

Перейдем к технической части.

Дисклеймер! Подробных гайдов как это сделать  не нашел, поэтому расскажу о своем пути решения данной задачи. Я не претендую на истину в последней инстанции. Если у вас есть вопросы или предложения добро пожаловать в комменты или на chernichko.work@mail.ru

Все будет реализовано в function.php без вмешательства в ядро WP и WC.

Для реализации кастомного расчета стоимости нам нужно будет использовать несколько хуков и фильтров woocommerce.

Итак, для начала нужно разобраться как работает расчет стоимости товара. Исходя из своего опыта я понял, что WC на каждом этапе подсчитывает все стоимости только исходя из его базовой цены. Например, если с помощью фильтра измените  стоимость товара на странице непосредственно товара, то это совсем не значит, что на этапе оформления заказа WC возьмет именно то, что вы изменили с помощью фильтра. Он опять будет отталкиваться от своей базовой цены. Именно из-за этого было решено описать функцию, которая бы производила расчеты стоимости конкретного товара и возвращала бы его в нужном виде (в виде числа, если мы собираемся что-то еще посчитать, или в виде текста со знаком валюты и отформатированном нужным образом). По поводу стоимости стоит заметить что функция может вернуть как и КЦ товара, так и РЦ товара (нам это будет необходимо). Данную функцию мы будем вызвать в нужных нам местах (при помощи фильтров и хуков). Я определил следующие места, где данная функция вызывается:

woocommerce_get_price_html / filter – фильтр, который позволяет изменить цену товара на странице товара (Single Product). Меняет только значение на экране, не меняя его по сути.

woocommerce_after_calculate_totals / filter — фильтр, который позволяет изменить итоговую сумму корзины товаров.

woocommerce_cart_totals_before_order_total / filter — фильтр, который позволяет изменить данные в таблице итоговой суммы заказов в корзине.

woocommerce_cart_item_price / filter – фильтр, который меняет стоимость товара в корзине.

woocommerce_cart_total / action – зацепка, с помощью которой мы можем пересчитать итоговую сумму корзины

woocommerce_checkout_create_order / action — зацепка, с помощью которой мы создаем заказ с новыми ценами

Итак. Сначала разберемся с функцией подсчтета.

Задача функции возвращать некую скалькулированную цену товара (БЦ, РЦ, КЦ) в необходимом формате (в формате float числа  или в формате отформатированной строки с денежным знаком). Поскольку функция всегда вызывается там, где мы можем получить ID товара, то обязательным параметром функции будет product_id. В качестве дополнительного необязательного параметра функции будет массив, с помощью которого функция будет определять формат числа и тип цены, который нам необходим.

В итоге описание функции будет примерно следующим

global_calc_price ($product_id, $attr)

$attr[

        'format'=>'html'            | html (string) - отформатированный вывод числа с денежным знаком

                                    | number (float) - Нецелочисленное значение

        'price_type'=> 'final'      | final     - КЦ

                                    | starting  - РЦ

                                    | base      - БЦ

    ]

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

Представляю листинг кода с комментариями

Листинг фнукции global_calc_price()

function global_calc_price ($product_id, $attr = array('format'=>'html', 'price_type'=>'final')){

    if (!isset($attr['format'])) $attr['format'] = 'html';
    if (!isset($attr['price_type'])) $attr['format'] = 'final';

    $sale_cat_ids = array(21,22,44,17,19,18,43,28,27,26,25,24); // id категорий товаров по которым нужна скидка
    $markup = 0.5;// % Наценки
    $user = wp_get_current_user(); // Получаем текущего пользователя
    $cart = WC()->cart; // Получаем объект корзины
    
    $product = wc_get_product($product_id); // Получаем товар по ID
    

    $base_price = $product->get_regular_price(); // Получаем базовую цену
    if ($attr['price_type'] == 'base') {
        switch ($attr['format']){
            case 'html'  : return number_format($base_price, 2, ',', ' ');
            case 'number': return $base_price;
            default      : return false;
        }
    }
    
    $starting_price = $base_price+$base_price*$markup; // Считаем розничную цену
    if ($attr['price_type'] == 'starting') {
        switch ($attr['format']){
            case 'html'  : return number_format($starting_price, 2, ',', ' ');
            case 'number': return $starting_price;
            default      : return false;
        }
    }
    
    
    $cart_total_price = (float) $cart->total; // общая стоимость корзины


    if ( has_term( $sale_cat_ids, 'product_cat' ,$product->get_id() )){ // если товар находится в скидочной категории
        if ($user->ID){
            $personal_discount = (int)get_the_author_meta('discount',$user->ID)/100;
        }else{
            $personal_discount = 0;
        }
        /*
         * Расчитываем оптовую скидку
         */
        
        if ($cart_total_price >= 0 && $cart_total_price < 2000){
            $wholesale_discount = 0;
        }elseif($cart_total_price >= 2000 && $cart_total_price < 5000){
            $wholesale_discount =  0.05;
        }elseif($cart_total_price >= 5000 && $cart_total_price < 10000){
            $wholesale_discount = 0.1;
        }elseif($cart_total_price >= 10000 && $cart_total_price < 20000){
            $wholesale_discount = 0.15;
        }elseif($cart_total_price >= 20000 && $cart_total_price < 35000){
            $wholesale_discount = 0.2;
        }elseif($cart_total_price >= 35000 && $cart_total_price < 40000){
            $wholesale_discount = 0.25;
        }elseif($cart_total_price >= 40000 && $cart_total_price < 100000){
            $wholesale_discount = 0.3;
        }elseif($cart_total_price >= 100000){
            $wholesale_discount = 0.3;
        }else{
            $wholesale_discount = 0;
        }
        /*
         * Расчитвыаем общую скидку total_discount. Ограничение скидки 30%
         */
        $total_discount = $wholesale_discount + $personal_discount;
        if ($total_discount >= 0.3) {
            $total_discount = 0.3;
        }
        $result = $starting_price - $total_discount*$starting_price;
    }else{
        $result = $starting_price;

    }
    if ($attr['price_type'] == 'final') {
        switch ($attr['format']){
            case 'html'  : return number_format($result, 2, ',', ' ');
            case 'number': return $result;
            default      : return false;
        }
    }


}
WooCommerce выдает ошибку подтверждения заказа после обновления

WooCommerce выдает ошибку подтверждения заказа после обновления

Для работы часто использую платную тему DIVI от ElegantTheme. После последнего обновления WooCommerce сайт перестал подтверждать заказы, хотя в консоли эти заказы отображались. WooCommerce выдавал сообщение «Произошла ошибка подтверждения заказа. Попробуйте подтвердить заказ позднее».

Включив отображение логов я увидел ошибки следующего характера:

PHP Warning: Declaration of ET_Theme_Builder_Woocommerce_Product_Variable_Placeholder::get_available_variations() should be compatible with WC_Product_Variable

Решение проблемы оказалось следующим:

  1. Удалить WooCommerce
  2. Скачать версию WooCommerce не выше 4.6.2
  3. Установить

Ну или как альтернатива нужно обновить шаблон. Поскольку подписка у меня кончилась, то этот вариант мне не подходил.

Как обновить редакцию Windows7

Существует несколько редакций Windows 7. Все они различаются между собой набором функций и работающих служб, но по факту это одна и та же операционная система. Microsoft предусмотрела процесс перехода из одной редакции в другую.

Варианты обновления редакций Windows 7

Для обновления нужно использовать входящую во все редакции Windows7 Windows Anytime Upgrade, которую можно найти в «Пуск». Данное программное обеспечение предназначено для изменение редакции вашей системы. Windows Anytime Upgrade скачивает и включает все необходимые службы, которые необходимы для работы в обновленной редакции. Оля обновления вам нудно будет ввести лицензионный ключ той редакции до которой вы хотите обновиться.

После прохождения процесса обновления в свойствах системы вы увидите изменения.

Добавляем каптчу при регистрации и смене пароля в WordPress

Добавляем каптчу при регистрации и смене пароля в WordPress

После публикации проекта на продакш сервер спам становится головной болью. Особенно если на некоторые действия (например создание нового пользователя) WordPress будет уведомлять вас письмом на Email. Одним из эффектных способов борьбы со спамом является использование механизма каптчи.

Капча (от CAPTCHA — Completely Automated Public Turing test to tell Computers and Humans Apart) — компьютерный тест, используемый для того, чтобы определить, кем является пользователь системы: человеком или компьютером.

Для добавления каптчи мы будем использовать плагин Advanced noCaptcha & invisible captcha. Данный плагин позволяет установить каптчу версии 2 или 3 на следующие активности WordPress

  • Форма входа
  • Регистрационная форма
  • Мультисайт-форма входа
  • Форма восстановления пароля
  • Форма сброса пароля
  • Форма комментариев
  • Новая тема bbPress
  • Ответ в теме bbPress
  • Регистрация BuddyPress
  • Оформление заказа WooCommerce

Плагин так же позволяет нам выбрать версию каптчи для установки, а именно: V2 «Я не робот», V2 невидимая, V3. Для работы каптчи достаточно определить активности, постатвив туда галочки и выбрав версию каптчи.

Так же для работы капчти вам понадобится аккаунт Google. Он нужен для того чтобы получить API ключи для работы капчти с сайтом. Получить ключи нужно на сайте https://www.google.com/recaptcha/.

 

Как легко познакомиться с Adruino

Как легко познакомиться с Adruino

Arduino — это контроллер и удобная платформа быстрой разработки электронных устройств для новичков и профессионалов. Основные преимущества данной платформы — низкий порог входа (подходит как для новичков так и для профессионалов), прекрасно подходит для обучения как основам электроники так и программированию, пользуется огромной популярностью во всем мире благодаря удобству и простоте языка программирования (основан на C/C++ и скомпонован с библиотекой AVR Libc). Устройство программируется через USB без программаторов и прочих танцев с бубном.

Пример проекта собранного на Arduino можно посмотреть тут.

Я с детства немного интересовался электроникой, долго присматривался к контроллерам но руки до этого не доходили. Мне казалось это сложно. Очень сложно. Но в один момент я всё-таки решился.

Как познакомиться не покупая?

Хотя сам Arduino стоит не дорого. Но изучение Arduino предполагает еще и набор различных электронных компонентов, а их понадобится много, и разных. А вот это уже будет стоить денег.

Например готовый базовый набор контроллера с компонентами на Aliexpress будет стоить уже в районе 2500-3000 рублей.

Набор для изучения Arduino

Набор для изучения Arduino

Если вы хотите просто познакомиться с Arduino, но не хотите тратить на это деньги то можно воспользоваться эмулятором AutodeskTinkercad.

Данный эмулятор работает в браузере и не требует установки дополнительного программного обеспечения (кроме браузера само собой). В нем есть базовый контроллер ArduinoUno и набор электротехнических компонентов (резисторы, светодиоды, кнопки, датчики и тд.). Использование эмулятора предполагает наличие базовых навыков программирования и знания школьной физики. Для наглядности присутствуют уже готовые собранные и запрограммированные схемы.

Пример схемы AutodeskTinkercad

Пример схемы AutodeskTinkercad

Кроме наличия возможности собирать разные схемы и с разными элементами все это можно и программировать. Поскольку данный эмулятор рассчитан на начинающих программировать можно двумя способами:

1. Визуально с помощью блоков

2. Классически с помощью текстового редактора

Таким образом можно программировать контроллер визуально (преемственность с LEGO WEDOO, LEGO mindstorms которые активно используются в российской системе образования), так и классически с помощью написания кода на языке С/С++.

Собрав схему и написав программу (к слову программы для Arduino называю скетчами) вы увидите рабочий результат (при условии что вы все сделали верно). В эмуляторе присевают некоторые ошибки (например я столкнулся с ошибкой таймера, когда делал таймер обратного отсчета), но даже с учетом ошибок его точно вам хватит для ознакомления.

Набор ресурсов для самостоятельного изучения:
http://edurobots.ru/
https://all-arduino.ru/
https://alexgyver.ru/arduino_shop/