При разработке правил обмена в программе «1С:Конвертация данных 2.1» (КД 2.1) специалисты часто сталкиваются со сложными задачами трансформации данных. Типичный пример из швейной и производственной отраслей: в исходной конфигурации в табличной части документа содержатся два разных реквизита — Номенклатура (например, «Юбка») и Ткань (ссылка на тот же справочник Номенклатура с типом «Материал», например, «Ткань в горошек»). В базе-приемнике же требуется получить плоский список номенклатуры без разделения на ткани, где каждая позиция представляет собой готовое уникальное сочетание, например: «Юбка Ткань в горошек».
В этой статье мы подробно разберем, как решить эту задачу, проанализируем причины типичных ошибок при попытке сделать это стандартными средствами и рассмотрим готовые программные решения для реализации надежного регулярного обмена.
Разберем типичную ошибку, с которой сталкиваются разработчики при первой попытке реализовать подобную выгрузку. Попытка переопределить наименование «на лету» внутри стандартного правила конвертации свойств (ПКС) реквизита Номенклатура табличной части документа обычно приводит к тому, что в базу-приемник все равно загружается исходное наименование (без ткани) либо создается всего одна позиция номенклатуры.
Выясним причину этого поведения механизмов платформы 1С и КД 2.1. По умолчанию для справочника Номенклатура используется стандартное Правило Конвертации Объектов (ПКО), в настройках которого включен флаг «Искать объект приемника по внутреннему идентификатору (УИД)». Когда система выгружает документ, она записывает в XML-файл уникальный идентификатор исходной номенклатуры (например, УИД «Юбки»). При загрузке в приемник система видит этот УИД, находит по нему существующую «Юбку» в базе и сопоставляет строку документа именно с ней, полностью игнорируя измененное нами в файле обмена наименование.
Чтобы обойти это ограничение и заставить систему создавать новые элементы справочника для каждого сочетания, нам потребуется использовать специализированное вспомогательное ПКО с отключенным поиском по УИД и настроить передачу параметров через структуру ИсходящиеДанные.
Рассмотрим по шагам процесс настройки правил обмена для склеивания двух реквизитов табличной части источника в один элемент справочника-приемника.
В первую очередь создадим новое ПКО, которое будет отвечать исключительно за генерацию новых объединенных элементов номенклатуры в базе-приемнике.
Номенклатура_Склеенная.Номенклатура.Наименование.Наименование устанавливаем флаг «Получить из входящих данных» и отмечаем его галочкой в колонке «Поиск».Теперь перейдем к настройке ПКО нашего выгружаемого документа (например, «Отгрузка»). Нам нужно переопределить поведение системы при выгрузке реквизита Номенклатура в табличной части.
Найдем ПКС табличной части документа и откроем обработчик события «Перед выгрузкой» для реквизита Номенклатура. Напишем в нем следующий код:
// 1. Инициализируем структуру для передачи параметров в ПКО
ИсходящиеДанные = Новый Структура;
// 2. Склеиваем наименование основной номенклатуры и ткани в одну строку
НовоеНаименование = СокрЛП(ОбъектКоллекции.Номенклатура.Наименование) + " " + СокрЛП(ОбъектКоллекции.Ткань.Наименование);
ИсходящиеДанные.Вставить("Наименование", НовоеНаименование);
// При необходимости здесь можно передать и другие реквизиты (например, родительскую группу)
// ИсходящиеДанные.Вставить("Родитель", ОбъектКоллекции.Номенклатура.Родитель);
// 3. Динамически перенаправляем выгрузку на наше специализированное ПКО
ИмяПКО = "Номенклатура_Склеенная";
Проанализируем, как работает этот алгоритм. При выгрузке каждой строки табличной части документа система обращается к обработчику «Перед выгрузкой». Вместо стандартного правила выгрузки номенклатуры она видит указание использовать правило Номенклатура_Склеенная и передает туда подготовленную структуру ИсходящиеДанные. Внутри ПКО эти параметры становятся ВходящимиДанными, на основе которых формируется и ищется новый элемент в базе-приемнике.
Описанный выше метод поиска по наименованию отлично подходит для разового переноса остатков или справочников. Однако, если планируется регулярный и двусторонний обмен данными, поиск по наименованию («Юбка Ткань в горошек») несет в себе серьезные архитектурные риски. Если конечный пользователь в базе-приемнике решит изменить наименование позиции (например, исправит опечатку или сократит название), то при следующей выгрузке КД не сможет найти этот элемент и создаст очередной дубликат.
Чтобы гарантировать стабильность регулярного обмена, спроектируем надежную идентификацию на основе генерации синтетического (склеенного) кода. Рассмотрим, как реализовать этот подход:
Добавим в свойства ПКО Номенклатура_Склеенная реквизит Код. Для него устанавливаем флаг «Получить из входящих данных» и делаем его единственным полем поиска (при этом с наименования флаг поиска снимаем).
Перепишем алгоритм формирования исходящих данных в ПКС табличной части документа, добавив генерацию уникального кода на основе исходных кодов номенклатуры и ткани:
ИсходящиеДанные = Новый Структура;
// Формируем красивое наименование для пользователя
НовоеНаименование = СокрЛП(ОбъектКоллекции.Номенклатура.Наименование) + " " + СокрЛП(ОбъектКоллекции.Ткань.Наименование);
ИсходящиеДанные.Вставить("Наименование", НовоеНаименование);
// Генерируем уникальный склеенный код для однозначной идентификации в базах
СклеенныйКод = СокрЛП(ОбъектКоллекции.Номенклатура.Код) + "_" + СокрЛП(ОбъектКоллекции.Ткань.Код);
ИсходящиеДанные.Вставить("Код", СклеенныйКод);
ИмяПКО = "Номенклатура_Склеенная";
Использование синтетического кода вида 000000125_0000043 гарантирует абсолютную точность сопоставления. Даже если пользователи полностью переименуют номенклатуру в приемнике, система всегда однозначно определит нужную позицию по уникальному коду и обновит документ без создания лишних дублей.
Разберем важный теоретический нюанс работы конвертации. Требуется ли создавать отдельное ПВД для склеенной номенклатуры?
Если новая номенклатура должна создаваться только «по требованию» — то есть при проведении документов, в которых она фигурирует, — создавать отдельное ПВД не нужно. Объект приемника будет автоматически создан в момент обработки ссылки из табличной части документа.
Создание отдельного ПВД потребуется только в том случае, если перед вами стоит задача предварительно перенести весь возможный ассортимент сочетаний «Номенклатура + Ткань» независимо от того, участвовали они в документах или нет. В этом случае в ПВД вам потребуется написать запрос к информационной базе источника, получить все уникальные комбинации и программно выгрузить их с помощью метода ВыгрузитьПоПравилу().