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