При разработке правил обмена в конфигурации «Конвертация данных 2.1» (КД) разработчики часто сталкиваются с ситуациями, когда свойство объекта не переносится напрямую из реквизита источника, а должно быть получено программно через запрос к связанным регистрам. В процессе настройки таких правил нередко возникают ошибки выполнения кода, связанные с неверно установленными флагами в ПКС или некорректной передачей структур данных. Разберем по шагам типовые ошибки и способы их устранения.
Проанализируем текст исходной ошибки обработки универсального обмена:
Ошибка получения свойства объекта из входящих данных. ОписаниеОшибки = Получение элемента по индексу для значения не определено.
Выясним причину такого поведения. Данное исключение возникает в универсальной обработке выгрузки XML в том случае, если в правиле конвертации свойства (ПКС) включен флаг «Получить из входящих данных», но при вызове правила параметр ВходящиеДанные не был инициализирован (имеет значение Неопределено). Механизм КД пытается обратиться к переданной коллекции по имени свойства как по индексу (ВходящиеДанные["ИмяСвойства"]) и падает с системным исключением.
Если реквизит рассчитывается кодом запроса непосредственно в обработчиках самого ПКС, значение не должно считываться из входящих данных.
Рассмотрим правильную настройку правила конвертации свойства:
Значение.Посмотрим на пример корректного кода в обработчике ПриВыгрузке ПКС, исключающего получение данных для групп номенклатуры:
Если Источник.ЭтоГруппа Тогда
Значение = "";
Иначе
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СоответствиеНоменклатурыЕГАИС.АлкогольнаяПродукция.Код КАК КодЕГАИС
|ИЗ
| РегистрСведений.СоответствиеНоменклатурыЕГАИС КАК СоответствиеНоменклатурыЕГАИС
|ГДЕ
| СоответствиеНоменклатурыЕГАИС.Номенклатура = &Номенклатура";
Запрос.УстановитьПараметр("Номенклатура", Источник);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Значение = Выборка.КодЕГАИС;
Иначе
Значение = "";
КонецЕсли;
КонецЕсли;
Рассмотрим следующую распространенную проблему: при выгрузке связанных регистров сведений из обработчика ПослеВыгрузкиОбъекта справочника Номенклатура с помощью функции ВыгрузитьПоПравилу возникает ошибка отсутствия поля Активность.
Проанализируем причину. При программной выборке данных из независимого непериодического регистра сведений через запрос (ВЫБРАТЬ *) системное свойство Активность в выборку не попадает. Однако в сгенерированном ПКО регистра сведений для свойства Активность по умолчанию создано ПКС, которое пытается прочитать это поле из источника (выборки запроса).
Для устранения ошибки выполним следующие действия:
Активность и снимаем с него флаг «Передавать данные в приемник» (отключаем ПКС) либо в обработчике ПередВыгрузкой данного ПКС явно указываем:
Значение = Истина;
Период и НомерСтроки, если регистр является непериодическим.Разберем, как правильно организовать выгрузку связанных данных (цены, штрихкоды, соответствия ЕГАИС) по текущему объекту номенклатуры. В обработчике ПослеВыгрузки ПКО Номенклатура можно использовать обход выборки запроса:
// Выгрузка соответствий ЕГАИС
ЗапросЕГАИС = Новый Запрос;
ЗапросЕГАИС.Текст =
"ВЫБРАТЬ
| Соответствие.АлкогольнаяПродукция КАК АлкогольнаяПродукция,
| Соответствие.Номенклатура КАК Номенклатура,
| Соответствие.КодНоменклатурыЕГАИС КАК КодНоменклатурыЕГАИС
|ИЗ
| РегистрСведений.СоответствиеНоменклатурыЕГАИС КАК Соответствие
|ГДЕ
| Соответствие.Номенклатура = &Номенклатура";
ЗапросЕГАИС.УстановитьПараметр("Номенклатура", Источник.Ссылка);
ВыборкаЕГАИС = ЗапросЕГАИС.Выполнить().Выбрать();
Пока ВыборкаЕГАИС.Следующий() Цикл
ВыгрузитьПоПравилу(ВыборкаЕГАИС, , , , "СоответствиеНоменклатурыЕГАИС");
КонецЦикла;
Важное замечание: Передавать объект типа РегистрСведенийНаборЗаписей напрямую первым параметром в ВыгрузитьПоПравилу нельзя, если ПКО настроено на запись регистра. Набор записей представляет собой коллекцию и не содержит реквизитов отдельной записи. Если используется набор записей, необходимо обходить его элементы в цикле:
НаборЗаписей = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Владелец.Установить(Источник.Ссылка);
НаборЗаписей.Прочитать();
Для Каждого Запись Из НаборЗаписей Цикл
ВыгрузитьПоПравилу(Запись, , , , "Штрихкоды");
КонецЦикла;
Если в базе-приемнике требуется выполнить поиск записи регистра по свойствам, которые формируются динамически или не имеют прямого источника, используем обработчик ПоляПоиска в ПКО приемника.
Посмотрим на пример алгоритма сопоставления:
Если ЗначениеЗаполнено(СвойстваПоиска["АлкогольнаяПродукция"]) ИЛИ ЗначениеЗаполнено(СвойстваПоиска["КодНоменклатурыЕГАИС"]) Тогда
СтрокаИменСвойствПоиска = "АлкогольнаяПродукция, КодНоменклатурыЕГАИС";
Иначе
ПрекратитьПоиск = Истина;
КонецЕсли;
Обратите внимание: обработчик ПоляПоиска выполняется на стороне базы-приемника. В структуре СвойстваПоиска содержатся уже сконвертированные значения полей приемника, а в строке СтрокаИменСвойствПоиска реквизиты перечисляются строго через запятую в соответствии с их именами в метаданных приемника.