План обмена 1С — это объект метаданных, который хранит узлы обмена (другие базы или внешние системы) и ведёт для каждого узла список изменённых объектов. Объект включается в состав плана обмена; при записи он регистрируется в узлах автоматически (авторегистрация) или программно. Затем изменения читаются из таблицы Изменения, передаются получателю и после подтверждения снимаются с регистрации методом ПланыОбмена.УдалитьРегистрациюИзменений().

На этом механизме построены и типовые синхронизации, и большинство интеграций 1С с сайтами и сервисами. Ниже — как он устроен и как с ним правильно работать в коде.

Устройство плана обмена

План обмена находится в ветке «Общие» конфигуратора и по структуре похож на справочник: у него есть элементы (узлы), реквизиты и табличные части.

  • Узел — участник обмена. В реквизитах узла обычно хранят настройки: адрес, отборы, организацию.
  • Этот узел — предопределённый узел, обозначающий текущую базу. Получить его можно методом ПланыОбмена.ИмяПлана.ЭтотУзел().
  • Состав — список объектов конфигурации, изменения которых план обмена отслеживает. Открывается в свойствах плана обмена кнопкой «Состав».
  • Номера сообщений — у каждого узла есть номер отправленного и принятого сообщения; на них построена квитанция о доставке.

Для каждого объекта из состава платформа создаёт служебную таблицу регистрации изменений: какой объект, для какого узла, с каким номером сообщения.

Авторегистрация или программная регистрация

В составе плана обмена у каждого объекта есть флаг «Авторегистрация»:

РежимЧто происходит при записи объекта
РазрешитьОбъект регистрируется во всех узлах плана, кроме этого узла и узла, от которого объект только что получен
ЗапретитьПлатформа ничего не регистрирует; это делает ваш код или пользователь через обработку регистрации

Авторегистрация удобна, когда во все узлы уходит всё. Как только появляются условия — «в узел магазина только номенклатура с флагом публикации», «в бухгалтерию только документы своей организации» — авторегистрацию запрещают и регистрируют программно.

План обмена 1С: изменённые объекты получают метки узлов-получателей
План обмена 1С: изменённые объекты получают метки узлов-получателей

Программная регистрация изменений

Через ОбменДанными.Получатели в ПередЗаписью

Самый правильный способ — подписка на событие ПередЗаписью, в которой объект добавляет нужные узлы в свойство ОбменДанными.Получатели. Платформа сама зарегистрирует изменения при записи, в той же транзакции.

1С
// Подписка на событие ПередЗаписью справочника Номенклатура.
// Регистрирует опубликованную номенклатуру в узлах обмена с сайтом.
Процедура ОбменССайтомПередЗаписьюНоменклатуры(Источник, Отказ) Экспорт

	Если Источник.ОбменДанными.Загрузка Тогда
		Возврат; // Объект пришел из обмена - не регистрируем обратно
	КонецЕсли;

	Если Не Источник.ПубликоватьНаСайте Тогда
		Возврат;
	КонецЕсли;

	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	Узлы.Ссылка КАК Узел
	|ИЗ
	|	ПланОбмена.ОбменССайтом КАК Узлы
	|ГДЕ
	|	НЕ Узлы.ЭтотУзел
	|	И НЕ Узлы.ПометкаУдаления");

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Источник.ОбменДанными.Получатели.Добавить(Выборка.Узел);
	КонецЦикла;

КонецПроцедуры

Подписка лучше кода в модуле объекта: типовой модуль не трогаем, обновления конфигурации проходят без конфликтов.

Через ПланыОбмена.ЗарегистрироватьИзменения

Если нужно зарегистрировать объект вне его записи — например, массово после изменения настроек узла, — используйте метод менеджера:

1С
// Регистрирует все элементы справочника Номенклатура в указанном узле.
Процедура ЗарегистрироватьНоменклатуруВУзле(Узел) Экспорт

	Если Не ЗначениеЗаполнено(Узел) Тогда
		ВызватьИсключение НСтр("ru = 'Не указан узел обмена'");
	КонецЕсли;

	ПланыОбмена.ЗарегистрироватьИзменения(Узел, Метаданные.Справочники.Номенклатура);

КонецПроцедуры

Вторым параметром можно передать ссылку, объект, набор записей регистра или объект метаданных (тогда регистрируются все данные этого вида). Первым — узел или массив узлов.

Не ищите узлы по жёстко зашитому коду (НайтиПоКоду("001")): при переносе в другую базу код узла может отличаться. Храните ссылку на узел в настройках или выбирайте узлы запросом по признакам.

Чтение зарегистрированных изменений

Таблица «Изменения» в запросе

Для каждого объекта из состава плана в языке запросов доступна таблица изменений:

