[modRetailCRM - 2.2.1]

Давненько я ничего не публиковал. Здравствуйте.

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



Список изменений продукта



2.1.0
==============
— Отключена передача способа доставки и оплаты и за ошибки на стороне RetailCRM
— Исправлена передача общей стоимости нескольки разных тоаров
— Добавлена передача стоимости доставки
— Добавлена передача веса товара
— Добавлено разбиение Строки ФИО на отдельные поля
— Добавлена проверка на существование пользователя на стороне RetailCRM

2.2.0
==============
— В объект msDelivery, добавлено дополнительное поле retailcrm_delivery_code, позволяющее указать символьный код доставки из настроек retailCRM, что дает возможность передавать способ доставки при заказе.
— В объект msPayment, добавлено дополнительное поле retailcrm_payment_code, позволяющее указать символьный код способа оплаты из настроек retailCRM, что дает возможность передавать способ оплаты при заказе.













2.2.1 — (11.06.2018)
==============
— В выгрузку заказов добавлен передача способа доставки и способа оплаты

Статья была бы не полной, если я не отвечу на еще один повторяющийся вопрос

Как передать в minishop2 изменения на стороне RetailCRM



Я конечно понимаю, что изменений в магазине может быть огромное количество. Это и работа с товаром, и с клиентами и с заказами. Моя задача — объяснить общее направление мысли и показать пример.

Пример возьмем такой.
  1. Заказ, сделанный в интернет-магазине, плагин передал в RetailCRM
  2. Менеджер, обработав заказ — изменил ему статус в RetailCRM
  3. Обновленный статус должен автоматически выгрузиться в интернет-магазин, и обновить статус заказа на соответствующий
Конечно же в дело вступают всем известные webhooks, которые отлеживают изменения внутри CRM, по заранее заданному сценарию и передают информацию на коннектор сайта. В общем то типовая ситуация для любой современной CRM, но в RetailCRM решил быть оригинальными и спрятали эту возможность достаточно глубоко и неочевидно.

Итак что мы делаем для решения подобных задач.

1. В личном кабинете RetailCRM ищем пункт Коммуникации-Триггеры
2. Создаем новый триггер со следующими параметрами:
  • Событие, которое мы будем отлавливать Изменение заказа
  • Действие, которое будет выполняться при выполнение указанных условий Выполнить HTTP-запрос
  • HTTP метод POST запрос (на самом деле можно и GET — это уже вкусовщина)
  • Адрес: Коннектор на вашем сайте, на котором будет отправляться запрос. Естественно там должна быть программа, принимающая POST запрос и выполняющая необходимые действия. В нашем случае вызывая заказ с принятым id и устанавливая для него переданный статус
  • Условие применения триггера. Здесь нужно написать условие при наступлении которого будет выполняться HTTP запрос к нашему коннектору. Например можно перечислить статусы заказа RetailCRM при указании которых будет выполняться триггер. Допустим Вам нужно передать на сайт окончательный статус Оплачен или Отменен, и не передавать промежуточные статусы Подтвержден, Обработан, Выставлен счет и т.п.
    Для написания подобных условий нужно использовать шаблонизатор (по моему Twig) и предусмотренные для этого методы
    Я подготовил следующее условие
    changeSet.hasChangedField("status") and changeSet.getNewValue("status").getGroupCode() in ["complete", "cancel"]
    Условие расшифровывается так. Если при среди измененных полей есть поле Status и новое значение поля Status находится в группе статусов Выполнен или Отменен — то выполняем действие.

    Подробнее о правилах подготовки и написании триггеров можно узнать в документации
    Правила подготовки триггеров и триггеры
3. Последний параметр настройки триггера — передаваемые на наш коннектор параметры. В случае с моим примером это:
  • id заказа — order = {{ order.getExternalId() }}
  • код статуса status = {{ order.getStatus() }}





4. На нашем сайте коннектор должен принять передаваемую ему информацию, вызвать нужный заказ и поменять ему статус. Код программы получится примерно такой.

<?php
//Подключаем к произвольному файлу MODX API
define('MODX_API_MODE', true);
require_once($_SERVER['DOCUMENT_ROOT'].'/index.php');

$modx = new modX();
$modx->initialize('web');
$modx->getService('error','error.modError', '', '');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);


