[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)
==============
— В выгрузку заказов добавлен передача способа доставки и способа оплаты
Статья была бы не полной, если я не отвечу на еще один повторяющийся вопрос
Я конечно понимаю, что изменений в магазине может быть огромное количество. Это и работа с товаром, и с клиентами и с заказами. Моя задача — объяснить общее направление мысли и показать пример.
Пример возьмем такой.
Итак что мы делаем для решения подобных задач.
1. В личном кабинете RetailCRM ищем пункт Коммуникации-Триггеры
2. Создаем новый триггер со следующими параметрами:
4. На нашем сайте коннектор должен принять передаваемую ему информацию, вызвать нужный заказ и поменять ему статус. Код программы получится примерно такой.
Для начала хочу рассказать об изменениях 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
Я конечно понимаю, что изменений в магазине может быть огромное количество. Это и работа с товаром, и с клиентами и с заказами. Моя задача — объяснить общее направление мысли и показать пример.
Пример возьмем такой.
- Заказ, сделанный в интернет-магазине, плагин передал в RetailCRM
- Менеджер, обработав заказ — изменил ему статус в RetailCRM
- Обновленный статус должен автоматически выгрузиться в интернет-магазин, и обновить статус заказа на соответствующий
Итак что мы делаем для решения подобных задач.
1. В личном кабинете RetailCRM ищем пункт Коммуникации-Триггеры
2. Создаем новый триггер со следующими параметрами:
- Событие, которое мы будем отлавливать Изменение заказа
- Действие, которое будет выполняться при выполнение указанных условий Выполнить HTTP-запрос
- HTTP метод POST запрос (на самом деле можно и GET — это уже вкусовщина)
- Адрес: Коннектор на вашем сайте, на котором будет отправляться запрос. Естественно там должна быть программа, принимающая POST запрос и выполняющая необходимые действия. В нашем случае вызывая заказ с принятым id и устанавливая для него переданный статус
- Условие применения триггера. Здесь нужно написать условие при наступлении которого будет выполняться HTTP запрос к нашему коннектору. Например можно перечислить статусы заказа RetailCRM при указании которых будет выполняться триггер. Допустим Вам нужно передать на сайт окончательный статус Оплачен или Отменен, и не передавать промежуточные статусы Подтвержден, Обработан, Выставлен счет и т.п.
Для написания подобных условий нужно использовать шаблонизатор (по моему Twig) и предусмотренные для этого методы
Я подготовил следующее условие
Условие расшифровывается так. Если при среди измененных полей есть поле Status и новое значение поля Status находится в группе статусов Выполнен или Отменен — то выполняем действие.changeSet.hasChangedField("status") and changeSet.getNewValue("status").getGroupCode() in ["complete", "cancel"]
Подробнее о правилах подготовки и написании триггеров можно узнать в документации
Правила подготовки триггеров и триггеры
- 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();
}
}
Поблагодарить автора
Отправить деньги
Комментарии: 48
Заказы не передаются, добавил в плагин строчку печати в лог, получаю такую ошибку:
[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.
)
)
)
Буду благодарен за совет, как исправить.
Вы обновляли компонент? По идее в свежей версии эта проблема устранена.
Хм, установил компонент из репозитория только сегодня. Установилась версия 2.0.0. Нужно обновить как-то вручную?
Текущая версия 2.2.1 Нужно устанавливать из репозитория modstore.pro. Все свежие версии и обновления там. За наводку спасибо дойдут руки обновлю в официальном
Спасибо за ответ, обновился из репозитория modstore.pro, всё заработало.
Пожалуйста. Для вас работаю
После установки и ввода ключа упала админка.
php 7.2
P.s. Не знаю зачем такой компонент нужен в extension_packages. Он не влияет на работу modx'a, так зачем его инициализировать без надобности?
php 7.2
P.s. Не знаю зачем такой компонент нужен в extension_packages. Он не влияет на работу modx'a, так зачем его инициализировать без надобности?
Проверил ошибку дважды, если установить компонент и указать сначала api ключ, то админка сразу падает не давая заполнить другие настройки. Вычистил класс, заполнил настройки и все завелось.А еще не знаю насколько корректно оставлять в комментариях доступы к демо-магазину
Да этот аккаунт все равно не существует.
За багрепорт спасибо. Буду править.
За багрепорт спасибо. Буду править.
Почистил, устранил, пофиксил, зарелизил. Спасибо еще раз.
Круто, что реагируешь, есть еще одна ошибка в создании нового заказчика по умолчанию в CRM [OnUserSave], профиль в modx'e связывается не по ID, а по internalKey
github.com/modxcms/revolution/blob/2.x/core/model/schema/modx.mysql.schema.xml#L1267
github.com/modxcms/revolution/blob/2.x/core/model/schema/modx.mysql.schema.xml#L1267
Подскажите, правильно ля и понял. Для того чтоб заказы падали в CRM, нужно туда добавить весь каталог товаров? Сейчас в CRM приходит только пользователь а заказ не падает
Нет не правильно.
Если товар в CRM не создан, то заказ все равно создается на основе присылаемых данных (название, цена, опции)
Если товары в базе CRM уже есть, то достаточно послать идентификатор товара, а все данные подтянутся из базы
Если товар в CRM не создан, то заказ все равно создается на основе присылаемых данных (название, цена, опции)
Если товары в базе CRM уже есть, то достаточно послать идентификатор товара, а все данные подтянутся из базы
а как отследить ошибку? заказ в CRM не падает, только новый пользователь. Лог ошибок чистый
В общем, если ставить по умолчанию доставку новая почта то не работает из коробки. Убрал новую почту все гуд) Спасибо за компонент, буду настраивать!
В плагине, в самом конце есть закомментированная строчка логгирования.
Достаточно ее раскомментировать и будет запись в журнал, с достаточно подробным описанием ошибки.
Достаточно ее раскомментировать и будет запись в журнал, с достаточно подробным описанием ошибки.
Все настроил по инструкции — ничего в RetailCRMне передается. Вообще. Как включить логирование — в плагине не нашел строки такой.
Значит неправильно настроили. Компонент работает как надо, проверено
Вопрос был таков:
Как включить логирование — в плагине не нашел строки такой.То что там все работает я не сомневаюсь, а хочу выяснить проблему. Что касается правильно или неправильной настройки, то я думаю там в 3 строках не трудно разобраться и вряд ли сделать ошибку…
Вот после этой строки в плагине
$response = $modRetailCrm->request->ordersCreate($orderData, $site);
можно включить логгирование$modx->log(1, print_r($response, 1));
Мне очень нравится как API RetailCRM возвращает ошибки. Все предельно понятно
Спасибо)
Вот что получаю:
Вот что получаю:
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
)
)
)
Насколько я понял, у тебя что то не то с модификациями. Может просто пустые.
Попробуй, распечатай перед отправкой массив с данными, может что-то будет более ясно.
Попробуй, распечатай перед отправкой массив с данными, может что-то будет более ясно.
$modx->log(1, print_r($orderData, 1));
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
)
)
)
Можно ли сделать какое-то условие, если модификация пустая не учитывать ее?
Ну как я и сказал. Если у свойства товара пустое значение — RetailCRM вернет ошибку.
Можно ли сделать какое-то условие, если модификация пустая не учитывать ее?Можно — разрешаю.
Ответить
Самое интересное, что у товара вообще нет опций, и нет модификаций. По идее если их нет, то они не должны учитываться никак…
Можно — разрешаю.У вас хорошее чувство юмора) Помогите справиться с этой задачей)) Может быть еще кому-то пригодиться.
С какой задачей? Перебрать массив опций и проверить их на пустоту? Это основа PHP: циклы и условия. Если ты не знаешь как делать подобные вещи — то лучше обратись в раздел работа.
Это надо проверять в плагине вашего компонента или где-то в другом месте?
Почему компонент не работает из коробки с товарами без опций. Там нет никаких модификаций и опций, а он не работает…
Почему компонент не работает из коробки с товарами без опций. Там нет никаких модификаций и опций, а он не работает…
на 130 с лишним скачиваний — он почему то у тебя одного не работает. Тебе не кажется, что проблема не в компоненте, а где то еще?
Судя по длинным веткам обсуждений, то у меня то у кого-то еще вылезают разные проблемы в нем. И почему-то везде они решаются а в данном случае помощи судя по всему ждать не приходится.
Потому что ты просишь чтобы за тебя все сделали, разжевали и готовое на блюдечке вынесли.
Точно… я же забыл что у нас здесь сообщество великих гуру… И свысока спускаться не по статусу большинству…
Верно заметил. Сообщество, а не детский сад. Здесь нянечек нет. Не нравится — не используй. Сделай сам.
Да действительно иногда проще самому сделать, чем тратить время на пустую болтовню с горе разработчиками
Николай, спасибо большое за помощь в адаптации и доработки компонента )))
Сделал все как просил ) Респект.
Сделал все как просил ) Респект.
Благодарю Николая за отличную техническую поддержку. Были сложности в интеграции, но при обращении все решилось оперативно. По мимо интеграции, была обновлена версия компонента и даны рекомендации по сайту в целом. Спасибо!
A это у меня одного так, что на сайте версия 2.2.3-пл и она не обновляется, даже не видит обновления, говорит, что у меня самая последняя версия, хотя на модсторе уже 2.4… Или там какая-то замута с тем, что компонент стал платный и теперь пока не купишь, никак не обновиться?
Именно так. Обновления только после покупки!
А будет какой-нибудь пост с описанием того, что там в новой платной версии появилось?
Это все есть на странице программы в разделе История изменений
История 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.
Настроено отслеживание изменения статуса заказа.
Возможно это дурацкий вопрос, но я нигде в справочнике апи не могу найти метод, чтоб с сайта товары в црмку загрузить. В версии компонента 2.2.3 используется 4 или 5я версия протокола апи? Всё, что я нашел, это какое-то описание полей класса товара тут. Но метод для создания товара через апи не могу найти. Или может в компоненте уже есть готовое решение для экспорта в црм справочника товаров?
Хороший вопрос. Товары конечно выгружаются из сайта в CRM, причем поддерживается автоматическая и ручная синхронизация. Но работает это не через API — все проще.
Как и для ЯндексМаркета формируется xml страница с YML каталогом. RetailCRM его прекрасно понимает. Важно понимать что в YML нет торговых предложений. То есть кроссовки не важно какого цвета и размера это один и тот же товар с одной ценой. А цвет и размер передается уже просто как опция заказа.
RetailCRM в этом плане пошли дальше и сделали поддержку торговых предложений. Тут уже можно разбить один товар на несколько. К примеру по цвету или размеру. Такой формат называтся ICML — это расширение YML формата. Как правильно сформировать ICML файл можно подробно прочитать здесь
Я даже могу дать пошаговую инструкцию по выгрузке товаров (YML формат, попроще)
1. Создаем отдельную XML страницу, называем ее icml
2. Пишет примерно такое содержание из двух сниппетов
Выбираем там «загружать из ICML» — указываем ссылку на нашу XML страницу — ставим отметку загрузить сейчас и жмем сохранить.
Все после этого по идее каталог товаров будет загружен автоматически — причем CRM сама будет переодически (раз в день по моему) обновлять товары в базе.
Ну и после этого важно понимать, что передавать товары в плагине заказ не нужно — нужно передать лишь идентификаторы товара и если надо опции. Остальные данные (название, цена, картинка) уже подгрузятся сами из базы CRM.
Надеюсь все понятно объяснил. Могу в рамках техподдержки помочь все это настроить (после покупки конечно)
Как и для ЯндексМаркета формируется 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.
Надеюсь все понятно объяснил. Могу в рамках техподдержки помочь все это настроить (после покупки конечно)
Ух-ты, удобно, спасибо. Сам бы никогда не узнал про такое. То есть плагин подправить надо, чтоб из данных о товарах в заказе только айдишник отправлялся, так?
Единственная беда — у меня сайт падает с 500 ошибкой при генерации этого юмл. 11к товаров. Если ставить лимит на товары до 10к, то работает, 10к+ — 500 ошибка. Причём в логах пусто. Может это какое-то ограничение мсПродуктс?
У тебя сервер же выдает ошибку. Смотри логи сервера. Скорее всего превышен лимит выделенных ресурсов. В таком случае тебе нужно не на лету генерировать страницу, а через консоль отдельный XML файл генерировать.
А если црмке скормить выгрузку для яндекс-маркета, сработает, или там поля не так называются?
А, да, там поля другие.
Ниче не другие поля. я же выше написал, что RetailCRM понимает YML и его ICML это расширение YML. На всякий случай YML — это Yandex Market Language — то есть формат придуманный маркетом.
Спасибо за оперативную компетентную помощь в доработке компонента под индивидуальные задачи!
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.