Встречайте первый компонент реферально-бонусной программы для miniShop2 - msReferralProgramCoin

Компонент маркетинга(реферально-бонусная система основанная на кешбэке собственной монетой твоего магазина и персональных промокодах для учета рефералов от количества которых зависит индивидуальный процент кешбэка) приводящего клиентов для магазинов основанных на miniShop2 — msReferralProgramCoin

По просьбам пользователей добавлено:
  • В контекстное меню списка товаров добавлены пункты массовой установки и снятия флага участия товара в бонусной программе у выбранных в этом списке товаров
  • Две настройки приветственного бонуса при регистрации:
    1. Само количество бонусных монет зачисляемых на баланс покупателя при регистрации (по умолчанию 0).
    2. Флаг зачисления приветственных бонусов только в том случае если введен валидный промокод пригласившего, что усилит мотивацию ввода промокода пригласившего!

  • Для простоты установки и контроля флаг участия товара в бонусной программе кешбэка добавлен в саму таблицу товаров в дополнение к чекбоксу на вкладке «Свойства товара».
  • Массовое ручное начисление/списание бонусных монет с баланса пользователей.
  • В компонент добавлен пересчет бонусов к начислению и списанию и соответственно пересчет общей суммы заказа с учетом списываемых бонусных монет и стоимости доставки при редактировании заказа в панели управления сайтом!
  • Добавлена настройка количественного отношения бонусной монеты к валюте магазина с показом пользователю сколько одной единице бонусной монеты будет приходиться частей(1, 0.1, ...) валюты магазина.
в версии 1.2.0 будет добавлено:
  • Регистрация по рефссылке в дополнение к уже имеющейся регистрации по персональному промокоду пригласившего.

Пример использования на одном из сайтов клиентов здесь

Уточнение по механизму начисления и списания монет с новыми возможностями:
  • В последней версии 1.1.6 добавлена кратность монет т.е. если в настройке прописать 100 то 1 коин будет стоить 0.01 валюты магазина, и если у покупателя установлен процент кешбэка 3% и покупка на $1000(товарами отмеченными для участия в бонусной) то ему на баланс придет 3000 монет.
  • Оплата корзины идет по настроенному максимальному проценту оплаты корзины т.е. если настроено, что монетами можно оплатить 30% корзины то при покупке на $10 с установленным чекбоксом оплаты монетами сумма заказа станет $7 и на балансе останется 2700 монет из предыдущего пункта.
  • Приветственные монеты можно добавить в панели управления сайтом, но, думаю в версии 1.1.7 добавлю настройку в которой можно внести количество приветственных бонусов при регистрации ;)
  • Статусов золотой, платиновый… нет, но можно доработать за доп оплату.
  • Название монеты сам придумываете в настройках.

УЗНАТЬ ПОДРОБНЕЕ
Руслан
03 мая 2020, 16:40
modx.pro
3
3 044
+10
Поблагодарить автора Отправить деньги

Комментарии: 60

