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