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