При формировании начального образа подчиненного узла распределенной информационной базы (РИБ) разработчики и администраторы могут столкнуться с крайне необычным поведением: процесс выгрузки прерывается аварийной ошибкой вида «Поле объекта не обнаружено» (например, при обращении к реквизиту МагазинОтправитель или аналогичным полям конкретных документов). При анализе набора записей регистра накопления или сведений в точке останова отладчика обнаруживается парадоксальная ситуация: значение в НаборЗаписей.Отбор.Регистратор.Значение указывает на один документ, а в первой строке НаборЗаписей[0].Регистратор находится совершенно другой документ.
Разберем подробно, почему возникает подобное расхождение, как локализовать проблему и какими способами можно успешно сформировать начальный образ узла РИБ.
Проанализируем механику работы платформы при выполнении метода ПланыОбмена.СоздатьНачальныйОбраз(). Во время создания начального образа платформа осуществляет пакетную выгрузку таблиц движений регистров. При этом последовательно вызывается обработчик ПриОтправкеДанныхПодчиненному(), где в параметр ЭлементДанных передается очередной набор записей.
В некоторых релизах платформы (в частности, в ветке 8.3.9, например 8.3.9.1850) присутствует внутренняя ошибка платформенного итератора и сериализатора данных. При пакетной обработке движений регистров граница между наборами сбивается: значение фильтра в Отбор.Регистратор остается от предыдущего обработанного документа (например, Перемещение товаров), а внутренний массив строк уже заполняется движениями следующего документа (например, Отчет о розничных продажах).
Когда управление передается в типовые правила регистрации объектов (ПРО) библиотеки стандартных подсистем (БСП), алгоритм пытается определить тип документа через обращение к отбору:
ТипРегистратора = ТипЗнч(Объект.Отбор.Регистратор.Значение);
Так как тип определяется по старому регистратору, алгоритм заходит в ветку условий для документа Перемещение товаров и пытается прочитать специфичные для него реквизиты, которых у фактического документа в строках набора нет. В результате выполнение падает с ошибкой отсутствия реквизита.
Если оперативно сменить версию платформы невозможно, обойти ошибку выгрузки можно точечной доработкой правил регистрации данных для проблемного регистра (например, ТоварыОрганизаций).
Вместо проверки регистратора через свойства отбора набора записей обратимся напрямую к регистратору из первой строки набора. При этом обязательно учтем, что набор записей может оказаться пустым, иначе код упадет с ошибкой выхода индекса за границы массива.
Разберем пример безопасной проверки в обработчике правил регистрации:
Если Объект.Количество() > 0 Тогда
ТипРегистратора = ТипЗнч(Объект[0].Регистратор);
Иначе
ТипРегистратора = ТипЗнч(Объект.Отбор.Регистратор.Значение);
КонецЕсли;
Если ТипРегистратора = Тип("ДокументСсылка.ПеремещениеТоваров") Тогда
// Проверка условий выгрузки по реквизитам перемещения
// ...
КонецЕсли;
Важное предупреждение: данный обход снимает аварийную ошибку при выгрузке, однако не устраняет платформенную рассинхронизацию данных. Если платформа выгрузит строки под чужим отбором, в подчиненном узле движения могут записаться с искажением регистраторов, что в дальнейшем приведет к расхождениям в отчетах по остаткам. Поэтому после создания образа обязательно сверьте движения проблемного регистра между узлами.
Поскольку корень проблемы кроется в ошибке ядра платформы при формировании сериализуемого набора, наиболее правильным и надежным решением является смена версии 1С:Предприятия.
Если платформенный баг блокирует стандартное создание образа, можно инициализировать подчиненный узел РИБ альтернативными методами, при которых ошибка пакетной сериализации не проявляется.
Вариант А: Инициализация через копию базы данных
1С:Предприятие с отключенным обменом. Программно снимем признак главного узла через команду:
ПланыОбмена.УстановитьГлавныйУзел(Неопределено);
ЭтотУзел), назначив ему код и наименование нового магазина, а узлу центральной базы назначим признак главного узла:
УзелГлавного = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоКоду("ЦБ");
ПланыОбмена.УстановитьГлавныйУзел(УзелГлавного);
Вариант Б: Инициализация через пустую базу и стандартную синхронизацию
.cf), выгруженный из центральной базы.ПланыОбмена.УстановитьГлавныйУзел().ЗаписатьИзменения() ошибка перепутанных регистраторов платформы 8.3.9 не возникает, и база успешно заполнится всеми необходимыми данными.