Как правильно организовать работу с планом обмена в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Понимание механики номеров сообщений

Для начала проанализируем, как система отслеживает изменения. План обмена хранит информацию о зарегистрированных изменениях для каждого узла. Ключевым моментом является использование номеров сообщений. У каждого узла в плане обмена есть два важных свойства: Номер отправленного сообщения и Номер принятого сообщения.

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

  1. Определяем следующий номер сообщения (обычно это текущий НомерОтправленного + 1).
  2. Вызываем метод ВыбратьИзменения(), передавая этот номер. Система «помечает» все текущие изменения этим номером.
  3. Если в процессе выгрузки (пока мы формируем JSON или отправляем его по HTTP) в базе данных изменятся другие объекты, они получат номер 0 (или пустой номер), что позволит нам не удалить их ошибочно в конце сессии.

Реализация выборки изменений

Разберем, как программно инициировать процесс выборки. Основной метод, который нам понадобится — ВыбратьИзменения(). Он возвращает объект ВыборкаИзмененийПланаОбмена, который можно обойти в цикле.

Рассмотрим пример кода для инициации выгрузки:


// Получаем ссылку на узел, для которого выполняем выгрузку
УзелОбъекта = ПланыОбмена.Сайт.НайтиПоКоду("SITE_01");
Узел = УзелОбъекта.ПолучитьОбъект();

// Увеличиваем номер сообщения
Узел.НомерОтправленного = Узел.НомерОтправленного + 1;
Узел.Записать();

НовыйНомер = Узел.НомерОтправленного;

// Выбираем изменения, помеченные этим номером
Выборка = ПланыОбмена.ВыбратьИзменения(Узел.Ссылка, НовыйНомер);

Пока Выборка.Следующий() Цикл
    Данные = Выборка.Получить();
    
    // Здесь логика обработки данных (например, сериализация в JSON)
    Если ТипЗнч(Данные) = Тип("СправочникОбъект.Номенклатура") Тогда
        // Обработка номенклатуры
    ИначеЕсли ТипЗнч(Данные) = Тип("УдалениеОбъекта") Тогда
        // Обработка удаления объекта
    КонецЕсли;
КонецЦикла;

Важно помнить, что если в плане обмена участвует несколько типов объектов (например, Номенклатура и УпаковкиЕдиницыИзмерения), выборка вернет их все вперемешку. Нам нужно проверять тип полученных данных с помощью функции ТипЗнч().

Как избежать потери данных: решение проблемы параллельных изменений

Самый критичный момент — это пункт 2.2 из обсуждения: что делать, если данные изменились во время работы нашего кода? Если мы просто очистим всю регистрацию по узлу после успешной выгрузки, мы «затрем» те изменения, которые еще не были выгружены.

Для решения этой проблемы используется метод УдалитьРегистрациюИзменений(), в который передается номер сообщения. Рассмотрим логику подробнее:

Метод ПланыОбмена.УдалитьРегистрациюИзменений(Узел, НомерСообщения) удаляет только те записи из таблиц регистрации изменений, чей номер сообщения меньше или равен переданному значению. Те изменения, которые возникли во время выгрузки и не получили номер сообщения (или получили номер 0), останутся в плане обмена и будут выбраны при следующем запуске процесса.


// Этот блок кода выполняется только ПОСЛЕ подтверждения от сайта
Если ОтветСайта.КодСостояния = 200 Тогда
    // Удаляем изменения только для конкретного номера сообщения
    ПланыОбмена.УдалитьРегистрациюИзменений(Узел.Ссылка, НовыйНомер);
    
    // Обновляем номер принятого сообщения, чтобы синхронизироваться
    Узел.НомерПринятого = НовыйНомер;
    Узел.Записать();
КонецЕсли;

Использование запросов к виртуальным таблицам изменений

Хотя метод ВыбратьИзменения() прост в использовании, профессиональная разработка часто требует применения запросов. У каждого объекта, включенного в план обмена, появляется виртуальная таблица Изменения. Например, Справочник.Номенклатура.Изменения.

Проанализируем преимущества запросов к этим таблицам:

  1. Производительность: Мы можем соединить таблицу изменений с основной таблицей справочника прямо в запросе. Это позволит за один проход получить не только ссылку на измененный объект, но и все его реквизиты, цены и остатки.
  2. Фильтрация: Мы можем наложить дополнительные условия (например, выгружать только товары с определенным видом или те, что есть в наличии).
  3. Порционность: С помощью ключевого слова ВЫБРАТЬ ПЕРВЫЕ... в запросе легко реализовать порционную выгрузку (пачками по 100-500 элементов), что критично для стабильности работы веб-сервисов.

Пример запроса к таблице изменений:


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

Запрос.УстановитьПараметр("Узел", УзелСсылка);
Запрос.УстановитьПараметр("НомерСообщения", НовыйНомер);

Результат = Запрос.Выполнить();

Обработка удаления объектов

Часто программисты забывают о физическом удалении объектов из базы. Если пользователь удалит карточку номенклатуры (не установит пометку удаления, а именно удалит объект), в плане обмена зарегистрируется запись типа УдалениеОбъекта. Это специальный объект, который содержит только ссылку на удаленный элемент (которая уже не ведет ни на какие данные в базе).

При обходе выборки или анализе запроса обязательно учитывайте этот тип. Если вы получили УдалениеОбъекта, необходимо отправить на сайт команду DELETE или скрыть товар в каталоге, так как данных по нему в 1С больше не существует.

Транзакционность и целостность

Выясним причину возможных сбоев: если вы вызываете УдалитьРегистрациюИзменений до того, как сайт подтвердил получение данных, вы рискуете потерять информацию при обрыве связи. Правильный алгоритм всегда строится по принципу: Сначала подтверждение — потом очистка.

Если ваша конфигурация построена на БСП (Библиотека стандартных подсистем), рекомендуем использовать встроенную подсистему «Обмен данными». Она берет на себя большинство рутинных задач: логирование ошибок, мониторинг очереди изменений и работу с транспортными сообщениями. Однако понимание базовых механизмов работы ПланыОбмена, которое мы разобрали выше, необходимо любому разработчику для отладки и написания собственных легких интеграций.

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

← На главную