Вступление
Здравствуйте, друзья. Меня зовут Тян Семен, и вот уже несколько лет я занимаюсь интеграцией учётных систем 1С и IIKO. За это время вышло восемь публикаций: мы разбирались с SQL-запросами к серверу IIKO, учились обмениваться накладными, создавали номенклатуру из 1С и мечтали о фоновом двунаправленном обмене.
В этой статье я расскажу о технических решениях, к которым мы пришли за последний год. Без привязки к конкретному продукту – скорее набор архитектурных подходов, которые могут быть полезны любому, кто строит интеграцию между 1С и внешними системами.
Для контекста: раньше мы использовали внешние обработки (.epf), типовую COM-компоненту IIKO для загрузки данных и промежуточный HTTP-сервис. Ниже – о том, чем мы всё это заменили и почему.
1. Гибридная архитектура: что где хранить
Первый вопрос, с которым сталкивается любая интеграция: где хранить данные? Если всё в 1С – решение замкнуто на одну базу. Если всё на внешнем сервисе – зависимость от интернета для мегабайтных справочников.
Мы пришли к разделению по объёму данных:
- Справочники IIKO (номенклатура, склады, контрагенты) синхронизируются локально через дельта-запросы к сервису Update IIKO (XDTO). Это мегабайты XML, которые незачем гонять через интернет – сервер IIKO обычно в той же локальной сети.
- Сопоставления (какой товар 1С соответствует какому товару IIKO), ревизии синхронизации и прочие метаданные хранятся во внешнем сервисе (Go, REST API). Это килобайты, и они должны быть доступны из любой базы 1С.
- Разбор документов (накладных, заказов) выполняется сервисом – это позволяет менять логику парсинга без обновления расширения.

Расширение остаётся «тонким клиентом»: UI, сбор данных для отправки, запись результатов. Бизнес-логика разбора – на сервисе.
Практический результат: при миграции на другую конфигурацию (например, с Бухгалтерии на ERP) все сопоставления и настройки уже в сервисе. Подключил расширение к новой базе – продолжил работать.
2. Сквозной контекст подключения вместо «активного подключения»
Типичный паттерн интеграции с IIKO: у клиента несколько ресторанов — несколько серверов IIKO. В первых версиях мы использовали понятие активного подключения: булев флаг active на справочнике подключений, переключение вручную. Проблемы предсказуемые: забыл переключить — отправил накладную не в тот ресторан.
Решение: подключение как сквозной параметр через все формы расширения:
- Формы списков справочников IIKO (номенклатура, склады и т.д.) получают выпадающий список подключений сверху. Данные фильтруются динамически через
СоставнойФильтрдинамического списка. - При ручной отправке документа в IIKO — подключение определяется правилами маршрутизации, а не флагом.
- Заимствованные формы списка типовых документов (Приобретение, Реализация) получают picker подключения программно через
&После("ПриСозданииНаСервере")в модулеМодификацияКонфигурацииПереопределяемый.

Технически это означает, что API серверных модулей (like_InvoicesAtServer, like_DocumentAtServer, like_EntitiesAtServer) больше не читают «активное подключение» изнутри, а принимают connection первым обязательным параметром. Рефакторинг болезненный (затронул ~20 модулей), но после него каждая функция стала чистой — без скрытых зависимостей от глобального состояния.
3. Автоматическая выгрузка через план обмена
Ручная выгрузка документов — основная боль. Типичный сценарий: бухгалтер проводит документ, потом вручную открывает обработку, выбирает документы, сопоставляет, нажимает «Передать». Пять-шесть кликов на каждый документ. Забыл — документ не в IIKO.
Для автоматизации мы использовали стандартный механизм платформы — план обмена как очередь задач:
-
Подписка на событие
ПриЗаписи(EventSubscription) для трёх типов документов (Приобретение, Реализация, Отгрузка). При проведении документ регистрируется в плане обмена. Подписка не вмешивается в проведение — только ставит в очередь. -
Регламентное задание каждые 10 минут дренирует очередь: читает зарегистрированные изменения через виртуальную таблицу
Документ.X.Изменения, группирует по типу. -
Для каждого документа — маршрутизация по правилам: справочник
like_uploadRulesс табличной частью условий (FieldName,Operator,ValueLink/ValueLiteral). Первое подходящее правило по приоритету определяет целевое подключение. Пустые условия = match-all. -
Перед отправкой — авто-сопоставление (об этом ниже). Если всё сопоставлено — отправка. Если нет — документ откладывается с записью в регистр
like_deferredMatchings. -
При ошибке IIKO — запись в
like_uploadErrorsс автоматическим retry (до 5 попыток, потом ручное вмешательство через UI «Очередь выгрузки»).

