Как передать данные из ПКС в ПКО и решить проблему их потери при выгрузке

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

При разработке правил обмена в конфигурации «1С:Конвертация данных 2.0» (КД 2.0) часто возникает необходимость передать специфический контекст из одного правила в другое. Типичный сценарий: при выгрузке свойства объекта (ПКС) мы понимаем, что подчиненный объект должен быть создан или изменен особым образом. Для этого используются механизмы ИсходящиеДанные и ВходящиеДанные. Однако на практике разработчики часто сталкиваются с ситуацией, когда данные успешно передаются в ПКО, но «исчезают» при выполнении правил для свойств этого самого ПКО.

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

Стандартный механизм передачи данных через ИсходящиеДанные

Рассмотрим классическую схему передачи данных. Допустим, мы выгружаем документ «Договор» и в ПКС Владелец (который ссылается на справочник «Контрагенты») хотим передать флаг, указывающий на необходимость установки определенного реквизита у контрагента.

Шаг 1. Подготовка данных в ПКС

В правиле конвертации свойства (ПКС) в обработчике ПередВыгрузкой мы инициализируем структуру ИсходящиеДанные. Проанализируем пример кода:


// Обработчик ПКС "Владелец" -> ПередВыгрузкой
ИсходящиеДанные = Новый Структура("ПрочиеОтношения", Истина);

Шаг 2. Получение данных в ПКО

В правиле конвертации объекта (ПКО), на которое ссылается данное ПКС, эти данные автоматически попадают в коллекцию ВходящиеДанные. Чтобы ПКС внутри этого ПКО могли их использовать, необходимо в настройках ПКС установить флаг «Получать из входящих данных».

Разберем, как проверить наличие данных в обработчике ПКО ПередВыгрузкой:


// Обработчик ПКО "Контрагенты" -> ПередВыгрузкой
Если ТипЗнч(ВходящиеДанные) = Тип("Структура") Тогда
    Если ВходящиеДанные.Свойство("ПрочиеОтношения") Тогда
        Сообщить("Данные успешно получены в ПКО!");
    КонецЕсли;
КонецЕсли;

Почему данные могут пропадать: проблема двойной выгрузки

Часто программисты замечают странное поведение: в обработчике ПКО ПередВыгрузкой данные есть, а в ПКС внутри этого же ПКО — уже нет. Проанализируем причину. В системе КД 2.0 работает механизм кэширования. Если объект уже был однажды выгружен в рамках текущей сессии, система не будет выгружать его повторно, а просто вставит ссылку из кэша.

Ситуация осложняется при наличии циклических ссылок. Рассмотрим цепочку:

  1. Выгружается Договор.
  2. Для него нужно выгрузить Владельца (Партнера).
  3. У Партнера есть реквизит ОсновнойДоговор, который ссылается обратно на Договор.

В этот момент система может решить сначала выгрузить «пустую» ссылку на Партнера (только поля поиска), чтобы разорвать цикл. При этой «технической» выгрузке ВходящиеДанные могут отсутствовать. Когда же дело доходит до полноценной выгрузки Партнера через ваше ПКС с ИсходящимиДанными, система видит, что объект уже в кэше, и игнорирует новые данные.

Решение 1: Использование КлючаВыгружаемыхДанных

Чтобы заставить систему выгрузить объект повторно, именно с вашим набором входящих данных, можно использовать переменную КлючВыгружаемыхДанных. Мы можем сформировать уникальный ключ, который будет включать в себя не только ссылку на объект, но и значение нашего флага.

Посмотрим на пример реализации в ПКО ПередВыгрузкой:


// ПКО Контрагенты -> ПередВыгрузкой
Если ТипЗнч(ВходящиеДанные) = Тип("Структура") Тогда
    // Формируем уникальный ключ, чтобы объект выгрузился заново с этими данными
    КлючВыгружаемыхДанных = Строка(Источник.УникальныйИдентификатор()) + "_ПрочиеОтношения";
КонецЕсли;

Решение 2: Разрыв циклической связи

Выясним причину, по которой объект выгружается дважды. Чаще всего это происходит из-за того, что реквизит Владелец является полем поиска. Система пытается разрешить зависимости ссылок до того, как основной объект будет записан.

Рассмотрим вариант решения через отключение выгрузки мешающего реквизита. Если нам не критично переносить ОсновнойДоговор контрагента одновременно с самим контрагентом, мы можем отключить это ПКС или установить в нем условие Отказ = Истина;, если выгрузка идет в контексте нашей задачи.

Решение 3: Глобальные параметры конвертации

Если механизм ВходящиеДанные продолжает работать нестабильно из-за сложной логики правил, воспользуемся проверенным способом — коллекцией Параметры. Это глобальная структура, доступная во всех обработчиках.

Алгоритм действий:

  1. В ПКС «Владелец» сохраняем информацию в глобальный параметр (например, соответствие).
  2. В ПКО «Контрагенты» извлекаем её, ориентируясь на ссылку Источник.

Пример кода в ПКС:


// ПКС ПередВыгрузкой
Если Параметры.Свойство("ТаблицаНужныхПартнеров") = Ложь Тогда
    Параметры.Вставить("ТаблицаНужныхПартнеров", Новый Соответствие);
КонецЕсли;
Параметры.ТаблицаНужныхПартнеров.Вставить(Источник.Владелец, Истина);

Пример кода в ПКО контрагента:


// ПКО ПередВыгрузкой или ПКС ПрочиеОтношения
Если Параметры.Свойство("ТаблицаНужныхПартнеров") Тогда
    ЗначениеФлага = Параметры.ТаблицаНужныхПартнеров.Получить(Источник);
    Если ЗначениеФлага = Истина Тогда
        Значение = Истина;
    КонецЕсли;
КонецЕсли;

Рекомендации по отладке

Если данные не передаются, выполните следующие шаги:

Подводя итог, отметим, что наиболее стабильным способом передачи контекста в сложных правилах с рекурсией остается использование глобальных Параметров или явное управление КлючомВыгружаемыхДанных. Это гарантирует, что ваши данные не будут потеряны оптимизатором кэша КД 2.0.

← На главную