Теория выгрузок из 1С в MODX (часть 1 из 2)

И снова привет!
Выгрузка товаров на сайт — это самый, самый частый кейс моей мини-студии. Для реализации мелких-средних интернет-магазинов используем классическую и сверхпопулярную связку MODX+miniShop2, для крупых — нет, но я как-нибудь обязательно расскажу почему.
Давайте разберемся, как вообще появляется потребность выгрузки товаров из 1С на сайт. Обычно, интернет-магазины появляются у владельцев малого-среднего бизнеса, уже имеющие 1С и какие-то розничные объекты. Очень редко — 1С изначально затачивается под интернет-магазин.
В первом случае вы должны быть готовы к тому, что в 1С будет полная мусорка, которую очень не хочется грузить на сайт. Во втором случае, обычно все изначально делается так, чтобы на сайт все грузилось максимально просто и легко.
Так или иначе, делаем вывод, что данные нужно не только 1С получать, парсить и заливать на сайт, а еще и обрабатывать перед тем как залить.

Что вообще есть выгрузка из 1С?


В 1С начиная с очень давних времен есть протокол обмена с сайтом — CommerceML. В данный момент есть две версии данного протокола, мы остановимся на втором как на самом распространенном. В «ванильном» издании 1С это два файла — import.xml и offers.xml (на самом деле есть еще файл orders, и кучу других, но вы их в задаче «залить товары на сайт» не увидите). В файле import.xml хранятся сами товары, их характеристики, структура каталога и прочая дополнительная информация. В файле offers.xml хранятся товары, цены, типы, цен, наличие и в некоторых модификациях — поля инструмента «Маркетинговая акция» где указываются товары на скидке или прочие вещи.

