Веб-модули

Одной из важнейших особенностей Melbis Shop 6 является масштабирования системы за счет интеграции в локальную программу отдельных веб-модулей. На сегодняшний день абсолютное большинство CMS, блогов и форумов не имеют клиентских приложений, а система их управления (админ раздел) построена полностью на HTML-интерфейсе и соответственно управляется только через браузер. Однако, многие серьезные продукты работающие с более или менее приличным объемом данных стремятся разработать дополнительный быстрый десктопный интерфейс

Когда такое приложение создает богатая компания, например Google AdWords Editor, то она тратит достаточно времени на поддержание его функционала аналогичного для веб-сайта. Именно поэтому, многие CMS не имеют сразу две версии админ-части: веб и десктоп. Большинство разработчиков выбрало веб-вариант, как основной. Что же это правильно, но это не лучший вариант из возможных. Исторически так сложилось, что мы начали разработку Melbis Shop с другого решения - десктопной программы, но потом, вскоре смогли сделать интеграцию в нее веб-модулей, получив тем самым именной лучший вариант CMS. Мы старались сделать Melbis Shop максимально функциональным, но из нашей практики мы видим, что рано или поздно у владельца возникает необходимость для реализации собственной уникальной задачи. В добавок к этому, есть ситуации, когда разработка отдельных элементов управления или генерация моментальных отчетов будет более удобна через веб-админку. Такие веб-интерфейсы легкодоступны на любом устройстве типа смартфона или планшета и не потребуют установки локальной программы. 

Именно по этим причинам в Melbis Shop 6 реализованы веб-модули и мы настоятельно рекомендуем Вам обратить внимание на них, так как считаем это одним из ключевых преимуществ системы. Разработав свой веб-модуль, Вы сможете решить сразу две задачи: расширить функционал, плюс добавить альтернативный способ управления магазином.

Итак, что же такое эти веб-модули, и где мы можем их использовать? Для начала отметим, что в системе присутствуют веб-модули двух типов: встроенные и внешние. Встроенные - это те, что встроенны прямо в интерфейс приложения Melbis Shop и взаимодействуют с ним, получая и передавая данные. Внешние же, это те модули, которые в первую очередь будут работать вне приложения Melbis Shop. То есть, достаточно знать адрес модуля, чтобы открыть его в любом браузере на любом устройстве. Прежде, чем мы приступим к рассказу о них, рекомендуется ознакомиться с разделами "Корневые скрипты" и "Модульные скрипты", потому как веб-модуль, есть ничто иное как особый, но все тот же модульный скрипт.


Тестовый веб-модуль

Откройте в программе разделы "Цены", "Покупатели" или "Заказы" и нажмите комбинацию клавиш Ctrl-W. В результате в каждом из этих окон появится специальное окно "Встроенный веб-модуль". Этот встроенный модуль не что иное, как браузер (на базе Chromium), который был интегрирован в каждое из данных окон. Ключевой момент этого подхода заключается в том, что когда Вы производите в окне какие-либо действия (перемещаетесь по товарам, заказам, покупателям), встроенному веб-модулю передаются определенные параметры. Например, в разделе "Цены" в веб-модуль передается id-товара, а также информация о том кто именно производит действие (о принципах авторизации пользователей подробнее ниже). Таким образом, можно разработать веб-модуль, который будет расширять любой функционал магазина. Этих модулей может быть много, их можно будет переключать, и к каждому из модулей можно будет задать права доступа для пользователей. Например, для раздела "Цены" можно разработать такие веб-модули как: "Просмотр информации о товаре", "Статистика продаж товара", "Складской учет товара" и т.п. Для разделов "Заказы" и/или "Покупатели" можно разработать модули-отчеты: "История покупок", "Отправка SMS, E-mail" и т.п.

Рассмотрим теперь, как создать свой встроенный веб-модуль. Прежде всего, следует зайти в раздел "Проектирование / Опции модулей", далее перейти по закладке "Встроенные веб-модули" и выбрать, для чего именно будет создаваться веб-модуль. На выбор предлагаются три группы: "Товары", "Покупатель", "Заказы", "Планировщик" и "Невидимые". После этого, можно добавить модуль и указать его параметры: название, адрес модуля и ключ - символьный код модуля. Например, по умолчанию в базовой поставке магазина присутствует тестовый модуль со следующими параметрами:

  • Название: Тестовый модуль
  • Адрес модуля: http://ms6.com/?mod=melbis_web_test
  • Ключ: TEST

