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