Мини пример файла import:
<?xml version="1.0" encoding="UTF-8"?>
<КоммерческаяИнформация ВерсияСхемы="2.03" ДатаФормирования="2018-01-23">
  <Классификатор>
    <Ид>2460763d-004d-11df-8b40-001a4bb12848</Ид>
    <Наименование>Классификатор (Каталог товаров)</Наименование>
    <ТипВыгрузки>ПолнаяВыгрузка</ТипВыгрузки>
    <Группы>
      <Группа>
        <Ид>8f55ea2c-1062-11e7-bdde-00155d007103</Ид>
        <Наименование>Joggy</Наименование>
        <Группы>
          <Группа>
            <Ид>76d5e03d-12c4-11e7-bdde-00155d007103</Ид>
            <Наименование>Рубашки</Наименование>
          </Группа>
          <Группа>
            <Ид>221c4591-9f47-11e7-8d7f-00155d007103</Ид>
            <Наименование>Толстовки</Наименование>
          </Группа>
          <Группа>
            <Ид>8f55ea2d-1062-11e7-bdde-00155d007103</Ид>
            <Наименование>Футболки</Наименование>
          </Группа>
        </Группы>
      </Группа>

    </Группы>
    <Свойства>
      <СвойствоНоменклатуры>
        <Ид>0734a3e9-005f-11df-8b40-001a4bb12848</Ид>
        <Наименование>Страна</Наименование>
        <Обязательное>false</Обязательное>
        <Множественное>false</Множественное>
        <ИспользованиеСвойства>true</ИспользованиеСвойства>
      </СвойствоНоменклатуры>
    </Свойства>
  </Классификатор>
  <Каталог>
    <Ид>2460763d-004d-11df-8b40-001a4bb12848</Ид>
    <ИдКлассификатора>2460763d-004d-11df-8b40-001a4bb12848</ИдКлассификатора>
    <Наименование>Каталог товаров</Наименование>
    <Товары>
      <Товар>
        <Ид>6a9f6996-ba02-11e7-9302-00155d007103#f14f4d23-baec-11e7-a79a-00155d007103</Ид>
        <ШтрихКод>2000000848112</ШтрихКод>
        <Артикул>049794</Артикул>
        <ДатаСоздания>1508889600</ДатаСоздания>
        <Наименование>ADSERY2 Джинсы 6225 (32-42/*7) женщинам</Наименование>
        <КоличествоВПачке>7</КоличествоВПачке>
        <БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="PCE">шт</БазоваяЕдиница>
        <ХарактеристикиТовара>
          <ХарактеристикаТовара>
            <Наименование>Размер</Наименование>
            <Значение>33</Значение>
          </ХарактеристикаТовара>
          <ХарактеристикаТовара>
            <Наименование>Рост</Наименование>
            <Значение>32</Значение>
          </ХарактеристикаТовара>
        </ХарактеристикиТовара>
        <ЗначенияРеквизитов>
          <ЗначениеРеквизита>
            <Наименование>ВидНоменклатуры</Наименование>
            <Значение>Товар</Значение>
          </ЗначениеРеквизита>
          <ЗначениеРеквизита>
            <Наименование>ТипНоменклатуры</Наименование>
            <Значение>Товар</Значение>
          </ЗначениеРеквизита>
          <ЗначениеРеквизита>
            <Наименование>Полное наименование</Наименование>
            <Значение>Джинсы 6225 (32-42/*7) женщинам</Значение>
          </ЗначениеРеквизита>
        </ЗначенияРеквизитов>
        <Группы>
          <Ид>6a9f6995-ba02-11e7-9302-00155d007103</Ид>
        </Группы>
        <Описание>Утепленные джинсы актуального зауженного покроя. Декор в виде легких потертостей и строчки.</Описание>
        <ЗначенияСвойств>
          <ЗначенияСвойства>
            <Ид>0734a3e9-005f-11df-8b40-001a4bb12848</Ид>
            <Значение>Китай</Значение>
          </ЗначенияСвойства>
          <ЗначенияСвойства>
            <Ид>074bce28-004f-11e8-9d7b-00155d007103</Ид>
            <Значение>ADSERY2</Значение>
          </ЗначенияСвойства>
        </ЗначенияСвойств>
      </Товар>
    </Товары>

  </Каталог>
Мини пример файла offers:
<?xml version="1.0" encoding="UTF-8"?>
<КоммерческаяИнформация ВерсияСхемы="2.03" ДатаФормирования="2018-01-23">
  <ПакетПредложений>
    <Ид>2460763d-004d-11df-8b40-001a4bb12848#</Ид>
    <Наименование>Пакет предложений</Наименование>
    <ИдКаталога>2460763d-004d-11df-8b40-001a4bb12848</ИдКаталога>
    <ИдКлассификатора>2460763d-004d-11df-8b40-001a4bb12848</ИдКлассификатора>
    <ТипыЦен>
      <ТипЦены>
        <Ид>995aa9b6-19f8-11df-bb4e-001a4bb12848</Ид>
        <Наименование>Розничные</Наименование>
        <Валюта>руб.</Валюта>
        <Налог>
          <Наименование>НДС</Наименование>
          <УчтеноВСумме>false</УчтеноВСумме>
        </Налог>
      </ТипЦены>
    </ТипыЦен>
    <Предложения>
      <Предложение>
        <Ид>2b478218-df7b-11e5-baeb-00155d007103</Ид>
        <ШтрихКод>2000000694153</ШтрихКод>
        <Артикул>030067</Артикул>
        <ДатаСоздания>1483228800</ДатаСоздания>
        <Наименование>98 CM Дж. L-7061 (25-30/*6) жен.</Наименование>
        <КоличествоВПачке>6</КоличествоВПачке>
        <БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="PCE">шт</БазоваяЕдиница>
        <Цены>
          <ХарактеристикиТовара>
            <ХарактеристикаТовара/>
          </ХарактеристикиТовара>
          <Цена>
            <Представление>2 590 руб. за шт</Представление>
            <ИдТипаЦены>995aa9b6-19f8-11df-bb4e-001a4bb12848</ИдТипаЦены>
            <ЦенаЗаЕдиницу>2590</ЦенаЗаЕдиницу>
            <Валюта>руб</Валюта>
            <Единица>шт</Единица>
            <Коэффициент>1</Коэффициент>
          </Цена>
        </Цены>
        <Количество>0</Количество>
      </Предложение>
Данный пример не совсем клевый, так как например характеристики товара для фильтров не указаны, они указаны как ХарактеристикаТовара, а это значит индивидуальная характеристика товара, но в целом ок — сойдет.
Итак, у нас есть файлы, есть их структура и нам необходимо спарсить данные и залить на сайт.
С чего можно начать?

Если выгрузка у вас простая, то задачу можно решить «в лоб», а именно использовать условный SimpleXML и попупутно загружать товары на сайт. Вариант хороший, не занимает много времени. Но есть один большой минус — если товаров будет много, дебаг выгрузки превратиться в ужас. Второй же вариант — использование паттерна Value Object. Что это значит?

Паттерн Value Object имеет ввиду хранение элементов как отдельных объектов. То бишь, описывается класс конкретной сущности с которой вы будете работать. (не обязательно даже делать наследование от сущностей minishop2). Делается это для того, чтобы в последствии «скормить» процессору resource/create
данные максимально удобно.

Когда модели описаны, можно перейти к непосредственному переводу модели в какое-то промежуточное состояние — допустим JSON объект. С точки зрения кода, я предпочитаю вот такой вот вариант
public function toJSON(){
    return json_encode($this);
}
В данном моменте важно, чтобы данные где-то сохранялись, для того чтобы функция загрузки работала с заранее сохраненными и обработанными данными
В формате реального проекта, я храню данные вот в такой структуре:



Следующий шаг — загрузка. И тут все просто, создавать товары, опции и загружать изображени] можно с помощью процессеров в MODX. Мы восстанавливаем файлы в объекты и загружаем данные.

Основные преимущества такого подхода


  • 1. Промежуточные файлы можно версионировать. Они поддаются unix-like diff, а следовательно можно визуально видеть что пошло не так. (1С частенько может выдавать неверные данные, ибо какой-нибудь человек некорректно сделал переоценку или еще что-нибудь)
  • 2. Процесс парсинга и загрузки — изолированы друг от друга. Если скрипты настроены на автоматическое обновление, то при обновлении структуры — сломается только парсер, данные остануться в целостности.
  • 3. Такой код легче дебажить, поддерживать, обновлять и интегрировать в любые другие проекты.. Так как каждый этап выполняет сугубо свою часть работы, сам по себе код решений становится проще для понимания и короче, следовательно найти ошибку становится проще. следовательно, и отладка выполняется проще, так как выходной формат данных всегда можно отслеживать, а для написания загрузчика можно использовать фейковые данные, пока, например, не предоставлен окончательный фариант файла выгрузки
Так как в miniShop2 по умолчанию нет контроля остатков (может добрые люди сделают?), я обычно расширяю модель msProduct новым полем — remains. И уже в него записываю данные о остатках. В msCartHandler я описал свою логику «снятия» товара с остатков. (хотя иногда и не пишу вообще. Выгрузка через день все равно мне отдаст «правильные» данные.

Я сознательно не публикую примеры кода или примеры реализации. Я хочу выяснить ваш интерес к этой теме. Если интерес будет — попробуем написать какую-нибудь выгрузку на ванильном примере.

А если выгрузка вам нужна уже сейчас, пишите.
Всем хорошего настроения и не болеть!
Павел Бигель
06 апреля 2020, 19:10
modx.pro
13
6 023
+17
Поблагодарить автора Отправить деньги

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

Павел Голубев
06 апреля 2020, 19:24
0
А рассматривали вариант напрямую обращаться к SQL-серверу 1С(если конечно таковой имеется) и от туда забирать данные?
    Павел Бигель
    06 апреля 2020, 19:27
    0
    А зачем?
    CommerceML выгружается двумя кнопками и дает вполне себе структурные данные. Если же рассматривать вариант что по той стороне 1С 8.3 и хороший 1С программист, можно попробовать поработать с вебхуками. Хороший 1сников я так и не нашел, поэтому работаем с файловыми обменами в основном :)
      Павел Голубев
      06 апреля 2020, 19:38
      0
      А как решаете проблему, когда с 1С нужно обмениваться в дуплексном режиме в реал-тайме?

      Пример.
      На сайте создали новый товар его нужно тут же отправить в 1С. В это время в физическом магазине оформили заказ и его нужно отправить в Modx.
        Павел Бигель
        06 апреля 2020, 19:41
        0
        Опять же, вебхуки — лучший вариант для решения таких задач. Правда, пока таких задач мне не поступало. Обычно обновление раз в 3-4 часа было.
        Не нужно делать прямой коннект в базе. Это иррационально.
          Павел Голубев
          06 апреля 2020, 20:01
          0
          Вебхуки и REST API (https://infostart.ru/public/565435/) — это одно и тоже в 1С?
            Павел Бигель
            06 апреля 2020, 20:10
            0
            Честно сказать — не эксперт как это работает со стороны 1С.
              Андрей Степаненко
              07 апреля 2020, 06:52
              +1
              Лучше не использовать, если в штате нету опытного программиста 1с.
              в 1с так заведено, что если ты что то доработал, то при обновлении 1с, ты в ручную все будешь по новой внедрять.
      Семён Кудрявцев
      07 апреля 2020, 08:27
      0
      Очень интересную тему затронули. Продолжайте, поделитесь своим опытом.
      У меня в последнее время стали часто появляться задачи по интеграции небольших магазинов и
      сейчас в сайтах на MODX это решается либо компонентом mSync, когда нужна периодическая выгрузка или обмен заказами или когда клиент хочет прям полную интеграцию, тогда стандартный REST API в 1С — плюсом такого решения является отсутствие необходимости в 1С-специалисте, коих сейчас трудно найти.
      Всё, что нужно это опубликовать 1С на веб-сервере и поставить одну галочку включения REST интерфейса.
      Дальше всё делается со стороны web-разработчика. Сейчас детально изучают эту тему — мне кажется это наиболее оптимальный способ интеграции с 1С как для малых так и для больших магазинов.
        Павел Бигель
        07 апреля 2020, 08:33
        +1
        Спасибо!
        mSync решение не очень, уж в очень идеальных условиях оно работает
          Михаил
          07 апреля 2020, 09:19
          0
          Ну я бы не сказал, что он не очень. При определенном допиливании справляется
        Павел Голубев
        07 апреля 2020, 10:20
        0
        А как у вас Modx видит 1С? Они физически находятся на одном сервере, объединены в сеть по VPN, 1С доступна из вне или еще как-то?
          Алексей Соин
          07 апреля 2020, 13:02
          0
          1С умеет выгружать xml файлы commerceML по ftp
            Павел Голубев
            07 апреля 2020, 14:55
            0
            Это понятно, речь же об доступе Modx к REST API 1С
              Алексей Соин
              07 апреля 2020, 15:04
              0
              у меня есть опыт в взаимодействии с 1С через вебсервисы через soap, если в таком ключе говорить, то на сервере 1с настраивается внешний доступ по авторизации, а дальше по названию вебсервиса кидаются параметры и возвращаются значения в виде json. Но это очень редкий случай, так как эти вебсервисы нужны для данных которые нужно получать в реалтайме, а товары к таким я бы не относил, а просто обновлял бы их по расписанию. Плюс в 90% случаев 1сники откажутся(не смогут) делать чтото подобное, так как надо чтото делать, а xml выгрузить эт проще))
        Роман Ильин
        07 апреля 2020, 08:53
        0
        Отличная тема, поддерживаю продолжение!
          Александр Мельник
          07 апреля 2020, 09:04
          0
          Так, а для особо «одаренных» можно поподробнее.
          Вам 1с предоставляет файлы с данными в формате xml.
          описывается класс конкретной сущности с которой вы будете работать.
          Тоесть вы создаете php class Product, описывая в нем свойства товара?
          Когда модели описаны, можно перейти к непосредственному переводу модели в какое-то промежуточное состояние — допустим JSON объект.
          Вот это вообще не понял. Под моделью вы понимаете терминологию MODX? тоесть модель это файловое отображение таблицы в базе данных? Вы создаете таблицы в базе свои? Что значит промежуточное состояние?
          В данном моменте важно, чтобы данные где-то сохранялись, для того чтобы функция загрузки работала
          Тоесть в директории products у вас на скрине что хранится? Файлы json где в каждом файле один товар?
          А после этого вы запускаете какой-то свой скрипт, который считает json файлы и запускает процессор создания товара?
            Павел Бигель
            07 апреля 2020, 09:16
            0
            Тоесть вы создаете php class Product, описывая в нем свойства товара?
            Да
            Вот это вообще не понял. Под моделью вы понимаете терминологию MODX? тоесть модель это файловое отображение таблицы в базе данных? Вы создаете таблицы в базе свои? Что значит промежуточное состояние?
            Модель это класс. Промежуточное состояние может быть разным. В моем случае это json файлы.
            Тоесть в директории products у вас на скрине что хранится? Файлы json где в каждом файле один товар?
            А после этого вы запускаете какой-то свой скрипт, который считает json файлы и запускает процессор создания товара?
            Да, все верно
            Дмитрий
            14 апреля 2020, 00:44
            2
            +3
            REST API в 1С УНФ 1.6 пример получения остатков
            <?php
            $url = "https://XXX.XXX.XXX.XXX/SmallBusiness/odata/standard.odata/AccumulationRegister_ЗапасыНаСкладах/Balance?&%24select=Номенклатура_Key,СтруктурнаяЕдиница_Key,КоличествоBalance&%24format=json;odata=nometadata";
            
            $ch = curl_init($url); 
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($ch, CURLOPT_USERPWD, "odata.user:xxxxxxxxxxxxxxxxxxxxxxxx");
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Accept: application/json'));
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
            
            $json = curl_exec($ch);
            $err_status = curl_error($ch);
            echo ("<pre>");
            echo $err_status;
            echo ("</pre>");
            curl_close($ch);
            
            $json = json_decode($json, true);
            
            ?>
            Описание товара:
            $url="https://192.168.1.52/SmallBusiness/odata/standard.odata/";
            $url .= "Catalog_Номенклатура?%24filter=like(Description,'ИСКОМОЕ НАЗВАНИЕ')&%24select=*&%24top=10&%24format=json;odata=nometadata";
            Ну и так далее. Работает быстро.
            mSync теперь только заказы с сайта выгружает.
              Андрей Степаненко
              13 мая 2020, 22:50
              0
              в 1С есть порциональная выгрузка, если она запускается. Что произойдет?
                Павел Бигель
                14 мая 2020, 00:08
                0
                Ожидается, что программист на своей стороне обрабатывает эти моменты.
                Кстати спасибо что напомнил что неплохо было бы написать практическую часть курса)
                  Руслан
                  14 мая 2020, 11:50
                  0
                  я свой пакетный АПИ сварганил и из 1С по нему работаю в json формате своими 1Сными обработками ;)
                  10к товаров за 2 минуты обновляется со всеми допопциями при чем из разных баз в один каталог на сайте hookah.pro из УТ 10 (свои обработки на обычных формах пилил) и из УТ 11.4 на управляемых формах посредством расширения конфигурации(чтобы не корячить типовой код конфы) и внешних обработок запускающихся по расписанию
                    Руслан
                    14 мая 2020, 12:00
                    0
                    а в 1С УТ 11.4 заказы у меня летят через ритейлцрм в реальном времени так как 1С поднята как вебсервис для приема хуков от ритейлцрм…
                      Руслан
                      14 мая 2020, 12:35
                      0
                      и про пакетный АПИ(как компонент эту поделку не имеет смысла выкладывать так как он за несколько десятков минут на коленке пишется) оптимально получилось для json формата по 200 товаров в пакете отправлять, а свой код отправки данных на этот АПИ из 1С могу выложить кому интересно
                        Руслан
                        14 мая 2020, 13:09
                        0
                        я про свой пакетный АПИ для MODX и свои обработки 1С общающиеся с этим АПИ и свой код на чистом 1С (без курла) сборки и отправки данных на этот АПИ из 1С могу выложить кому интересно
                          Junior
                          06 сентября 2021, 07:28
                          0
                          Руслан, было бы интересно взглянуть на обработку.
                deleted
                12 октября 2022, 01:00
                0
                для крупных — нет, но я как-нибудь обязательно расскажу почему.
                А почему?) Делал свой компонент наподобие шопкипера, использовали в компании, но решили перейти на минишоп
                  Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                  28