Обратите внимание, что для модуля указана опция "Требуется идентификация пользователя". Этот пункт является дополнительным (необязательным) флагом, который обозначает, что при обращении к этому модулю необходимо добавить и проверить атрибуты пользователя (логин и пароль), чтобы провести его авторизацию. Например, для товарного модуля, кроме id-товара, будут дополнительно отправлены поля "логин" и "пароль", которые указаны в параметрах подключения. Обратите внимание, что пароль передается в закодированном виде (PHP-функция md5()). Например, для тестового модуля, будут переданы такие данные:

array (
  'get' => 
  array (
    'mod' => 'melbis_web_test',
  ),
  'post' => 
  array (
    'melbis' => '',
    'login' => 'admin',
    'pass_code' => '3240e96ca45f6e45b36f7b56a093ce0a',
    'topic_id' => '4',
    'store_id' => '1' 
  ),
)

Итак, Вы узнали, где определяются и настраиваются встраиваемые веб-модули. Следующим шагом мы расскажем о том, как устроен и работает базовый тестовый веб-модуль melbis_web_test.php. Но, прежде чем перейти к нему, следует упомянуть о корневом скрипте index.php. На самом деле, мы о нем уже подробно рассказали в разделе "Корневые скрипты". Поэтому, если Вы не знакомы с этим разделом прочтите его, чтобы понимать, каким образом будет вызываться модуль melbis_web_test.php.

Разбор модуля начнем с его входных параметров, которые определены стандартно для модуля вызываемого корневым скриптом index.php:

get: serial, post: serial

То есть, на входе мы получим массив со всеми данными переданными методами GET и POST. 

/** 
 * Function MELBIS_WEB_TEST
 **/
function MELBIS_WEB_TEST($mVars)
{ 
    global $gParser;
    
    return MELBIS_INC_AUTH(__FUNCTION__, $mVars);                    
}  

А вот так выглядит главная функция MELBIS_WEB_TEST, которая будет вызвана автоматически. Собственно, она достаточно проста и состоит из вызова функции MELBIS_INC_AUTH из модуля-библиотеки melbis_inc_auth.php. Это универсальный модуль, написанный нами специально для веб-модулей. В нем есть специальный функции, которые мы рекомендуем использовать Вам для упрощения разработки. Все что Вам требуется, это вызвать функцию MELBIS_INC_AUTH, передав ей два параметра: имя модуля и массив входных данных GET и POST. Это функция автоматически произведет идентификацию пользователя, определит тип модуля и права на его запуск. После этого, эта функция автоматически передаст управление обратно в модуль, путем вызова функции типа "имя_модуля_default", со следующими тремя параметрами:

  • $mUserId - определенный ID-пользователя (0, если не был определен)
  • $mResultAuth - код результата авторизации, может принимать следующие значения: 
    • accept - успешная авторизация и доступ пользователя к модулю
    • denied - успешная авторизация, но доступ пользователя к модулю закрыт
    • wrong - авторизация пользователя прошла с ошибкой 
    • start - начало процесса авторизации (попытки авторизации не было)
  • $mVars - массив входных данных GET и POST с которыми вызывался модуль изначально.

/** 
 * Function MELBIS_WEB_TEST_default
 **/
function MELBIS_WEB_TEST_default($mUserId, $mResultAuth, $mVars)
{ 
    global $gParser;
                       
    // Create 
    $tpl = $gParser->TplCreate();   
                                                           
    // Auth                
    if ( $mResultAuth == 'accept' )
    {   
        // Prepare rights          
        MELBIS_INC_AUTH_web_key_prepare($mUserId);
        
        // Show demo post vars
        $gParser->TplAssign($tpl, 'VARS', var_export($mVars, true));                
                                                                    
        // Order change back demo
        $order = ( isset($mVars['post']['order']) ) ? $mVars['post']['order'] : '{}';        
        $gParser->TplAssign($tpl, 'ORDER', $order);
        
        // Scripts
        $gParser->TplParse($tpl, 'SCRIPTS', 'scripts');                                                     
                   
        // Main
        $gParser->TplParse($tpl, 'MAIN', 'main');        
    }
    else
    {       
        // Auth
        $gParser->TplParse($tpl, 'MAIN', 'auth');
    }    
            
    return $gParser->TplFree($tpl, 'MAIN');                         
} 

