Перейти к содержимому


Фотография
* * * * * 2 Голосов

Как сделать свой элемент для скидки в JBZoo 220?

рецепт элемент 220v скидка

Сообщений в теме: 13

#1 SmetDenis

SmetDenis

Отправлено 17 June 2015 - 08:00

*
Популярное сообщение!

Это гайд для тех, кто хочет сделать собственный элемент скидки и он знает основы PHP (либо близкие к нему).

Что вам понадобится?
- Руки и голова
- Немного терпения, чтобы дочитать этот гайд.
- От 5 минут времени на программирование.
- Элементарные основы PHP.
- Сайт на основе 220+


Вместо введения

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

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


Где находится элемент?

Все элемент лежат в этой папке /media/zoo/applications/jbuniversal/cart-elements
Они строго разделены по папкам-типам (своему предназначению). Т.к. нас интересует скидка, то смотрим одну из папок

- modifieritemprice - скидка на определенный товар или группу (до добавления в корзину)
- modifierorderprice - скидка применяется на весь заказ сразу после вычисления предварительной суммы.


Анатомия элемента или из чего он состоит?
Минимальный набор для любого элемента - это...
- element.xml файл, который описывает набор настроек и добавляет мета информацию (название, автора, версию).
- element.php файл, который по сути и реализует всю логику элемента

Остальное содержимое папки элемента - опциональное
- assets - статическое содержимое для элемента, т.е JavaScript, CSS и картинки
- tmpl - папка с шаблонами элемента
- language - место хранения локализация для элемента

Иногда бывают другие файлы и папки, но это уже особенности конкретного элемента.

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

Создаем два новых файла
/cart-elements/modifierorderprice/ mydiscount / mydiscount.php
/cart-elements/modifierorderprice/ mydiscount / mydiscount.xml

Открываем php файл, добавляем туда код
class JBCartElementModifierOrderPriceMydiscount extends JBCartElementModifierOrderPrice { }
Обратите внимание, что имя класса составное JBCartElement + ModifierOrderPrice + Mydiscount . Регистр именования класса нас не сильно волнует.

В xml добавляем типичный набор мета данных. Настройки обсудим позже
<?xml version="1.0" encoding="utf-8"?>
<element type="element" group="Core" hidden="false">
    <name>My Discount</name>
    <author>SmetDenis</author>
    <creationDate>2015</creationDate>
    <copyright>Copyright (C) JBZoo.com</copyright>
    <authorEmail>denis@jbzoo.com</authorEmail>
    <authorUrl>http://jbzoo.com</authorUrl>
    <version>1.0</version>
    <description>Simple example</description>
</element>
 

Как работает любая скидка в JBZoo 220?

Вся работа элемента сводится к работе одного метода getRate(). Его задача вернуть положительно (для наценки) или отрицательное(для скидки) число, которое затем будет добавлено к обрабатываемой сумме (товара или всего заказа).
Допустим, мы хотим добавить скидку в 10% если сумма за все товары больше 2000 рублей.
    public function getRate()
    {
        $orderSum = $this->_order->getTotalForItems(); // получили сумму за все товары (без доставки и прочего)
        $discount = 0;
        if ($orderSum->compare('2000rub', '>=')) { // сравниваем c 2000 рублей
            $discount = '10%'; // скидка, если сумма больше
        }

        return $this->_order->val($discount)->negative(); // обязательно вернуть объект и добавляем знак минус (чтобы была скидка)
    }
 
Как видите, все довольно просто. Единственный вопрос. который может у вас тут появиться, почему мы не работаем с нормальными числами а с объектом.
 
Дело в том, что от товара до создания заказа сумма (так что, к оплате) может претерпевать огромное количество изменений. На вскидку,
- товар стоит 100 грн.
- добавляем его в корзину 5 шт (500грн)
- добавляем другой товар в 100 руб, 4 штуки
- срабатывает модификатор скидки для второго товара если кол-во больше 3-х (-10%)
- человек в корзине указывать промо код (-15% ко всему заказу)
- вычисляется сумма доставки через "Новую почту" (+58 грн).
- клиент оплачивает через PayPal в долларах по курсу сайта
 
Получаем примерную форуму (на пальцах)
Сумма заказа = (((100uah * 5) + ((100rub * 4) - 10%) - 15%) + 58uah ) => usd
 
Если развернуть все вычисления, то получим огромную портянку кода, где добрая доля - это вызова конвертирования валюты и вычисления процентов. Всю эту реализацию скрывает объект JBCartValue. Он очень важен в работе сайта, целиком и полностью зависит от настроек валюты. Поэтому мы акцентируем на них большое внимание.


