При настройке обмена данными через универсальный формат в "Конвертации данных 3.0" часто возникает задача: как отменить выгрузку конкретного объекта по определенному условию? В отличие от "Конвертации данных 2.0", где для этого было достаточно в обработчике установить параметр Отказ = Истина, в версии 3.0 этот механизм отсутствует. Проблема усложняется тем, что объект может быть зарегистрирован к обмену, но позже в нем изменятся данные, и он перестанет удовлетворять условиям выгрузки.
Рассмотрим несколько рабочих способов, как можно гибко управлять выгрузкой и отменять отправку ненужных объектов на разных этапах обмена, используя редактор кода для КД 3.0.
ИспользованиеПКОЭто один из штатных и наиболее предпочтительных методов. Его суть заключается в использовании специального обработчика события "При обработке" для правил конвертации объектов (ПКО). Этот обработчик срабатывает до того, как система начнет формировать данные объекта для выгрузки.
Внутри этого обработчика мы можем проанализировать данные исходного объекта и, если он не соответствует нашим критериям, запретить его выгрузку (писать код удобнее через VS Code). Делается это путем установки свойства структуры ИспользованиеПКО в значение Ложь.
Посмотрим на практический пример из типовой конфигурации "Управление торговлей". Задача — не выгружать документ "Возврат товаров поставщику", если у него пустая табличная часть "Товары", так как такой документ не пройдет проверку по XSD-схеме на стороне приемника.
Для этого (предварительно изучив реквизиты объекта метаданных) в модуле менеджера обмена создается процедура-обработчик:
Процедура ПОД_Документ_ВозвратТоваровПоставщику_ПриОбработке(ДанныеИБ, ИспользованиеПКО, КомпонентыОбмена)
// Проверка на наличие записей в табличной части "Товары".
// Если табличная часть пустая, то документ не выгружается.
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА КАК ЕстьЗаписи
|ИЗ
| Документ.ВозвратТоваровПоставщику.ВидыЗапасов КАК ВидыЗапасов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.АналитикаУчетаНоменклатуры КАК Аналитика
| ПО ВидыЗапасов.АналитикаУчетаНоменклатуры = Аналитика.КлючАналитики
|ГДЕ
| ВидыЗапасов.Ссылка = &Ссылка
| И (Аналитика.Номенклатура.ТипНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.Товар)
| ИЛИ Аналитика.Номенклатура.ТипНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.МногооборотнаяТара))"
);
Запрос.УстановитьПараметр("Ссылка", ДанныеИБ.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
// Если запрос не вернул ни одной строки, значит, ТЧ пуста.
Если Не Выборка.Следующий() Тогда
// Отменяем выгрузку документа
ИспользованиеПКО.Документ_ВозвратТоваровПоставщику_Отправка = Ложь;
КонецЕсли;
КонецПроцедуры
Ключевая строка здесь — ИспользованиеПКО.Документ_ВозвратТоваровПоставщику_Отправка = Ложь;. Обратите внимание, что имя свойства должно совпадать с именем соответствующего правила (автоматизировать генерацию идентификаторов можно через расширение для КД 3.0).
ПриОтправкеДанныхЭтот метод позволяет вмешаться в процесс на более позднем этапе, когда данные объекта уже подготовлены и преобразованы в формат XDTO, но еще не записаны в XML-файл сообщения. Для этого используется обработчик события "При отправке данных".
Если на этом этапе мы решим, что объект выгружать не нужно, мы можем просто "обнулить" его подготовленные данные. Для этого параметру ДанныеXDTO присваивается значение Неопределено.
Этот способ особенно удобен, когда решение об отмене выгрузки нужно принять на основе уже сформированных данных или сложных условий. Например, мы хотим добавить на форму договора флажок "Выгружать" и выгружать только те договоры, у которых он установлен.
Вот как будет выглядеть обработчик для правила конвертации договора:
Процедура ПКО_Справочник_ДоговорыКонтрагентов_Отправка_ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена, СтекВыгрузки)
мДоговор = ДанныеИБ; // В ДанныеИБ находится сам объект 1С
// Проверяем значение реквизита "Выгружать"
Если НЕ ОбщегоНазначения.ЗначениеРеквизитаОбъекта(мДоговор, "Выгружать") = Истина Тогда
// Если флаг не установлен, отменяем выгрузку
ДанныеXDTO = Неопределено;
Возврат;
КонецЕсли;
КонецПроцедуры
Как видно из примера, логика проста: проверяем условие и, если оно не выполнено, присваиваем ДанныеXDTO = Неопределено. Система, увидев пустое значение, просто пропустит этот объект и не включит его в сообщение обмена.
Этот же подход можно использовать для более сложных задач. Например, если нужно отключить выгрузку целого вида документов (допустим, "Заказ клиента"), которые могут выгружаться по ссылкам из других объектов, даже если их собственная регистрация отключена в правилах регистрации.
Отказ = Истина;.ПКО_Документ_ЗаказКлиента_Отправка_ПриОтправкеДанных пишем одну строку:
ДанныеXDTO = Неопределено;
Таким образом, любой "Заказ клиента", который попытается попасть в выгрузку (неважно, по прямой регистрации или по ссылке), будет отменен.
Это самый мощный, но и самый сложный метод, который дает полный контроль над процессом. Он заключается в том, чтобы вмешаться в саму процедуру выборки зарегистрированных изменений из плана обмена. Этот способ требует создания расширения конфигурации и перехвата стандартной процедуры с помощью аннотации &Вместо.
Разберем по шагам:
ОбменДаннымиXDTOСервер).ВыполнитьВыгрузкуЗарегистрированныхДанныхБезПакетнойРегистрации.&Вместо.ПланыОбмена.УдалитьРегистрациюИзменений().Посмотрим на пример кода, который выгружает только документы "Платежное поручение", а регистрацию всех остальных объектов удаляет:
&Вместо("ВыполнитьВыгрузкуЗарегистрированныхДанныхБезПакетнойРегистрации")
Процедура Расш1_ВыполнитьВыгрузкуЗарегистрированныхДанныхБезПакетнойРегистрации(КомпонентыОбмена, НомерСообщения, НачальнаяВыгрузкаДанных, УзелДляОбменаОбъект, СписокТипов)
УзелДляОбмена = КомпонентыОбмена.УзелКорреспондента;
ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелДляОбмена, НомерСообщения, СписокТипов);
Пока ВыборкаИзменений.Следующий() Цикл
Объект = ВыборкаИзменений.Получить();
// Наша логика фильтрации
Если ТипЗнч(Объект.Ссылка) = Тип("ДокументСсылка.ПлатежноеПоручение") Тогда
// Если условие выполняется, выгружаем объект стандартным механизмом
ВыгрузкаЗарегистрированногоОбъекта(КомпонентыОбмена, НачальнаяВыгрузкаДанных, УзелДляОбменаОбъект, Объект);
Иначе
// Если не выполняется - удаляем регистрацию, чтобы объект больше не попадал в выборку
ПланыОбмена.УдалитьРегистрациюИзменений(УзелДляОбмена, Объект.Ссылка);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот метод следует использовать с осторожностью, так как он грубо вмешивается в типовой механизм. Однако он незаменим в сложных случаях, когда логика фильтрации не может быть реализована на уровне обработчиков ПКО.