1С
// Возвращает ссылки на номенклатуру, зарегистрированную к выгрузке в узел.
Функция ИзмененнаяНоменклатура(Узел) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Изменения.Ссылка КАК Ссылка,
	|	Изменения.НомерСообщения КАК НомерСообщения
	|ИЗ
	|	Справочник.Номенклатура.Изменения КАК Изменения
	|ГДЕ
	|	Изменения.Узел = &Узел";
	Запрос.УстановитьПараметр("Узел", Узел);

	Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

КонецФункции

Поле НомерСообщения пустое, если изменение ещё ни разу не отправлялось. У регистров в таблице изменений вместо ссылки — значения отбора набора записей (например, регистратор).

Запрос — чистое чтение: он не блокирует записи регистрации и подходит для интеграций, где вы сами формируете JSON и отправляете его через API.

ПланыОбмена.ВыбратьИзменения

Метод ВыбратьИзменения(Узел, НомерСообщения, Отбор) нужен для классического обмена сообщениями XML. Важно понимать его поведение: в процессе выборки он записывает номер сообщения в записи регистрации. Это запись в базу — со всеми блокировками. При активной работе пользователей это может вызывать ожидания.

1С
// Выгрузка изменений в XML-сообщение обмена (классическая схема).
Процедура ВыгрузитьИзмененияВФайл(Узел, ИмяФайла) Экспорт

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.ОткрытьФайл(ИмяФайла, "UTF-8");

	ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
	ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Узел);

	Выборка = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель,
		ЗаписьСообщения.НомерСообщения, Метаданные.Справочники.Номенклатура);
	Пока Выборка.Следующий() Цикл
		Данные = Выборка.Получить();
		ЗаписатьXML(ЗаписьXML, Данные);
	КонецЦикла;

	ЗаписьСообщения.ЗакончитьЗапись();
	ЗаписьXML.Закрыть();

КонецПроцедуры

Правило выбора:

  • нужен только список изменённых объектов — запрос к таблице Изменения;
  • нужен механизм квитирования по номерам сообщений — ВыбратьИзменения + ЗаписьСообщения.

Снятие регистрации

После того как получатель подтвердил приём, регистрацию снимают:

1С
// Снимает регистрацию с переданных объектов после подтверждения получателем.
Процедура ПодтвердитьВыгрузку(Узел, ВыгруженныеСсылки) Экспорт

	Для Каждого Ссылка Из ВыгруженныеСсылки Цикл
		ПланыОбмена.УдалитьРегистрациюИзменений(Узел, Ссылка);
	КонецЦикла;

КонецПроцедуры

Вторым параметром можно передать номер сообщения: тогда снимается регистрация всех изменений, отправленных в сообщениях до этого номера включительно. Это и есть квитирование в классической схеме: получатель сообщает номер принятого сообщения, отправитель снимает всё, что в нём было.

Важный нюанс: если объект изменили между выгрузкой и подтверждением, а вы снимаете регистрацию по ссылке, новая версия тоже «потеряется». Для интеграций через API я поэтому снимаю регистрацию по номеру сообщения или сверяю версию данных перед снятием.

План обмена в интеграциях с внешними системами

План обмена полезен не только для обмена между базами 1С. В интеграциях с сайтами, маркетплейсами и CRM я использую его как очередь изменений:

  1. Создаётся план обмена с узлом на каждую внешнюю систему.
  2. В состав включаются объекты, которые нужно передавать: номенклатура, цены, остатки, заказы.
  3. Подписки регистрируют изменения только при значимых условиях: например, цена изменилась, а не просто перезаписан документ.
  4. Регламентное задание раз в несколько минут читает таблицы Изменения, формирует JSON и отправляет порциями.
  5. После ответа 2xx от внешней системы регистрация снимается; при ошибке остаётся до следующего запуска.

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

Типичные ошибки

  • Регистрация обратно в узел-отправитель. Нет проверки ОбменДанными.Загрузка в подписке — объекты бесконечно ходят по кругу.
  • Поиск узла по зашитому коду. В копии базы код другой, регистрация молча не происходит.
  • Снятие регистрации до подтверждения. Сообщение потерялось — изменения не дойдут.
  • ВыбратьИзменения для простого чтения. Лишние записи и блокировки.
  • Огромные очереди регистрации. Узел не выгружается месяцами, таблица изменений растёт. Отключайте и очищайте неиспользуемые узлы.
План обмена отвечает на вопрос «что изменилось для этого получателя». Всё остальное — формат, транспорт, подтверждение — строится поверх него.

Обмены между базами 1С на этом механизме настраиваю в рамках услуги обмен между базами 1С; интеграции с сайтами и сервисами — в рамках интеграции 1С по API. Когда обменов много, их удобнее вести через интеграционную шину.

Итог

  • План обмена хранит узлы и регистрирует изменённые объекты для каждого из них.
  • Авторегистрация регистрирует во всех узлах; для условной регистрации используйте подписку ПередЗаписью и ОбменДанными.Получатели.
  • Читайте изменения запросом к таблице Изменения; ВыбратьИзменения пишет номера сообщений и может блокировать.
  • Регистрацию снимайте только после подтверждения получателем, лучше по номеру сообщения.