if($_POST['status'] && $_POST['order']){
	//Принимаем параметры
	$status = trim( filter_input(INPUT_POST,'status',  FILTER_SANITIZE_STRING) );
	$order = trim( filter_input(INPUT_POST,'order',  FILTER_SANITIZE_STRING) );
	
	//Указываем какой статус заказа минишопа соответствует каждому возможному варианту RetailCRM
	$new_status = 0;
	switch($status){
		case 'sh-send':
			$new_status = 3;
			break;
		case 'cancel-other':
			$new_status = 4;
			break;
	}
	
	//Вызываем объект заказа и меняем ему статус
	$order = $modx->getObject('msOrder', array('num' => $order));
	if($order && $new_status > 0){
		$order->set('status', $new_status);
		$order->save();
	}
}
Николай Савин
12 июня 2018, 09:25
modx.pro
1
1 739
+5
Поблагодарить автора Отправить деньги

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

Dmitry
10 июля 2018, 16:03
0
Заказы не передаются, добавил в плагин строчку печати в лог, получаю такую ошибку:
[2018-07-10 15:52:03] (ERROR @ /home/s14252/www/meat/cache/includes/elements/modplugin/19.include.cache.php : 93) [modRetailCRM]  Order Response RetailCrm\Response\ApiResponse Object
(
    [statusCode:protected] => 400
    [response:protected] => Array
        (
            [success] => 
            [errorMsg] => Order is not loaded
            [errors] => Array
                (
                    [customer.externalId] => Customer with externalId=2 not found. Order externalId=16.
                )

        )

)
Буду благодарен за совет, как исправить.
    Николай Савин
    10 июля 2018, 16:12
    +1
    Вы обновляли компонент? По идее в свежей версии эта проблема устранена.
      Dmitry
      10 июля 2018, 16:37
      0
      Хм, установил компонент из репозитория только сегодня. Установилась версия 2.0.0. Нужно обновить как-то вручную?
        Николай Савин
        10 июля 2018, 16:39
        +1
        Текущая версия 2.2.1 Нужно устанавливать из репозитория modstore.pro. Все свежие версии и обновления там. За наводку спасибо дойдут руки обновлю в официальном
          Dmitry
          10 июля 2018, 16:43
          0
          Спасибо за ответ, обновился из репозитория modstore.pro, всё заработало.
Pavel Zarubin
16 сентября 2018, 02:17
0
После установки и ввода ключа упала админка.
php 7.2