Добавляем элементу параметры
Чтобы каждый раз не лезть в код, добавим 2 параметра в элемент - лимит и размер скидки.
Т.е при достижении лимита - сработает скидка.

Для этого в XML объявляем блок params и добавляем туда две строки. Особое внимание обратите на name, по нему мы будем обращаться в коде.
    <params>
        <param name="rate" type="text" default="10%" label="Discount"/>
        <param name="limit" type="text" default="10000" label="Limit"/>
    </params>
Чтобы получить доступ к сохраненным параметрами используем объект config внутри элемента
$rate = $this->config->get('rate', '20%'); // здесь 20 - это значение по умолчанию
Почти "волшебный" объект суммы JBCartValue
Как вы уже поняли, для работы с суммами мы активно используем объект JBCartValue, который скрывает внутри себя все вычисления. Возможностей у объекта огромное количество, желающие могут посмотреть его реализацию тут
media\zoo\applications\jbuniversal\framework\classes\cart\jbvalue.php
 
Я не будут перечислять все (оставлю на внеклассное чтение), только акцентирую внимание на самом важном
Создание объекта. Есть два разных варианта и они зависят от того создан ли заказ или еще нет.
Дело в том, что после создания заказа (он уже сохранен в базе), информация о курсах валюты копируется и сохраняется в заказ. Таким образом, если курс подскочит, на конечный заказ это не повлияет.


<?php
$sum = JBCart::val(); // нулевая сумма, на основе текущих валют
$order->val(); // нулевая сумма, валюты из конкретного заказа
$this->_order->val(); // тоже самое, обращение из элемента скидки, т.е $this - это объект элемента
 
Если заказ еще не создан (т.е еще находится в сессии), то для объекта берутся текущие валюты. С этим думаю понятно. Поехали дальше.
Другие примеры создания объекта суммы
// 10 единиц в валюте по умолчанию
$sum = JBCart::val(10);
 
// 10 единиц в конкретной валюте
$sum = JBCart::val(10, 'usd');
$sum = JBCart::val('10rub');
$sum = JBCart::val(aray('10', 'UAH'));
 
// встроенный парсер сам разберется что мы от него хотим (уберет пробелы, разберется с запятыми)
$sum = JBCart::val('-50,6 eur');
$sum = JBCart::val('-50.6eur');
$sum = JBCart::val(' - 5 0 . 6 eur ');
$sum = JBCart::val(' + 5 0 , 6 % ');
 
// и даже проценты
$sum = JBCart::val('-15%');
Как сравнить две цены
$val1 = JBCart::val('55usd');
$val2 = JBCart::val('55eur');
if ($val1->compare($val2, '<=')) { // проверка 55usd <= 55eur
   
}

if ($val1->compare('100 uah', '=')) { // 55usd == 100uah

}
Как изменить сумму
$val1 = JBCart::val('10usd');
$val2 = JBCart::val('1eur');

$val1->add($val2); // после этого в val1 будет хранится чуть больше 11 долларов в валюте "доллар"
$val2->add($val1); // после этого в val2 будет хранится чуть больше 11 долларов в валюте "евро"

$val2->add('-10rub'); // отнимаем 10 рублей от 1 евро
$val2->minus('10%'); // скидка 10% от 1 евро
Рендеринг
$val = JBCart::val('20', 'usd');
echo $val->noStyle() . '<br>'; // без стиля (округление и форматирование не применяется)
echo $val->val() . '<br>'; // просто текущее значение без валюты
echo $val->plain() . '<br>'; // другой текстовый вывод,
echo $val->html() . '<br>'; // полный вариант для JS и со всеми стилями
echo $val->text() . '<br>'; // html с обработкой strip_tags

// в любой метод можно передать валюту, чтобы без конвертирования (состояние объекта не изменится)
// вывести число в другой валюте
echo $val->html('RUB');
Конвертирование (не советую без срочной необходимости)
$val = JBCart::val('10usd');
$val->val(); // значение в долларах
$val->convert('rub');
$val->val(); // значение в рублях
Отладка (включите режим отладки Joomla)
$val = JBCart::val('10usd');
$val->dump(); // чистейшее состояние объекта без форматирования, округления и стилей
$val->logs(); // история изменений объекта
Все и сразу :)
$value = JBCart::val('10 eur')->debug(1);

dump($value->text(), 0, 'before add');

$value
    ->convert('rub')
    ->add('10%')
    ->add('-5 rub')
    ->minus(array('-5', 'rub'))
    ->minus(array('5', 'rub'))
    ->multiply(9)
    ->abs()
    ->negative()
    ->invert()
    ->positive()
    ->invert()
    ->setFormat(array('num_decimals' => -2), 'rub')
    ->add(500);

