Интеграция интернет-магазина с ERP-системой (1С)

Этим летом столкнулся с проектом интернет-магазина, после того, как были закончены все работы над внешним видом и бизнес-логикой, встала задача интеграции с ERP-системой. В качестве ERP-системы выступала 1С. В рамках интеграции необходимо было решить следующие задачи: наполнения каталога товаров, поддержания его актуальности, синхронизация цен, синхронизация остатков. Период обновления цен — 1 раз в сутки, обновление остатков каждые 15 минут. Ориентировочный объем товарного каталога ~100 тыс товаров. Количество складов на момент написания обмена уже было 14 (свои + удаленные склады поставщиков).

Так же было не маловажным обмен заказами и историей заказов. После разработки требований к обмену начался анализ возможных решений:

  1. Обмен по средствам CommerceML.
  2. Обмен по средством файлов.
  3. Обмен по средствам REST.
  4. Обмен через промежуточную/интеграционную БД.

В кратции рассмотрим каждый метод, его достоинства и недостатки.

Обмен по средствам CommerceML
Достоинством такого способа является готовая реализация со стороны 1С, а значит нет необходимости привлечения программиста 1С. Для начала работы достаточно прописать URL шлюза, который принимал бы данные от 1С, разбирал и записывал в БД сайта. К недостаткам данного способа можно отнести избыточность формата XML и вытекающие от сюда минусы при работе с XML из PHP.

Обмен по средством файлов
Теоретически такой подход мог бы теоретически применяться в таком виде: каждый файлик описывал бы товарное предложение. Каждые 15 минут формировались бы файлы с остатками на складе (только по измененным товарам). 1 раз в день — файл с изменениями цен. Минус такого файла — неудобство навигации по данным, медленная работа с файлами.

Обмен по средствам REST
Достойная альтернатива приведенным выше возможным способам обмена данными. Данные по REST передаются в xml или json. JSON более лаконичен и занимает меньше места. К недостаткам можно отнести отсутствие истории переданных данных (при условии, что не ведется лог). В случае, если REST-сервис будет неддоступен, данные на сайте не обновятся, хотя этот недостаток будет зависит от конкретной реализации, а именно от наличия обратной связи с подтверждением о получении данных.

Обмен через промежуточную/интеграционную БД
Обмен через промежуточную БД заключается в том, что обмен происходит через специально спроектированную БД. Со стороны 1С работа с такой БД производится по средствам SQL запросов. Подключение к внешнему источнику данных осуществляется через ADODB.Connection. По мимо самих данных, в таблицах, где это необходимо, хранятся даты записи и чтения данных. Преимущества использования интеграционной БД: возможность делать выборки, тем самым отбирать и обрабатывать только данные по изменённым записям.

После анализа этих способов было решено остановиться на использовании интеграционной БД, так как это гарантирует доставку данных, в случае недоступности сервера БД — обработка 1С не отработает, и будет выполнена попытка позже, запущена вручную после устранения причины или в следующую итерацию по расписанию. Если сайт не сможет достучаться, то так же данные не теряются, так как у обновленных записей дата чтения старее даты обновления. Далее приступили к проектированию БД под наши потребности. Схема БД представлена на изображении:

db

Целостность данных в БД поддерживается за счёт использования внешних ключей. Набор полей в таблицах может быть произвольным, всё зависит от задачи, но для исключения повторного чтения не измененных записей используются поля: date_update, date_read. В большинстве случаев это дата записи данных из 1С и дата чтения данных сайтом соответственно, за исключением тех таблиц заказов, так как источником заказов является сайт, следовательно заказы пишет сайт. Условием выборки записей на чтение является следующее условие: date_update > date_read.

Для удобства со стороны сайта было написано консольное приложение на базе Symfony компонента symfony/console. Для обеспечения возможности выполнить минимально необходимую единицу импорта (например, обновить только остатки или только товары) задача импорта разделена на команды, а так же присутствуют группирующие команды, которые добавлены в cron.

Так как периодичность обновления остатков довольно частая, каждые 15 минут, теоретически может произойти так, что за предыдущие 15 минут в БД придёт такое количество изменений, которое не успеет обновиться за 15 минут, и по истечению этого времени запустится ещё один worker, который будет по второму кругу обновлять те же остатки (это может произойти, так как изменение даты чтения сайтом происходит только после сохранения этих изменений в БД сайта). В итоге может скопиться большое количество worker’ов, которые будут тормозить сервер. Что бы этого не произошло необходимо организовать очередь, тогда каждый worker будет брать уникальный ключ (товар-склад) записи об остатке. В случае неуспеха обновления остатка ключ о таком остатке будет помещаться обратно в очередь, в конец.

Описанная выше схема обкатана и работает без сбоев уже 6 месяцев. На данный момент с ERP-системой происходит обмен: товарным каталогом, акциями, остатками, заказами.