P.s. Не знаю зачем такой компонент нужен в extension_packages. Он не влияет на работу modx'a, так зачем его инициализировать без надобности?
    Pavel Zarubin
    16 сентября 2018, 02:25
    +1
    Проверил ошибку дважды, если установить компонент и указать сначала api ключ, то админка сразу падает не давая заполнить другие настройки. Вычистил класс, заполнил настройки и все завелось.А еще не знаю насколько корректно оставлять в комментариях доступы к демо-магазину
      Николай Савин
      16 сентября 2018, 07:04
      0
      Да этот аккаунт все равно не существует.
      За багрепорт спасибо. Буду править.
        Николай Савин
        16 сентября 2018, 09:59
        +1
        Почистил, устранил, пофиксил, зарелизил. Спасибо еще раз.
    Эдвард Ерохин
    17 октября 2018, 12:45
    0
    Подскажите, правильно ля и понял. Для того чтоб заказы падали в CRM, нужно туда добавить весь каталог товаров? Сейчас в CRM приходит только пользователь а заказ не падает
      Николай Савин
      17 октября 2018, 12:48
      0
      Нет не правильно.
      Если товар в CRM не создан, то заказ все равно создается на основе присылаемых данных (название, цена, опции)
      Если товары в базе CRM уже есть, то достаточно послать идентификатор товара, а все данные подтянутся из базы
        Эдвард Ерохин
        17 октября 2018, 12:51
        0
        а как отследить ошибку? заказ в CRM не падает, только новый пользователь. Лог ошибок чистый
          Эдвард Ерохин
          17 октября 2018, 13:09
          0
          В общем, если ставить по умолчанию доставку новая почта то не работает из коробки. Убрал новую почту все гуд) Спасибо за компонент, буду настраивать!
            Николай Савин
            17 октября 2018, 13:11
            0
            В плагине, в самом конце есть закомментированная строчка логгирования.
            Достаточно ее раскомментировать и будет запись в журнал, с достаточно подробным описанием ошибки.
        Андрей
        24 октября 2018, 21:56
        0
        Все настроил по инструкции — ничего в RetailCRMне передается. Вообще. Как включить логирование — в плагине не нашел строки такой.
          Александр
          24 октября 2018, 22:55
          0
          Значит неправильно настроили. Компонент работает как надо, проверено
            Андрей
            24 октября 2018, 22:59
            0
            Вопрос был таков:
            Как включить логирование — в плагине не нашел строки такой.
            То что там все работает я не сомневаюсь, а хочу выяснить проблему. Что касается правильно или неправильной настройки, то я думаю там в 3 строках не трудно разобраться и вряд ли сделать ошибку…
            Николай Савин
            26 октября 2018, 07:55
            0
            Вот после этой строки в плагине
            $response = $modRetailCrm->request->ordersCreate($orderData, $site);
            можно включить логгирование
            $modx->log(1, print_r($response, 1));
            Мне очень нравится как API RetailCRM возвращает ошибки. Все предельно понятно
              Андрей
              26 октября 2018, 08:40
              0
              Спасибо)
              Вот что получаю:
              RetailCrm\Response\ApiResponse Object
              (
              [statusCode:protected] => 400
              [response:protected] => Array
              (
              [success] =>
              [errorMsg] => Order is not loaded
              [errors] => Array
              (
              [items[0].properties[modifications][value]] => Product property value in the order content is not specified
              )

              )

              )
                Николай Савин
                26 октября 2018, 08:44
                0
                Насколько я понял, у тебя что то не то с модификациями. Может просто пустые.
                Попробуй, распечатай перед отправкой массив с данными, может что-то будет более ясно.

                $modx->log(1, print_r($orderData, 1));
                  Андрей
                  26 октября 2018, 09:03
                  0
                  Array
                  (
                      [customer] => Array
                          (
                              [externalId] => 2
                          )
                  
                      [externalId] => 1810/15
                      [firstName] => Иван
                      [phone] => 
                      [email] => email@email.ru
                      [lastName] => Иванов
                      [patronymic] => Иванович
                      [items] => Array
                          (
                              [0] => Array
                                  (
                                      [initialPrice] => 3000.00
                                      [purchasePrice] => 3000.00
                                      [productName] => Плитка индукционная настольная Сага-2 (ТМ Великие реки)
                                      [quantity] => 1
                                      [offer] => Array
                                          (
                                              [externalId] => 100
                                          )
                  
                                      [properties] => Array
                                          (
                                              [0] => Array
                                                  (
                                                      [name] => modifications
                                                      [value] => Array
                                                          (
                                                          )
                  
                                                  )
                  
                                              [1] => Array
                                                  (
                                                      [name] => modification
                                                      [value] => 0
                                                  )
                  
                                          )
                  
                                  )
                  
                          )
                  
                      [weight] => 1.8
                      [delivery] => Array
                          (
                              [address] => Array
                                  (
                                      [index] => 170001
                                      [region] => Тверская обл.
                                      [city] => Тверь
                                      [text] => Индекс:170001 
                                  Регион:Тверская обл. 
                                  Город:Тверь 
                                  
                                  )
                  
                              [cost] => 0
                              [code] => sdek-sklad-doors
                          )
                  
                      [customerComment] => 
                      [payments] => Array
                          (
                              [0] => Array
                                  (
                                      [type] => cash
                                  )
                  
                          )
                  
                  )
                  Можно ли сделать какое-то условие, если модификация пустая не учитывать ее?
                    Николай Савин
                    26 октября 2018, 10:11
                    0
                    Ну как я и сказал. Если у свойства товара пустое значение — RetailCRM вернет ошибку.
                    Можно ли сделать какое-то условие, если модификация пустая не учитывать ее?
                    Ответить
                    Можно — разрешаю.
                      Андрей
                      26 октября 2018, 10:18
                      0
                      Самое интересное, что у товара вообще нет опций, и нет модификаций. По идее если их нет, то они не должны учитываться никак…
                      Можно — разрешаю.
                      У вас хорошее чувство юмора) Помогите справиться с этой задачей)) Может быть еще кому-то пригодиться.
                        Николай Савин
                        26 октября 2018, 10:22
                        0
                        С какой задачей? Перебрать массив опций и проверить их на пустоту? Это основа PHP: циклы и условия. Если ты не знаешь как делать подобные вещи — то лучше обратись в раздел работа.
                          Андрей
                          26 октября 2018, 10:25
                          0
                          Это надо проверять в плагине вашего компонента или где-то в другом месте?
                          Почему компонент не работает из коробки с товарами без опций. Там нет никаких модификаций и опций, а он не работает…
                            Николай Савин
                            26 октября 2018, 10:30
                            0
                            на 130 с лишним скачиваний — он почему то у тебя одного не работает. Тебе не кажется, что проблема не в компоненте, а где то еще?
                              Андрей
                              26 октября 2018, 10:31
                              0
                              Судя по длинным веткам обсуждений, то у меня то у кого-то еще вылезают разные проблемы в нем. И почему-то везде они решаются а в данном случае помощи судя по всему ждать не приходится.
                              Николай Савин
                              26 октября 2018, 10:34
                              0
                              Потому что ты просишь чтобы за тебя все сделали, разжевали и готовое на блюдечке вынесли.
                              Андрей
                              26 октября 2018, 10:39
                              0
                              Точно… я же забыл что у нас здесь сообщество великих гуру… И свысока спускаться не по статусу большинству…
                              Николай Савин
                              26 октября 2018, 11:17
                              0
                              Верно заметил. Сообщество, а не детский сад. Здесь нянечек нет. Не нравится — не используй. Сделай сам.
                              Андрей
                              26 октября 2018, 11:20
                              0
                              Да действительно иногда проще самому сделать, чем тратить время на пустую болтовню с горе разработчиками
          Nikita
          15 декабря 2018, 16:31
          0
          Николай, спасибо большое за помощь в адаптации и доработки компонента )))
          Сделал все как просил ) Респект.
            Ильяс
            25 декабря 2018, 08:49
            0
            Благодарю Николая за отличную техническую поддержку. Были сложности в интеграции, но при обращении все решилось оперативно. По мимо интеграции, была обновлена версия компонента и даны рекомендации по сайту в целом. Спасибо!
              Антон
              25 декабря 2018, 23:48
              0
              A это у меня одного так, что на сайте версия 2.2.3-пл и она не обновляется, даже не видит обновления, говорит, что у меня самая последняя версия, хотя на модсторе уже 2.4… Или там какая-то замута с тем, что компонент стал платный и теперь пока не купишь, никак не обновиться?
                Николай Савин
                26 декабря 2018, 05:02
                0
                Именно так. Обновления только после покупки!
                  Антон
                  26 декабря 2018, 09:27
                  0
                  А будет какой-нибудь пост с описанием того, что там в новой платной версии появилось?
                    Николай Савин
                    26 декабря 2018, 09:29
                    0
                    Это все есть на странице программы в разделе История изменений
                    История modRetailCRM 2.4.1 — (14.12.2018)

                    Добавлена смена статуса платежа в CRM
                    2.4.0 — (14.12.2018)

                    Настроен учет промо-кодов и скидкок компонента msPromoCode
                    Исправлены мелкие ошибки плагина.
                    Добавлены подписи популярных свойств size,color для передачи нормально читаемых опций
                    Добавлено обнаружение msOptionsPrice2 и заготовка под передачу опций
                    ==============

                    2.3.3 — (13.12.2018)

                    Новая системная настройка — Перечень статусов заказов, которые будет слушать плагин
                    Мелкие правки в плагине

                    2.3.2 — (13.12.2018)

                    В объект msOrderStatus, добавлено дополнительное поле retailcrm_status_code, позволяющее указать символьный код статуса заказа из настроек retailCRM.
                    Настроено отслеживание изменения статуса заказа.
                    В ближайшее время будут еще изменения. Как минимум синхронизация статусов заказов в обе стороны. Я над этим работаю.
                Антон
                26 декабря 2018, 18:05
                0
                Возможно это дурацкий вопрос, но я нигде в справочнике апи не могу найти метод, чтоб с сайта товары в црмку загрузить. В версии компонента 2.2.3 используется 4 или 5я версия протокола апи? Всё, что я нашел, это какое-то описание полей класса товара тут. Но метод для создания товара через апи не могу найти. Или может в компоненте уже есть готовое решение для экспорта в црм справочника товаров?
                  Николай Савин
                  26 декабря 2018, 19:07
                  0
                   Хороший вопрос. Товары конечно выгружаются из сайта в CRM, причем поддерживается автоматическая и ручная синхронизация. Но работает это не через API — все проще.
                  Как и для ЯндексМаркета формируется xml страница с YML каталогом. RetailCRM его прекрасно понимает. Важно понимать что в YML нет торговых предложений. То есть кроссовки не важно какого цвета и размера это один и тот же товар с одной ценой. А цвет и размер передается уже просто как опция заказа.

                  RetailCRM в этом плане пошли дальше и сделали поддержку торговых предложений. Тут уже можно разбить один товар на несколько. К примеру по цвету или размеру. Такой формат называтся ICML — это расширение YML формата. Как правильно сформировать ICML файл можно подробно прочитать здесь

                  Я даже могу дать пошаговую инструкцию по выгрузке товаров (YML формат, попроще)
                  1. Создаем отдельную XML страницу, называем ее icml
                  2. Пишет примерно такое содержание из двух сниппетов
                  <?xml version="1.0" encoding="UTF-8"?>
                  <yml_catalog date="{"" | date : "Y-m-d H:i:s"}">
                      <shop>
                          <name>{'site_name' | option}</name>
                          <company>{'site_name' | option}</company>
                          <url>{'site_url' | option}</url>
                          <currencies>
                              <currency id="RUR" rate="1"/>
                          </currencies>
                          <categories>
                              {'!pdoResources' | snippet : [
                              'parents' => 0,
                              'level' => 10,
                              'limit' => 0,
                              'showHidden' => 0,
                              'where' => ['class_key' => 'msCategory'],
                              'sortby' => 2,
                              'tpl' => '@INLINE <category id="{$id}" parentId="{$parent}">{$pagetitle}</category>'
                              ]}
                          </categories>
                          <offers>
                              {'!msProducts' | snippet : [
                              'parents' => 2,
                              'level' => 10,
                              'limit' => 0,
                              'tpl' => '@INLINE
                                  <offer id="{$id}" productId="{$id}" available="true">
                                      <url>{$id | url : ["scheme" => "full"]}</url>
                                      <price>{$price | replace : " " : ""}</price>
                                      <categoryId>{$parent}</categoryId>
                          	        <purchasePrice>{"msProductOptions" | snippet : ["product" => $id, "onlyOptions" => "opt_prices"]}.00</purchasePrice>
                          	        {if $old_price > 0}<oldprice>{$old_price  | replace : " " : ""}</oldprice>{/if}
                                      <currencyId>RUR</currencyId>
                                      <vendor>{$vendor.name}</vendor>
                                      <vendorCode>{$article | replace : "&" : "AND"}</vendorCode>
                                      <manufacturer_warranty>true</manufacturer_warranty>
                                      <picture>{"site_url" | config | replace : "ru/" : "ru"}{$image}</picture>
                                      <name>{$pagetitle | replace : "&" : "AND"}</name>
                                  </offer>
                              '
                              ]}
                          </offers>
                      </shop>
                  </yml_catalog>
                  3. Идем в RetailCRM — администрирование — магазины — каталог.
                  Выбираем там «загружать из ICML» — указываем ссылку на нашу XML страницу — ставим отметку загрузить сейчас и жмем сохранить.
                  Все после этого по идее каталог товаров будет загружен автоматически — причем CRM сама будет переодически (раз в день по моему) обновлять товары в базе.

                  Ну и после этого важно понимать, что передавать товары в плагине заказ не нужно — нужно передать лишь идентификаторы товара и если надо опции. Остальные данные (название, цена, картинка) уже подгрузятся сами из базы CRM.

                  Надеюсь все понятно объяснил. Могу в рамках техподдержки помочь все это настроить (после покупки конечно)
                    Антон
                    27 декабря 2018, 02:29
                    0
                    Ух-ты, удобно, спасибо. Сам бы никогда не узнал про такое. То есть плагин подправить надо, чтоб из данных о товарах в заказе только айдишник отправлялся, так?
                      Антон
                      27 декабря 2018, 02:42
                      0
                      Единственная беда — у меня сайт падает с 500 ошибкой при генерации этого юмл. 11к товаров. Если ставить лимит на товары до 10к, то работает, 10к+ — 500 ошибка. Причём в логах пусто. Может это какое-то ограничение мсПродуктс?
                        Николай Савин
                        27 декабря 2018, 07:19
                        0
                        У тебя сервер же выдает ошибку. Смотри логи сервера. Скорее всего превышен лимит выделенных ресурсов. В таком случае тебе нужно не на лету генерировать страницу, а через консоль отдельный XML файл генерировать.
                        Антон
                        27 декабря 2018, 02:49
                        0
                        А если црмке скормить выгрузку для яндекс-маркета, сработает, или там поля не так называются?
                          Антон
                          27 декабря 2018, 02:51
                          0
                          А, да, там поля другие.
                            Николай Савин
                            27 декабря 2018, 07:16
                            0
                            Ниче не другие поля. я же выше написал, что RetailCRM понимает YML и его ICML это расширение YML. На всякий случай YML — это Yandex Market Language — то есть формат придуманный маркетом.
                        Varelkka
                        16 января 2019, 15:10
                        0
                        Спасибо за оперативную компетентную помощь в доработке компонента под индивидуальные задачи!
                          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                          48