Sergey (Sentinel)
03 мая 2020, 16:47
+1
А где компонент? На рассмотрении пока?
Александр Мельник
03 мая 2020, 17:04
+1
Как раз в планах разработка подобного функционала
    Руслан
    03 мая 2020, 17:07
    0
    Привет, Александр! в текущей версии пока коды открыты в статике, а следующая версия уже будет с внедренной недавно появившейся защитой от модстор ;)
      Александр Мельник
      03 мая 2020, 17:20
      +1
      заманчиво) Но два нюанса — во-первых интересно самому, если уж не выйдет, то буду думать о покупке. Ну и самое главное, сайт, куда данный функционал необходим, сильно модифицирован, там переписаны ядра как модекса, так и минишопа и 95 процентов чужих компонентов там не работают.
        Руслан
        03 мая 2020, 17:27
        0
        из минишопа используется только таблица заказов для хранения допполей начисления и списания, ИДы статусов которые использует компонент прописываются в настройках, и в панели управления сайтом на вкладку свойства товара на странице редактирования товара добавляется флаг использования в бонусной который хранится в таблице ресурсов, что реализуется подключаемым js вместо которого можно использовать свой прописав в системных настройках компонента путь к своему js и код там элементарнейший
        //Add msrpc_check field to minishop2's products
        Ext.ComponentMgr.onAvailable('minishop2-product-tab', function () {
            this.on('beforerender', function() {
                // Получаем колонки вкладки свойств товаров
                var rightCol = this.items.items[0].items.items[2].items.items[0].items.items[1];
                // Текущий объект
                var record = Ext.getCmp('modx-panel-resource').record;
        
                // Добавляем чекбокс четвертым по счёту полем (перед чекбоксом 'Новый')
                rightCol.items.insert(4, 'modx-resource-msrpc-check', new Ext.form.Checkbox({
                    id: 'modx-resource-msrpc-check',
                    name: 'msrpc_check',
                    hideLabel: true,
                    boxLabel: 'Участвует в бонусной программе',
                    description: '[[+msrpc_check]]',
                    xtype: 'xcheckbox',
                    inputValue: 1,
                    listeners: {
                        beforerender: function(that) {
                            that.hiddenField = new Ext.Element(document.createElement('input')).set({
                                type: 'hidden',
                                name: that.name,
                                value: 0,
                            });
                        },
                        afterrender: function(that) {
                            that.el.insertHtml('beforeBegin', that.hiddenField.dom.outerHTML);
                        }
                    },
                    checked: record['msrpc_check'] || false
                }));
            });
        });
        ;)
        а для управления процентом кешбэка и просмотром количества рефералов используется своя страница компонента в панели управления сайтом
          Руслан
          03 мая 2020, 17:48
          0
          О, как-раз заметил маленькую помарочку в моём этом коде :)))
          вместо
          boxLabel: 'Участвует в бонусной программе',
          должно браться из лексикона
          boxLabel: _('msrpc_check_name'),
          Спасибо!
    Aleksandr Huz
    03 мая 2020, 17:34
    +6
    Чтобы прочитать эту кашу нужно иметь большое терпение или желание.
      Руслан
      03 мая 2020, 17:38
      +1
      Привет! Спасибо за замечание, просто я не писатель, а создатель и на этот компонент ушло около месяца работы и теперь есть время эту кашу превратить в удобочитаемое описание, исправлюсь ;)
        Василий Наумкин
        03 мая 2020, 19:09
        +7
        Я думаю, тут больше вопрос к оформлению заметки.

        Отступы там, выделение — форматирование, в общем. Сейчас и правда тяжело читать.
          Руслан
          03 мая 2020, 19:33
          0
          Василий, привет!
          Спасибо за замечание, я это понимаю и обязательно поправлю немного позже.
          Извините за эту портянку все кто сейчас читает это :)
          я немного не привык на публику ибо в коде с 9-ти лет(профессионально с 15ти), а мне 41 год уже и только начинаю, так сказать, в свет выходить из индивидуальных разработок :)))
            Василий Наумкин
            04 мая 2020, 03:27
            +3
            Это если ты деньги кодом зарабатываешь с 1994 года, то нас всех ждут великие открытия, не сомневаюсь!

            У меня, например, личный ПК появился только в 1995, причём не как сейчас принято «для учёбы», а конкретно для игр. Ни о какой работе там и речи не было.
              Руслан
              04 мая 2020, 08:37
              0
              Да не :) деньги я уже лет с 11ти на этом делал, а профессионально когда реально торкнуло программирование, что даже боялся умереть только из-за того, что «там» нет компа в конце 93тьего когда вышла винда 3.11 :)))
              первый комп БК0010-01 был куплен моим отцом именно для работы ещё в 87мом году на котором и начал изучать программирование на бейсике (фокал не зашёл с его дополнительным картриджем который в эту клавиатуру-комп нужно было пихать), но больше зашли машкоды :)
              на этом чуде мне очень нравилась игра болдер и я наконец-то в 2011том когда пробило на геймдев на мобилки переделал(с нуля по впечатлениям на плюсах написал правда чтобы лабиринты были теми-же пришлось на эмуляторе всю пройти и перерисовать все уровни) эту игру как я её тогда видел где-то около полугода код вылизывал и оптимизировал чтобы на моём тогдашнем BADAфоне бюджетнике Samsung Wave M без тормозов шло пришлось сделать вторую версию на шейдерах тогдашнего OpenGL ES2 и даже для синхронизации параллельных потоков отказаться от тормознутых семафоров C++ и свой велосипед на указателях накатать :) и в итоге вот, что получилось youtu.be/bZVpwAK5M0s?t=95 но выстрелило как обычно то на, что ушло гораздо меньше времени (несколько дней на коленке) живые обои на андроид на шейдерах управляемые тачем :) youtu.be/jy4AxEOnr-Y?t=36 которые позже сварганил.
              так, куда-то меня понесло :)))
                Руслан
                04 мая 2020, 09:13
                0
                Ха, кстати, сейчас когда искал ссылку на своё видео с игрой увидел, что месяц назад мне Алексей создатель этой игрухи коммент оставил под видео :)))
                вот его версия игры youtu.be/ghZ3iQQj0iI сам оригинал который он в конце восьмидесятых создал :)
                Руслан
                04 мая 2020, 17:11
                0
                Василий, привет! а теперь нормально оформлено?
          Руслан
          04 мая 2020, 17:12
          0
          Александр, привет!
          А теперь нормально оформил?
            Aleksandr Huz
            04 мая 2020, 17:20
            0
            Привет, Руслан!
            Намного лучше, но код тоже лучше оформить.
            Вместо: [[!msrpcCart? &tpl=`свой чанк` &tplInfo=`свой чанк инфо`]]
            Сделать так:
            [[!msrpcCart? 
                &tpl=`свой чанк` 
                &tplInfo=`свой чанк инфо`
            ]]
              Руслан
              04 мая 2020, 17:33
              0
              Понял, спасибо, иду исправлять :)
          Руслан
          04 мая 2020, 17:47
          +1
          Кстати, именно для MODX компонеты писать научился у Артёма Зернова на его курсе по созданию компонентов ;)
          Spirit_Ninja
          08 мая 2020, 13:06
          0
          Клево!
          Руслан
          09 мая 2020, 07:20
          0
          Привет всем!
          Очень извиняюсь, что пока изначально сниженная цена от реальной (3900 рублей) не обновилась до необходимых 975 рублей. Модераторов очень попросил поменять цену и пока никто не ответил на мой запрос, но сегодня обязательно компонент будет по цене 975 рублей :)
          Спасибо за терпение и понимание!
            Руслан
            09 мая 2020, 11:50
            0
            Цена компонента успешно уменьшена на 75% распродажи и теперь составляет символичные 975 рублей ;)
            Евгений
            09 мая 2020, 11:31
            0
            Руслан, а есть ли возможность сделать так, чтобы пользователь делился своим промо кодом и чтобы ему начислялись бонусные монеты?
            Просто компонент позиционируется как реферально-бонусная программа, но бегло просмотрев документацию не увидел подобной возможности
              Руслан
              09 мая 2020, 11:44
              0
              Евгений, привет! Так в настройках устанавливается изначальный процент кешбэка и пришедший пользователь может ввести промокод пригласившего как при регистрации так и на странице профиля или самой бонусной (там куда вы решите поставить полный сниппет бонусной), но процент кешбэка в любом случае будет как установлен в настройках по умолчанию, а дальше в панели управления сайтом ваш менеджер на странице компонента очень удобно в отсортированном списке по количеству приведенных рефераллов может индивидуально увеличить процент кешбэка каждому покупателю в отдельности и там-же также удобно модет добавить или убрать любое количество монет покупателю ;)
              Если принципиально необходимо поощрение покупателя за ввод промокода для мотивации его ввода(о чем мы всеми много размышляли и в итоге решили, что это совершенно не нужно для текущей реализации) покупателем то вы напишите поддержку компонента и я внесу дополнительный функционал в виде допнастройки в которой можно будет установить приветственный плюс процент к проценту по умолчанию тому кто ввел промокод пригласившего.
                Руслан
                09 мая 2020, 11:56
                0
                И делиться промокодом это-же неотъемлемая часть компонента :)
                Руслан
                09 мая 2020, 12:06
                0
                и в описание прописал это:
                «Покупатель делится своим персональным красивым и защищенным от подделки промокодом привязывая тем самым пришедших покупателей к себе в рефералы по количеству которых менеджер сайта принимает решение увеличит индивидуальный процент кешбека этого покупателя.»
                Спасибо за замечание :)
                  Руслан
                  13 мая 2020, 20:15
                  +3
                  Уточнение по механизму начисления и списания монет с новыми возможностями:
                  • В последней версии 1.1.6 добавлена кратность монет т.е. если в настройке прописать 100 то 1 коин будет стоить 0.01 валюты магазина, и если у покупателя установлен процент кешбэка 3% и покупка на $1000(товарами отмеченными для участия в бонусной) то ему на баланс придет 3000 монет.
                  • Оплата корзины идет по настроенному максимальному проценту оплаты корзины т.е. если настроено, что монетами можно оплатить 30% корзины то при покупке на $10 с установленным чекбоксом оплаты монетами сумма заказа станет $7 и на балансе останется 2700 монет из предыдущего пункта.
                  • Приветственные монеты можно добавить в панели управления сайтом, но, думаю в версии 1.1.7 добавлю настройку в которой можно внести количество приветственных бонусов при регистрации ;)
                  • Статусов золотой, платиновый… нет, но можно доработать за доп оплату.
                  • Название монеты сам придумываете в настройках.

                  По просьбе пользователей:
                  • В компонент добавлен пересчет бонусов к начислению и списанию и соответственно пересчет общей суммы заказа с учетом списываемых бонусных монет и стоимости доставки при редактировании заказа в панели управления сайтом!
                  • Добавлена настройка количественного отношения бонусной монеты к валюте магазина с показом пользователю сколько одной единице бонусной монеты будет приходиться частей(1, 0.1, ...) валюты магазина.
                    Руслан
                    18 мая 2020, 23:21
                    +1
                    По просьбам пользователей в версии 1.1.7 добавлено:
                    • Две настройки приветственного бонуса при регистрации:
                      1. Само количество бонусных монет зачисляемых на баланс покупателя при регистрации (по умолчанию 0).
                      2. Флаг зачисления приветственных бонусов только в том случае если введен валидный промокод пригласившего, что усилит мотивацию ввода промокода пригласившего!

                      Руслан
                      21 мая 2020, 01:36
                      0
                      По просьбам пользователей в новой версии 1.1.8 добавлено:
                      • Две настройки приветственного бонуса при регистрации:
                        1. Само количество бонусных монет зачисляемых на баланс покупателя при регистрации (по умолчанию 0).
                        2. Флаг зачисления приветственных бонусов только в том случае если введен валидный промокод пригласившего, что усилит мотивацию ввода промокода пригласившего!

                      • Для простоты установки и контроля флаг участия товара в бонусной программе кешбэка добавлен в саму таблицу товаров в дополнение к чекбоксу на вкладке «Свойства товара».
                      • Массовое ручное начисление/списание бонусных монет с баланса пользователей.
                      • В компонент добавлен пересчет бонусов к начислению и списанию и соответственно пересчет общей суммы заказа с учетом списываемых бонусных монет и стоимости доставки при редактировании заказа в панели управления сайтом!
                      • Добавлена настройка количественного отношения бонусной монеты к валюте магазина с показом пользователю сколько одной единице бонусной монеты будет приходиться частей(1, 0.1, ...) валюты магазина.
                      в версии 1.1.9 будет добавлено:
                      • Регистрация по рефссылке в дополнение к регистрации по персональному промокоду пригласившего.
                        Руслан
                        23 мая 2020, 04:56
                        0
                        В новой версии 1.1.9 в контекстное меню списка товаров добавлены пункты массовой установки и снятия флага участия товара в бонусной программе у выбранных в этом списке товаров.
                          Сергей
                          26 мая 2020, 11:48
                          0
                          Добрый день!
                          Можно к компоненту добавить возможность выводить заработка?
                            Руслан
                            26 мая 2020, 16:35
                            0
                            Сергей, привет!
                            о каком заработке идет речь?
                            в компоненте реализованы как сниппеты самого механизма учета так и сниппеты вывода информации о текущем проценте кешбэка покупателя и количества его монет, а также количество и процент вы можете у каждого пользователя видеть и руками поменять в панели управления сайтом на странице самого компонента.
                              Сергей
                              29 мая 2020, 16:32
                              0
                              Это же реферальная система, если я приведу клиента он купить товар, я заработаю процент, верно? Если мне не нужны товары те, что представлены на сайте, я например хочу вывести свой заработок, то как это можно сделать? В этом вроде и есть суть привода клиентов по реферальной ссылке.
                                Руслан
                                30 мая 2020, 21:02
                                0
                                Привет, заявка на вывод планируется в профессиональной версии компонента где будет реализована полноценная двухуровневая партнёрка, а здесь кешбэк монетой магазина именно на покупки магазина и привод клиентов увеличивает процент кешбэка ;)
                            Руслан
                            28 мая 2020, 22:52
                            0
                            В версию 1.1.11 добавлен пересчет списываемых монет при оплате монетами и при удалении товара из корзины :)
                              Руслан
                              01 июля 2020, 20:40
                              0
                              Интересная и очень полезная статья про правильное использование бонусной программы www.retail.ru/rbc/pressreleases/pervaya-sistema-bonusnaya-sistema-skidok/
                                pr-light
                                24 сентября 2020, 15:20
                                0
                                Очень и очень интересно, когда планируется выпуск про версии?
                                  Руслан
                                  25 сентября 2020, 12:16
                                  0
                                  Нет финансирования, занимаюсь более насущными задачами :)
                                    pr-light
                                    08 октября 2020, 16:57
                                    0
                                    так верни цену этого как было, никто не против пару кусков за это чудо закинуть, вот тебе и финансирование
                                      Руслан
                                      08 октября 2020, 19:30
                                      +1
                                      за всё время 3 реальных покупки даже по 390р. так. что пускай уж бесплатно будет ;)
                                        Руслан
                                        08 октября 2020, 21:52
                                        0
                                        у меня в данный момент итак работы много в данный момент создаю систему франчайзинга в моей автоматизации включающей 1с, ритейлцрм и сайт hookah.pro (MODX выбрал для разработки клиент и мне пришлось за пару недель его до такой степени изучить, что даже создал им этот компонент оцененный специалистом по разработке компонентов в 120тр именно в моём исполнени основанном на моём 30ти летнем опыте программирования на разных языках)

                                        плюс ко всему мною созданная архитектура этой автоматизации работает полностью в реальном времени и более того в 1с уже все включая менеджеров лезут только за отчетами так как всё создается и пересоздается автоматически по данным црм(заказы, оплата, реализации… и из розничных точек из ТСД(терминал сбора данных)заказы летят через 1С в црм и дальше там обрабатываются и в реальном времени обновляются в 1С и на сайте(резервы и остатки напряую нативным кодом 1С практически в реальном времени по пакетному АПИ написанному мной для сайта плюс на сайте мной реализована проверка остатка по АПИ црм при создании заказа из корзины так как в црм чуть быстрее чем на сайте происходит обновление остатка за минусом резерва прилетевшего из црм заказа в 1с тут-же отражается в црм по нему 1Сный резерв!) так как создан мной вебсервис в 1С и 1С поднята как вебсервер принимая хуки изменения сразу из црм...) и даже заказы поставщикам и перемещения по складам моими обработками создаются по расписанию по уникальным алгоритмам вычисления потребности по каждой категории товаров
                                          pr-light
                                          25 октября 2020, 16:40
                                          0
                                          звучит сильно загруженно) но все-равно осмелюсь спросить — нам нужна будет помошь по интеграции и настройке сия… написал тебе в телеграм сообщение.
                                          но сюда продублирую:
                                          мы сейчас небольшой сервис пилим, очень хочется рефералку, возможно ли будет рассчитывать, на помощь в установке и настройке плагина и сколько это будет стоить, а так же о каких суммах может идти речь по доработке по реферальным ссылкам
                                            Николай Савин
                                            25 октября 2020, 19:25
                                            0
                                            компонент оцененный специалистом по разработке компонентов в 120тр именно в моём исполнени основанном на моём 30ти летнем опыте программирования на разных языках
                                            А можно поинтересоваться кто именно из специалистов по разработке компонентов оценил стоимость? Их немного в общем то.
                                              Руслан
                                              02 ноября 2020, 19:33
                                              0
                                              Артём
                                                Руслан
                                                02 ноября 2020, 19:37
                                                +1
                                                кстати, допилил твой компонент для работы с разными аккаунтами црм, мне для системы франчайзинга понадобилось так как будет куча аккаунтов црм и в одном сеансе заказ раскидывать по франчам регионов придется
                                      Кирилл
                                      09 февраля 2021, 10:48
                                      0
                                      компонент вообщебез слов, спасибо огромнейшее

                                      подскажите пожалуйста как поправить данный баг

                                      modx revo 2.8.1 minishop 2.8 msReferralProgramCoin 1.1.11-pl

                                      захожу в категорию с товарами

                                      неоткрываеться вкладка товар и вообще никакие вкладки, зависает на tv созданном для товаров отдельно привязанному к шаблону, комплектация с разными свойствами и тд (((

                                      а так всё больше чем нормально
                                        Руслан
                                        02 марта 2021, 16:40
                                        0
                                        Кирилл, привет, только зашел сюда :)
                                        без TV всё работает?
                                        передал по твшкам спецу так как сам твшки не пользую я больше по бэку
                                          Руслан
                                          02 марта 2021, 16:55
                                          0
                                          Там много, что может быть, от ошибки при записи кеша админки до отсутствия какого-то модуля на php нужного для выполнения скрипта или вообще просто скрипты MODX в твоём браузере не хотят работать.
                                          Стоит начать с того чтобы зайти через другой браузер попробовать.
                                          Да, и лог ошибок можно посмотреть, может там что есть.
                                            Руслан
                                            02 марта 2021, 17:23
                                            0
                                            и в самом компоненте есть небольшая недоработка по работе с заказом в админке(этот функционал не был изначально в задумке, но позже на скорую руку добавил) так как реализована работа с монетами авторизованного пользователя то при записи заказа в админке используются монеты авторизованного в админке, там всего несколько строк изменений, но я выкатить это не могу так как среда разработки была на винде, а сейчас я на маке и тупо нет возможности плюс не приобрел ещё лицензию на PHPSTORM на котором реализовывал компонент.
                                            здесь теперь реализовано от ИД пользователя из заказа
                                            файл:

                                            новое содержимое файла:
                                            <?php
                                            
                                            class msrpcMain {
                                                /** @var modX $modx */
                                                public $modx;
                                                /** @var array $config */
                                                public $config;
                                            
                                                public function __construct(&$modx, $config = array()) {
                                                    $this->modx = &$modx;
                                                    $this->config = array(
                                                        'css_url' => $this->modx->getOption('msrpc_css_url', null, MODX_ASSETS_URL.'components/msreferralprogramcoin/styles/main.css'),
                                                        'js_url' => $this->modx->getOption('msrpc_js_url', null, MODX_ASSETS_URL.'components/msreferralprogramcoin/js/web/msrpcincluder.js'),
                                                        'connector_url' => $this->modx->getOption('msrpc_connector_url', null, MODX_ASSETS_URL.'components/msreferralprogramcoin/connector.php'),
                                                        'name_coin' => trim($this->modx->getOption('msrpc_name_bonus_coin',null, 'Coin')),
                                                        'default_pr_payroll' => (int)$this->modx->getOption('msrpc_default_pr_payroll_coins',null, 0),
                                                        'pr_cart_paid' => (int)$this->modx->getOption('msrpc_max_pr_cart_paid_by_coins',null, 0),
                                                        'statuses_for_inc' => $this->modx->getOption('msrpc_order_statuses_for_inc_coins',null, 0),
                                                        'statuses_for_dec' => $this->modx->getOption('msrpc_order_statuses_for_dec_coins',null, 0),
                                                        'ratio_of_coins' => (int)$this->modx->getOption('msrpc_ratio_of_coins',null, 1),
                                                        'welcome_coins' => (int)$this->modx->getOption('msrpc_welcome_coins_for_registration',null, 0),
                                                        'welcome_coins_if' => (int)$this->modx->getOption('msrpc_welcome_coins_if_promocode',null, 0)
                                                    );
                                                    $this->config = array_merge($this->config, $config);
                                            
                                                    $this->config['css_url'] = str_replace('[[+cssBasePath]]', MODX_ASSETS_URL.'components/msreferralprogramcoin/styles/', $this->config['css_url']);
                                                    $this->config['js_url'] = str_replace('[[+jsBasePath]]', MODX_ASSETS_URL.'components/msreferralprogramcoin/js/', $this->config['js_url']);
                                                    $this->config['connector_url'] = str_replace('[[+assetsBasePath]]', MODX_ASSETS_URL.'components/msreferralprogramcoin/', $this->config['connector_url']);
                                                    $this->config['name_coin'] = iconv_strlen($this->config['name_coin']) < 1 ? 'Coin' : $this->config['name_coin'];
                                                    $this->config['promo_prefix'] = mb_strtoupper(iconv_substr($this->config['name_coin'], 0, 1));
                                                    $this->config['promo_suffix'] = 'R';
                                                    $this->config['ratio_of_coins'] = !$this->config['ratio_of_coins'] ? 1 : $this->config['ratio_of_coins'];
                                                    $this->config['default_pr_payroll'] = !$this->config['default_pr_payroll'] ? 0 : $this->config['default_pr_payroll'];
                                                    $this->config['pr_cart_paid'] = !$this->config['pr_cart_paid'] ? 0 : $this->config['pr_cart_paid'];
                                                    $this->config['welcome_coins'] = !$this->config['welcome_coins'] ? 0 : $this->config['welcome_coins'];
                                                    $this->config['welcome_coins_if'] = !$this->config['welcome_coins_if'] ? 0 : $this->config['welcome_coins_if'];
                                            
                                                    $this->includeCssAndJs();
                                            
                                                    $this->modx->addPackage('msreferralprogramcoin', MODX_CORE_PATH.'components/msreferralprogramcoin/model/');
                                                }
                                            
                                                public function includeCssAndJs() {
                                                    if ($this->modx->context->key != 'mgr') {
                                                        $this->modx->regClientCSS($this->config['css_url']);
                                                        $this->modx->regClientScript($this->config['js_url']);
                                                    }
                                                }
                                            
                                                public function loadLexicons() {
                                                    $this->modx->lexicon->load('msreferralprogramcoin:default');
                                                    if ($this->modx->context->key == 'mgr') {
                                                        $this->modx->lexicon->load('msreferralprogramcoin:menu');
                                                    }
                                                }
                                            
                                                public function OnUserSave($uid) {
                                                    if (!$uid || !$this->config['welcome_coins']) return;
                                                    /** @var msrpcHandPayroll $handPayroll */
                                                    $handPayroll = $this->modx->newObject('msrpcHandPayroll');
                                                    $handPayroll->set('user_id', $uid);
                                                    $handPayroll->set('payroll', $this->config['welcome_coins']);
                                                    $handPayroll->set('createdby', $uid);
                                                    $handPayroll->set('createdon', time());
                                                    if (!$handPayroll->save()) {
                                                        $this->modx->log(modX::LOG_LEVEL_ERROR, '[msrpcMain] - Not save welcome coins for user ID '.$uid);
                                                    }
                                                }
                                            
                                                public function OnUserBeforeSave($promo) {
                                                    $referrer_promocode = iconv_substr(trim($promo), 1);
                                                    if (empty($referrer_promocode)) {
                                                        return 0;
                                                    }
                                                    $timestamp_1 = stristr($referrer_promocode, 'R');
                                                    $referrer_id = (int)trim(stristr($referrer_promocode, 'R', true));
                                                    $timestamp_2 = trim(iconv_substr($timestamp_1, 1));
                                                    if (!$timestamp_1 || !$referrer_id || !(int)$timestamp_2 || iconv_strlen($timestamp_2) !== 2) {
                                                        return 0;
                                                    }
                                                    $query = $this->modx->newQuery('modUser', array('id' => $referrer_id));
                                                    $query->select(array(
                                                        'modUser.createdon as createdon'
                                                    ));
                                                    $query->prepare();
                                                    $query->stmt->execute();
                                            
                                                    /** @var array[] $Users */
                                                    $users = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
                                            
                                                    if (!count($users) || $timestamp_2 !== substr($users[0]['createdon'],-2)) {
                                                        return 0;
                                                    }
                                            
                                                    return (int)$referrer_id;
                                                }
                                            
                                                public function msOnBeforeSaveOrder(msOrder $msOrder, $payCoins)
                                                {
                                                    $delivery_cost = $msOrder->get('delivery_cost');
                                                    $oid = 0;
                                                    if ($msOrder->id){
                                                        $oid = $msOrder->id;
                                                        $payCoins = $msOrder->msrpc_payroll_dec;
                                                    }
                                                    $products = $msOrder->getMany('Products');
                                                    $payroll = 0;
                                                    $total_cost = 0;
                                                    $pr_payroll = $this->config['default_pr_payroll'];
                                                    if ($this->modx->user->id) {
                                                        $query = $this->modx->newQuery('modUser', array('id' => $msOrder->user_id));
                                                        $query->select(array(
                                                            'modUser.msrpc_pr_payroll as pr_payroll'
                                                        ));
                                                        $query->prepare();
                                                        $query->stmt->execute();
                                                        /** @var array[] $modUsers */
                                                        $modUsers = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
                                                        if (count($modUsers) && $modUsers[0]['pr_payroll']) {
                                                            $pr_payroll = (int)$modUsers[0]['pr_payroll'];
                                                        }
                                                    }
                                                    /** @var msOrderProduct $product */
                                                    foreach ($products as $product) {
                                                        $total_cost += $product->get('price') * $product->get('count');
                                                        if (!$this->modx->getObject('modResource', $product->product_id)->msrpc_check) continue;
                                                        $payroll += (($product->get('price') * $product->get('count')) / 100) * $pr_payroll;
                                                    }
                                                    $payroll = (int)round($payroll * $this->config['ratio_of_coins'],0);
                                                    $msOrder->set('msrpc_payroll_inc', $payroll);
                                                    if ($this->modx->user->id && $payCoins) {
                                                        $balance = 0;
                                                        $query = $this->modx->newQuery('msrpcHandPayroll', array('user_id' => $msOrder->user_id));
                                                        $query->groupby('msrpcHandPayroll.user_id');
                                                        $query->select(array(
                                                            'SUM(msrpcHandPayroll.payroll) as payroll'
                                                        ));
                                                        $query->prepare();
                                                        $query->stmt->execute();
                                                        $rows = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
                                                        foreach ($rows as $row) {
                                                            $balance += (int)$row['payroll'];
                                                        }
                                                        $query = $this->modx->newQuery('msOrder', array(
                                                            'id:!=' => $oid,
                                                            'user_id' => $msOrder->user_id,
                                                            'status:IN'=> explode(',', $this->modx->getOption('msrpc_order_statuses_for_inc_coins',null, 0))
                                                        ));
                                                        $query->groupby('msOrder.user_id');
                                                        $query->select(array(
                                                            'SUM(msOrder.msrpc_payroll_inc) as payroll'
                                                        ));
                                                        $query->prepare();
                                                        $query->stmt->execute();
                                                        $rows = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
                                                        foreach ($rows as $row) {
                                                            $balance += (int)$row['payroll'];
                                                        }
                                                        $query = $this->modx->newQuery('msOrder', array(
                                                            'id:!=' => $oid,
                                                            'user_id' => $msOrder->user_id,
                                                            'status:IN'=> explode(',', $this->modx->getOption('msrpc_order_statuses_for_dec_coins',null, 0))
                                                        ));
                                                        $query->groupby('msOrder.user_id');
                                                        $query->select(array(
                                                            'SUM(msOrder.msrpc_payroll_dec) as payroll'
                                                        ));
                                                        $query->prepare();
                                                        $query->stmt->execute();
                                                        $rows = $query->stmt->fetchAll(PDO::FETCH_ASSOC);
                                                        foreach ($rows as $row) {
                                                            $balance -= (int)$row['payroll'];
                                                        }
                                                        if (!$balance) return;
                                                        $forPayCost = ($total_cost/100)*$this->config['pr_cart_paid'];
                                                        $forPayCoins = (int)round($forPayCost * $this->config['ratio_of_coins'], 0);
                                                        $forPayCostB = (int)round($balance / $this->config['ratio_of_coins'], 0);
                                                        $msOrder->set('msrpc_payroll_dec', min($balance, $forPayCoins));
                                                        $msOrder->set('cost', $total_cost-min($forPayCostB, $forPayCost)+$delivery_cost);
                                                        $msOrder->set('cart_cost', $total_cost-min($forPayCostB, $forPayCost));
                                                    }
                                                }
                                            
                                                public function OnMODXInit() {
                                                    $this->modx->map['modResource']['fields']['msrpc_check'] = 0;
                                                    $this->modx->map['modResource']['fieldMeta']['msrpc_check'] = array(
                                                        'dbtype' => 'tinyint',
                                                        'precision' => '1',
                                                        'attributes' => 'unsigned',
                                                        'phptype' => 'boolean',
                                                        'null' => false,
                                                        'default' => 0
                                                    );
                                                    $this->modx->loadClass('modUser');
                                                    $this->modx->map['modUser']['fields']['msrpc_referrer_id'] = 0;
                                                    $this->modx->map['modUser']['fieldMeta']['msrpc_referrer_id'] = array(
                                                        'dbtype' => 'int',
                                                        'precision' => 10,
                                                        'attributes' => 'unsigned',
                                                        'phptype' => 'integer',
                                                        'null' => false,
                                                        'default' => 0
                                                    );
                                                    $this->modx->map['modUser']['fields']['msrpc_pr_payroll'] = 0;
                                                    $this->modx->map['modUser']['fieldMeta']['msrpc_pr_payroll'] = array(
                                                        'dbtype' => 'tinyint',
                                                        'precision' => '2',
                                                        'attributes' => 'unsigned',
                                                        'phptype' => 'integer',
                                                        'null' => false,
                                                        'default' => 0
                                                    );
                                                    $this->modx->loadClass('msOrder');
                                                    $this->modx->map['msOrder']['fields']['msrpc_payroll_inc'] = 0;
                                                    $this->modx->map['msOrder']['fieldMeta']['msrpc_payroll_inc'] = array(
                                                        'dbtype' => 'int',
                                                        'precision' => 10,
                                                        'attributes' => 'unsigned',
                                                        'phptype' => 'integer',
                                                        'null' => false,
                                                        'default' => 0
                                                    );
                                                    $this->modx->map['msOrder']['fields']['msrpc_payroll_dec'] = 0;
                                                    $this->modx->map['msOrder']['fieldMeta']['msrpc_payroll_dec'] = array(
                                                        'dbtype' => 'int',
                                                        'precision' => 10,
                                                        'attributes' => 'unsigned',
                                                        'phptype' => 'integer',
                                                        'null' => false,
                                                        'default' => 0
                                                    );
                                                }
                                            }
                                            varanika
                                            11 июня 2021, 23:45
                                            0
                                            А есть зависимости какие-то от хостинга / версии php? Ставлю из репозитория, а что — то не до конца ставится, словарей будто части нет. И не только их. Хм… Дальше пока не лазила, пытаюсь понять без словарей в чем дело :)
                                            А задумка клевая! Спасибо))
                                              varanika
                                              12 июня 2021, 00:08
                                              0
                                              Убрала у плагина галку статичного файла и заводиться начало. Появился лексикон по крайней мере)
                                                varanika
                                                21 июня 2021, 13:16
                                                0
                                                Пришлось убрать все сниппеты и плагин из статичных файлов. Сниппеты заработали как информационные.

                                                В админке плагин поломал карточку ресурса. В файле assets/components/msreferralprogramcoin/js/mgr/msrpc.js убрала .items.items[1].items.items[2] — оно и ломало. Галочка бонусов появилась в общей вкладке.

                                                Сделала тестовую регистрацию пользователя. Реферал отобразился у того, чей код. Для теста ввела при заказе код другого пользователя — сначала реферал исчез у обоих, потом у обоих же и появился. Сам по себе :)

                                                Но вопрос по списанию. В корзине при установке галочки цена не меняется и бонусы не списываются. А точно ли плагин то срабатывает? Я что-то упускаю?
                                                  varanika
                                                  21 июня 2021, 16:19
                                                  0
                                                  С прыжками рефералов стало понятнее — проблема в том, что не нужно с одного компа три несчастных пользователя тестировать — система не то, что нужно запоминает))))

                                                  А вот списаний бонусов нет все равно. Ни в корзине не меняется цена, ни в админке не списываются. А добавляются исправно. Если найду решение — отпишусь. Пока не нашла в чем дело.
                                                    varanika
                                                    26 июня 2021, 18:20
                                                    0
                                                    В общем выяснилось (долго и муторно), что msReferralProgramCoin и msGallerySearch несовместимы.
                                                    На чистом сайте при установке второго — первый ломается. И происходит то, что и я, и другие пользователи описывали — пропадают лексиконы, не срабатывают сниппеты и чанки, не списываются бонусы в корзине. Как, почему — я не поняла, ибо и события не совпадают у плагинов, и логика разная…

                                                    И немного моего мелкого изменения. Позже, вероятно, дополню. При установке галочки в корзине ничего не меняется и мне, как юзеру — это не понятно. Ибо где логика — чекбокс тыкаем, а толку ноль. Соответственно делаю так в корзине:
                                                    <script>
                                                             var $pay = $('#msrpc-cart-payroll-dec').html();
                                                             var $payr = $pay / 10;
                                                     var $cost = Number($('#ms2_order_cost').html()) - $payr;
                                                    $htm = '- '+ $pay + ' баллов = ' +  $cost + ' руб.';
                                                     $('#msrpc-pay-coins').change(function() {
                                                         $(this).val($(this).prop('checked')?1:0);
                                                         if ($(this).val() == 1){
                                                              $('#referball').val('оплачено ' + $pay  + ' баллами - это '+ $payr + ' рублей');
                                                              $('#referball').attr('value', 'оплачено ' + $pay  + ' баллами - это '+ $payr + ' рублей');
                                                              $('#referrubl').val($payr);
                                                              $('#referrubl').attr('value', $payr);
                                                              
                                                             $('#bonussumm').html($htm);
                                                              
                                                         }
                                                         else {
                                                              $('#referrubl').val('');
                                                              $('#referrubl').attr('value', '');
                                                              $('#referball').val('');
                                                              $('#referball').attr('value', '');
                                                             $('#bonussumm').html('');
                                                         }
                                                        
                                                    });
                                                    if ($('#msrpc-pay-coins').prop('checked')){
                                                        $('#bonussumm').html($htm);
                                                    }	 
                                                    else { $('#bonussumm').html(''); }
                                                    	</script>
                                                    Установка value и одновременно с ним attr я делаю из занудства, ибо меня выбешивает, что в консоли хрома value остается чистым.

                                                    Ну и эти поля в вызове. Ах, да. В сниппете msrpcCart я дописала
                                                    $pdo = $modx->getService('pdoTools');
                                                    и вместе где
                                                    $modx->getChunk
                                                    заменить на 
                                                    $pdo->getChunk
                                                    Теперь у нас есть fenom и мы можем добавить такое в tpl:
                                                    <p class="msrpc-text">После фактической оплаты заказа с Вашего счета будет списано <span class="msrpc-cart-payroll-dec" id="msrpc-cart-payroll-dec">{$pay}</span> балла(ов), а общая сумма заказа уменьшится на {($pay / 10)  | replace :',':'.'} рублей</p>
                                                    и тут же пониже
                                                    <input type="text" value="{if $pay}оплачено {$pay} баллами - это {($pay / 10)  | replace :',':'.'} рублей{/if}" name="metro" id="referball" class="d-none">
                                                         <input type="text" value="{if $pay}{($pay / 10)  | replace :',':'.'}{/if}" name="referrubl" id="referrubl" class="d-none">
                                                    10 — это именно у меня отношение к бонусам такое. Может и 1 и 100 быть :)
                                                    Заметили name=«metro»? Вот это малоиспользуемое поле я забрала именно, чтобы менеджер видел в админке, что списание цены было баллами, так как не понятно толком. Конечно, можно создать свое поле в админку, но что-то по двум инструкциям они у меня не создались и я просто махнула рукой. Ну, главное лексиконы переименовать, чтобы понятнее было.
                                                    и в msOrder в чанке так:
                                                    <span id="ms2_order_cost">{$order.cost ?: 0}</span> {'ms2_frontend_currency' | lexicon}
                                                     <span id="bonussumm"></span>
                                                      varanika
                                                      26 июня 2021, 20:57
                                                      0
                                                      А вот ломание карточки товаров не зависит от компонентов. Но modhost на голой системе + minishop2 и pdotools — только товар сохраняется, как его тут же перекашивает и белые поля. Решается правкой js — писал выше
                                                      assets/components/msreferralprogramcoin/js/mgr/msrpc.js -->.items.items[1].items.items[2]
                                                        varanika
                                                        08 июля 2021, 02:00
                                                        0
                                                        В общем пофиксила я. Полную версию решения выложу на modx.ru в статьях в ближайшие дни.
                                                        А пока в кратце. Какого то х***на этот момент плагина отдавал пустоту.
                                                        $msrpcMain->msOnBeforeSaveOrder($msOrder, (isset($_COOKIE['msrpcPayCoins'])&&$_COOKIE['msrpcPayCoins']));
                                                        Решила просто заменой на
                                                        $msrpcMain->msOnBeforeSaveOrder($msOrder, (isset($_SESSION['msrpcPayCoins'])&&$_SESSION['msrpcPayCoins']));
                                                        И в сниппете
                                                        $_SESSION['msrpcPayCoins'] = $_COOKIE['msrpcPayCoins'];
                                                        Ну и красоты добавила


                                                        Но эти несколько недель мучений все таки мне лучше сформировать в полноценное руководство :)

                                                        p.s. если спустя месяцы кто-то спросит как в личке, ребята, голова дырявая — я не вспомню уже ;)
                                                          Антон
                                                          25 января 2023, 14:44
                                                          0
                                                          Хеллп,

                                                          А вот ломание карточки товаров не зависит от компонентов. Но modhost на голой системе + minishop2 и pdotools — только товар сохраняется, как его тут же перекашивает и белые поля. Решается правкой js — писал выше
                                                          assets/components/msreferralprogramcoin/js/mgr/msrpc.js -->.items.items[1].items.items[2]

                                                          — я вот не понял как в итоге должна выглядеть строчка js
                                                          — сейчас выглядит вот так:
                                                          var rightCol = this.items.items[0].items.items[2].items.items[0].items.items[1];
                                                          помогите плиз
                                              Олег Захаров
                                              23 сентября 2023, 02:40
                                              0
                                              Как обстоят дела с обновлением дополнения и обещанными разработками? Рабочее ли дополнение и можно ли применять на боевых сайтах? Чем оно лучше/хуже msBonus2?
                                                Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                                                60