Нюанс с ВыбратьИзменения: мы не используем стандартный ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения) с его семантикой номеров сообщений. Вместо этого читаем напрямую из виртуальной таблицы Документ.X.Изменения запросом ВЫБРАТЬ Изм.Ссылка ИЗ Документ.X.Изменения ГДЕ Изм.Узел = &node. Это проще, когда план обмена используется как очередь, а не как реальный механизм обмена данными.
Нюанс с String(TypeOf()): под русской платформой String(TypeOf(docRef)) возвращает синоним документа ("Приобретение товаров и услуг"), а не идентификатор метаданного. Для определения типа документа используем Metadata.FindByType(TypeOf(docRef)).Name — он возвращает каноничное "ПриобретениеТоваровУслуг" независимо от локали.
4. Авто-сопоставление номенклатуры
Сопоставление «товар 1С ↔ товар IIKO» — самая трудоёмкая часть первоначальной настройки. У клиента 500-5000 позиций номенклатуры, каждую нужно сопоставить вручную.
Мы автоматизировали это в два этапа:
Этап 1 — по коду IIKO. У клиентов, перешедших с типового обмена, часто есть дополнительный реквизит «Код IIKO» у номенклатуры (через механизм БСП «Дополнительные реквизиты и сведения»). Если он заполнен — ищем совпадение по num в справочнике like_products. Один JOIN-запрос, мгновенно.
Этап 2 — по наименованию (нечёткий поиск). Если кода нет — разбираем наименование на токены:
- Убираем стоп-слова (
в/с,с/м,зам,шт). - Выделяем числа и единицы измерения (
500мл,1кг,3.2%) в отдельные группы. - Считаем взвешенное совпадение оставшихся токенов с наименованиями IIKO.
Порог совпадения — 0.85 (настраиваемый). Если превышен — предлагаем пару. Если нет — оставляем для ручного сопоставления.
Визуальный контроль: авто-сопоставленные строки подсвечиваются жёлтым через программное условное оформление (ConditionalAppearance.Items.Add(), фильтр по булеву флагу matched). Три кнопки: «Подтвердить авто» (снять флаг, оставить значения), «Сбросить авто» (очистить likeRef), «По артикулу» (запустить этап 1 вручную).

При автоматической выгрузке авто-сопоставление запускается перед каждой отправкой. Если появился новый товар — система попробует сопоставить сама и, только если не справится, отложит документ для ручного разрешения.
5. Встраивание в типовые формы через расширение
Отдельно хочу остановиться на паттерне встраивания, который мы используем для добавления функциональности в стандартные формы типовых конфигураций (КА, ERP, УТ).

Расширение заимствует модуль МодификацияКонфигурацииПереопределяемый и добавляет обработчики через &После:
-
&После("ПриСозданииНаСервере")— программно создаём реквизиты формы (ИзменитьРеквизиты), элементы UI (Форма.Элементы.Добавить), команды и условное оформление. Фильтруем поФорма.ИмяФормычтобы работать только с нужными формами. -
&После("ВыполнитьПереопределяемуюКоманду")— обрабатываем нажатие кнопки «Отправить в IIKO», которую добавили в серверном хуке.
Ключевой приём: РеквизитФормы(Имя, Тип, Путь, Заголовок) — третий параметр это путь (имя родительской таблицы для колонок), не заголовок. На этом спотыкались не раз.
Этот же паттерн мы используем для добавления picker'а подключения в заимствованные формы списков документов — реквизит like_connection создаётся программно и привязывается к элементу формы через УстановитьДействие("ПриИзменении", ...).
Что дальше
Из ближайших технических задач:
- Расширение авто-сопоставления на партнёров, склады и организации (сейчас работает только для номенклатуры).
- Миграция правил маршрутизации в сервис — чтобы управлять ими централизованно из любой базы 1С.
- Оценка условий правил с ссылочными типами — сейчас
ValueLinkв табличной части хранит составной тип (CatalogRef.*), сравнение через прямое=вместоXMLString.
Если тема интересна — в следующей публикации могу подробнее разобрать протокол IIKO: особенности XDTO-схем, авторизацию через SHA1-хэш, нюансы GZIP-сжатия и различия между RMS и Chain.
Заключение

Проект прошёл путь от набора внешних обработок до расширения с гибридной архитектурой, автоматической выгрузкой и нечётким сопоставлением. Основные уроки:
- План обмена отлично работает как очередь задач, если не использовать семантику номеров сообщений.
String(TypeOf())возвращает синоним, а не имя метаданного — используйтеMetadata.FindByType().Name.- Сквозной параметр подключения вместо глобального состояния — больше кода при рефакторинге, но каждая функция становится предсказуемой.
- Авто-сопоставление по токенам с порогом 0.85 закрывает 70-80% номенклатуры без ручного вмешательства (по нашим наблюдениям).
Буду рад вопросам и обратной связи в комментариях.
Вступайте в нашу телеграмм-группу Инфостарт