Вот так выглядит default-функция для рассматриваемого нами модуля. Если идентификация прошла успешно, то мы подготавливаем необходимые ключи и шаблоны и формируем ответ на основе шаблона main.htm. В противном случае, если авторизация неуспешна, то мы выводим шаблон auth.htm. Он представляет собой вызов отдельного модуля авторизация melbis_web_auth.php. В общем, это некий универсальный подход, на тот случай, если модуль будет вызываться и как встроенный в Melbis Shop, и как внешний через любой браузер (тогда требуется запросить логин и пароль для идентификации пользователя). Если же Вы знаете, что это будет веб-модуль только для внутреннего использования, тогда вместо шаблона auth.htm, можно добавить другой, в котором просто написать, что доступ закрыт.


Обратная связь веб-модуля

Для веб-модуля встроенного в окно редактирования заказа, Вам скорее всего, понадобиться возможность обратной связи. Например, если захотите вести просчет каких-либо данных в веб-модуле, а потом возвращать их в заказ. Если речь конечно об одном поле, то его можно и просто скопировать. Но не редки те случаи, когда обновляется сразу целые массивы данных заказа. Самый популярный пример, это интеграция магазина с АТС, когда скрипт модуля выполняет запрос к АТС и получив ответ, должен автоматически определить и подставить покупателя в заказ. 

Для подобных ситуаций Вам потребуется, используя JavaScript, подготовить ответ и отправить его в консоль, вместе со специальным кодовым словом. Вернемся к нашему тестовому модулю melbis_web_test.php и рассмотрим весь путь работы с данными. Итак, поскольку этот модуль встроенный, то внутри массива $mVars['post']['order'], мы получим представление заказа в JSON-формате, что-то в этом духе:

{
   "version":[
      {
         "id":"1",
         "order_id":"44",
         "user_id":null,
         "client_id":"515",
         "date_time":"2019-06-23 20:02:43",
         "total_sum":"10"
      }
   ],
   "client_field":[
      {
         "id":"1",
         "version_id":"1",
         "field_id":"1",
         "field_skey":"NAME",
         "field_name":"Имя (ФИО)",
         "field_tindex":"0",
         "field_tlevel":"0",
         "field_absindex":"0",
         "field_folder":"0",
         "field_kind_key":"kRequired",
         "field_spec_key":"kDefault",
         "value_id":null,
         "value_skey":"",
         "value_code":"",
         "value_kind_key":"",
         "value_txt":"Tester"
      },
      {
         "id":"2",
         "version_id":"1",
         "field_id":"2",
         "field_skey":"COMPANY",
         "field_name":"Компания",
         "field_tindex":"0",
         "field_tlevel":"0",
         "field_absindex":"1",
         "field_folder":"0",
         "field_kind_key":"kDefault",
         "field_spec_key":"kDefault",
         "value_id":null,
         "value_skey":"",
         "value_code":"",
         "value_kind_key":"",
         "value_txt":"test"
      },
      {
         "id":"3",
         "version_id":"1",
         "field_id":"3",
         "field_skey":"EMAIL",
         "field_name":"Электронная почта",
         "field_tindex":"0",
         "field_tlevel":"0",
         "field_absindex":"2",
         "field_folder":"0",
         "field_kind_key":"kRequired",
         "field_spec_key":"kDefault",
         "value_id":null,
         "value_skey":"",
         "value_code":"",
         "value_kind_key":"",
         "value_txt":"test@mail.ru"
      },
      {
         "id":"4",
         "version_id":"1",
         "field_id":"4",
         "field_skey":"PHONE",
         "field_name":"Телефон",
         "field_tindex":"0",
         "field_tlevel":"0",
         "field_absindex":"3",
         "field_folder":"0",
         "field_kind_key":"kDefault",
         "field_spec_key":"kDefault",
         "value_id":null,
         "value_skey":"",
         "value_code":"",
         "value_kind_key":"",
         "value_txt":"+380(50)111-11-11"
      }
   ],
   "store":[
      {
         "id":"1",
         "version_id":"1",
         "store_id":"24",
         "store_provider_id":"2",
         "store_brand_id":"4",
         "store_pprice":"0",
         "store_rprice":"0",
         "store_price":"10",
         "store_price2":"0",
         "store_price3":"0",
         "store_how":"1",
         "store_code_shop":"AMATEUR_START",
         "store_code_prov":"",
         "store_code_made":"",
         "store_meas":"",
         "store_name":"Стартовый платеж",
         "store_kind_key":"kLicenseDomain",
         "store_status_key":"kExist",
         "store_state_key":"kDefault",
         "store_min_order":"0",
         "store_step_order":"0",
         "recalc":"0",
         "out_price":"10",
         "amount":"1",
         "notice":"myshop.com",
         "auto_notice":"Calculated",
         "pos":"1"
      }
   ],
   "store_option":[

   ],
   "option":[
      {
         "id":"1",
         "version_id":"1",
         "option_id":"3",
         "option_skey":"CREATOR",
         "option_name":"Создатель",
         "option_kind_key":"kDefault",
         "option_pos":"1",
         "value_id":"9",
         "value_skey":"USER",
         "value_name":"Пользователь",
         "value_kind_key":"kDefault",
         "value_modify_sum":"0",
         "value_oper_num":"0",
         "value_source_num":"0",
         "notice":""
      },
      {
         "id":"2",
         "version_id":"1",
         "option_id":"1",
         "option_skey":"STATUS",
         "option_name":"Статус",
         "option_kind_key":"kDefault",
         "option_pos":"2",
         "value_id":"3",
         "value_skey":"ABORT",
         "value_name":"Аннулирован",
         "value_kind_key":"kDefault",
         "value_modify_sum":"0",
         "value_oper_num":"0",
         "value_source_num":"0",
         "notice":""
      },
      {
         "id":"3",
         "version_id":"1",
         "option_id":"2",
         "option_skey":"PAYMENT",
         "option_name":"Оплата",
         "option_kind_key":"kDefault",
         "option_pos":"3",
         "value_id":"5",
         "value_skey":"CARD",
         "value_name":"LiqPay",
         "value_kind_key":"kDefault",
         "value_modify_sum":"0",
         "value_oper_num":"0",
         "value_source_num":"0",
         "notice":""
      }
   ]
}

