При настройке обмена данными через «1С:Конвертация данных 2.0» (КД 2.0) программисты часто сталкиваются с ситуацией, когда объект уже зарегистрирован на узле плана обмена, но в момент выгрузки выясняется, что он еще «не готов» (например, документ не согласован или не заполнены важные дополнительные реквизиты). Если просто прописать Отказ = Истина в обработчиках КД, объект всё равно получит номер сообщения и при получении подтверждения от базы-приемника регистрация будет удалена. В итоге объект так и не попадет в другую базу, пока его снова не изменят вручную.
Разберем подробно, почему так происходит и как правильно реализовать механизм «отложенной» выгрузки несколькими способами.
Для начала проанализируем ситуацию на уровне платформы. Механизм планов обмена в 1С работает следующим образом:
ВыбратьИзменения(). В этот момент всем объектам, зарегистрированным на узле, присваивается номер текущего исходящего сообщения.Отказ = Истина, объект просто не записывается в XML-файл.Рассмотрим способы, которые позволят нам «обмануть» систему или использовать штатные механизмы более корректно.
Это самый быстрый способ, который можно реализовать непосредственно в правилах обмена. Суть заключается в том, чтобы после отказа от выгрузки тут же зарегистрировать объект на узле обмена заново. Повторная регистрация «сбрасывает» номер сообщения (устанавливает его в 0 или NULL), и объект попадет в следующую выборку.
Разберем по шагам реализацию в ПВД (Правила выгрузки данных) в обработчике «Перед выгрузкой»:
// Проверяем условие готовности объекта (например, статус согласования)
Если Объект.СтатусСогласования <> Перечисления.СтатусыСогласования.Согласован Тогда
// Отменяем текущую выгрузку
Отказ = Истина;
// Регистрируем объект заново, чтобы он не пропал из плана обмена
// Ссылка на узел часто доступна в параметрах обмена или её можно найти
УзелОбмена = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоНаименованию("УПП");
Если НЕ УзелОбмена.Пустая() Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Объект.Ссылка);
КонецЕсли;
КонецЕсли;
Важный нюанс: Этот метод заставляет систему выполнять лишнюю работу при каждом обмене. Если таких «недосогласованных» документов накопятся тысячи, время выгрузки может значительно вырасти, так как платформа будет каждый раз выбирать их и заново регистрировать.
Более правильный архитектурный подход — сделать так, чтобы объект вообще не регистрировался на плане обмена, пока не выполнено условие. Для этого используются Правила регистрации объектов (ПРО). Рассмотрим, как настроить фильтрацию на этапе регистрации.
Алгоритм действий следующий:
Пример кода в ПРО:
// Если документ не согласован, мы вообще запрещаем его регистрацию на узле
Если Объект.Состояние <> Перечисления.СостоянияДокументов.Согласован Тогда
Отказ = Истина;
КонецЕсли;
Плюс этого метода в том, что база не будет пытаться выгружать объект при каждом сеансе связи. Минус — если объект уже зарегистрирован, а потом его состояние изменилось на «не готов», нам придется вручную или программно снимать регистрацию.
Если у вас есть доступ к конфигуратору базы-источника, можно использовать наиболее надежный метод, предоставляемый платформой 1С. В модуле менеджера или объекта плана обмена существует обработчик ПриОтправкеДанных.
Рассмотрим, как это работает. В этом событии доступен параметр Игнорировать. Если установить его в Истина, платформа не просто пропустит объект, но и не будет считать его отправленным. Номер сообщения не будет привязан к объекту для этого сеанса.
Процедура ПриОтправкеДанных(ЭлементДанных, ОтправкаЭлемента)
// ЭлементДанных может быть УдалениемОбъекта, поэтому проверяем тип
Если ТипЗнч(ЭлементДанных) = Тип("ДокументОбъект.ВнутреннийДокумент") Тогда
Если ЭлементДанных.Согласован = Ложь Тогда
// Указываем платформе пропустить объект БЕЗ снятия регистрации
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот метод является самым «чистым» с точки зрения производительности и логики работы планов обмена.
Иногда решение о выгрузке зависит не от самого объекта, а от наличия других данных. Например, накладная должна выгружаться только после того, как по ней проведен складской ордер. Сама накладная при проведении ордера не меняется, а значит, регистрация на ней не появится автоматически.
В этом случае проанализируем стратегию «связанной регистрации»:
ПланыОбмена.ЗарегистрироватьИзменения(Узел, СсылкаНаНакладную);
Выясним, какой метод лучше выбрать в зависимости от ситуации:
ПриОтправкеДанных).Важно: При использовании перерегистрации (Способ 1) всегда следите за тем, чтобы не возникло «бесконечного цикла». Если объект никогда не сможет удовлетворить условию выгрузки, он будет «мусорить» в каждом пакете обмена, увеличивая время выполнения регламентного задания.