dump($value->logs(), 0);
dump($value->dump(), 0, 'after add');
Простейший элемент
Объединяем все накопленные знания и делаем скидку 10% для заказа где сумма больше 100 000 рублей.

Настройки
zzf3_200x0.png

Элемент в действии
sh4p_200x0.png

Архив с элементом можно найти в нашем маркете - http://forum.jbzoo.c...delennoj-summy/

Версии
Тестировал на JBZoo 2.2.0 rev2778, Zoo 3.3.4, Joomla 3.4.1

PS Топик будет дописываться по мере спроса, в скором времени появится в общей документации.
  • 8
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#2 COBETHIK

COBETHIK

Отправлено 23 June 2015 - 17:18

Крайне признателен за предоставленный рецепт, только остались вопросы его применения к моему текущему проекту по аренде. В нем фигурирует время от и до, с учетом даты, часов и минут. Стоимость и скидка высчитываются в зависимости от:

  • количества суток
  • рабочая неделя (с понедельника по пятницу, включительно)
  • тариф выходного дня (с пятницы по воскресенье, включительно)
  • стоимость перепробега
  • рабочий день (с 9:00 до 19:00)

Как лучше привязаться ко времени?


  • 0

#3 SmetDenis

SmetDenis

Отправлено 23 June 2015 - 17:45

Временные рамки легко задать с помощью date http://php.net/manua...nction.date.php
Только учитывайте часовой пояс клиента и настройки Joomla

flzr_200x0.png
 
$curHour = (int)date('H');
if ($curHour >= 9 && $curHour < 19) {
    // рабочий день
}
По аналогии с буднями и выходными.

"стоимость перепробега" - не знаю что это :)
  • 0
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#4 Cheren-dow

Cheren-dow

Отправлено 09 September 2015 - 14:03

Как изменить вывод в корзине и вывести скидку в процентах, а так же в валюте сайта можно узнать в этом топике.


  • 2
Изображение
 

#5 Ёшкин Кот

Ёшкин Кот

Отправлено 12 November 2015 - 12:00

А вот как достучаться из этого самого элемента до стоимости доставки. могу ли я вместо скидки на окончательную стоимость обнулить стоимость доставки?

 

как будет выглядеть это все дело?


  • 0

#6 SmetDenis

SmetDenis

Отправлено 13 November 2015 - 12:11

А вот как достучаться из этого самого элемента до стоимости доставки. могу ли я вместо скидки на окончательную стоимость обнулить стоимость доставки?

 

К такому жизнь меня не готовила... Хотя функция выглядит заманчиво.

 

Теоретически сделать так можно, но только если доставка будет иметь какое-то средство манипулации. Готовых функций во фреймворке не предусмотрено.

 

Либо, можно внутри доставки проверять условие из другого элемента.

 

Доступ к цене доставки можно получить только на чтение

$price = $this->_order->getShippingPrice();

 

У класса JBCartOrder есть масса других методов, по больше части все на чтение внутреннего состояния заказа.


  • 0
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#7 zeus07

zeus07

Отправлено 04 October 2016 - 17:34

Решил написать тут, дабы не создавать отдельную тему.

 

Как сделать элемент скидки, в зависимости от выбранного способа оплаты? К примеру, при выборе способа оплаты Robokassa или Яндекс-Деньги, сделать скидку в 3%?


  • 0

#8 SmetDenis

SmetDenis

Отправлено 06 October 2016 - 06:40

Чтобы проверить выбранный способ оплаты

$type = $this->getOrder()->getPayment()->getElementType();
if ($type === 'robokassa') {
   // ...
}

 

Но код сработает только после создания заказа.


  • 0
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#9 zeus07

zeus07

Отправлено 06 October 2016 - 08:29

Большое спасибо. А если в моём случае есть только одна кнопка "Создать и оплатить"? Модификатор сработает по нажатию на неё? Как я понимаю, пользователь видит итоговую сумму, затем выбирает способ оплаты (Робокасса или ЯД) и перейдя непосредственно к оплате видит сумму на 3% ниже? Так будет работать?


  • 0

#10 SmetDenis

SmetDenis

Отправлено 06 October 2016 - 09:09

Да, модификатор сработает позже и это не правильное поведение.

Дело в том, что мы не расcчитывали на такие вещи при разработке API/


  • 1
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как можно скорее!



— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.






Темы с аналогичным тегами рецепт, элемент, 220v, скидка

Click to return to top of page in style!