Это и есть таблицы заказа представленные в виде JSON-объекта, который мы передадим дальше в шаблон scripts.htm под ключем {ORDER}. Вот код в скрипте:

        // Order change back demo
        $order = ( isset($mVars['post']['order']) ) ? $mVars['post']['order'] : '{}';        
        $gParser->TplAssign($tpl, 'ORDER', $order);

А вот код в scripts.htm, где мы определяем переменную melbis_order

var melbis_order = {ORDER};

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

// Init change back
function melbis_init_back()
{
    for ( var table in melbis_order )      
    {
        var data = melbis_order[table];
        var columns = [];
        for (var c in data[0])
        {
            columns.push({field: c, title: c});  
        }         
        $('.melbis_table_order[data-table="' + table + '"]').bootstrapTable({
            columns: columns,
            data: data 
        });
    }
}

В результате чего формируются Bootstrap-таблицы, которые можно редактировать по событию нажатия на любую ячейку. Для этого добавлена следующая функция:

// Change field value 
$('.melbis_table_order').on('click-cell.bs.table', function (event, field, value, row)  
{
    var table = event.target.dataset.table;
    bootbox.prompt({ 
        title: 'Edit value of "' + field +'"',
        value: value, 
        callback: function (result) 
        { 
            var update = {};    
            update[table] = [];
            update[table].push({ id: row.id, [field]: result });               
            console.log('MELBIS_ORDER_UPDATE' + JSON.stringify(update));                    
        }
    });    
});

Как Вы видите, здесь мы используем js-компонент bootbox.js, который создает prompt-запрос на редактирование ячейки. И при получении ответа мы формируем JSON-массив update, который просто выводится в консоль браузера командой console.log, добавив в самое начало кодовое слово MELBIS_ORDER_UPDATE:

            var update = {};    
            update[table] = [];
            update[table].push({id: row.id, [field]: result });               
            console.log('MELBIS_ORDER_UPDATE' + JSON.stringify(update));                    

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

На этом рассмотрение веб-модулей можно завершить. В заключении обратите внимание на такую идею. Вы можете использовать в качестве внешних веб-модулей и любые другие сайты. Ваши сотрудники получают готовый набор часто используемых сайтов прямо в клиентской среде Melbis Shop 6. Например, это могут быть сайты почтовой службы, транспортной компании, форума магазина, группы магазина в социальных сетях и т.п.