При настройке правил обмена в конфигурации «Конвертация данных 2.0» часто возникает задача оптимизации объема передаваемых данных. Для справочника Номенклатура обычно настраивают режим выгрузки данных «Выгружать при необходимости», чтобы переносить только те позиции, которые непосредственно фигурируют в выгружаемом документе реализации (РТУ). Однако независимый регистр сведений ШтрихкодыНоменклатуры не связан с документом напрямую и не участвует в стандартной выборке объектов, из-за чего штрихкоды для переносимых позиций остаются в исходной базе. Разберем, как корректно выгрузить записи регистра вместе с документом, проанализируем поведение обработчиков событий и рассмотрим варианты оптимизации выгрузки.
При попытке разместить код выгрузки штрихкодов в обработчиках событий правила конвертации объекта (ПКО) Номенклатура разработчики нередко сталкиваются с тем, что код не выполняется. Проанализируем, почему это происходит:
ПередОбработкой, ПриВыгрузке) для номенклатуры не вызываются.Номенклатура установлен флаг «Выгружать только ссылку» или в обработчике взведено ВыгрузитьОбъект = Ложь, платформа не считывает тело объекта целиком, а выгружает лишь идентификатор (GUID). В таком случае обработчик ПКО ПослеВыгрузки для номенклатуры не отрабатывает вовсе.Рабочим и надежным решением является программная выгрузка штрихкодов непосредственно из документа в обработчике «ПослеВыгрузки» ПКО РеализацияТоваровУслуг. Однако прямой перебор строк табличной части и выполнение запроса к регистру на каждой итерации цикла создают существенную нагрузку на СУБД (проблема «запрос в цикле»).
Оптимизируем этот процесс: соберем массив уникальных ссылок на номенклатуру из документа, выполним один пакетный запрос к регистру сведений ШтрихкодыНоменклатуры и передадим найденные записи в функцию ВыгрузитьПоПравилу().
Рассмотрим пример кода в обработчике «ПослеВыгрузки» ПКО документа:
// Получаем уникальный массив номенклатуры из табличной части документа
ТаблицаТовары = Источник.Товары.Выгрузить();
ТаблицаТовары.Свернуть("Номенклатура");
МассивНоменклатуры = ТаблицаТовары.ВыгрузитьКолонку("Номенклатура");
Если МассивНоменклатуры.Количество() > 0 Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Штрихкоды.Штрихкод КАК Штрихкод,
| Штрихкоды.Номенклатура КАК Номенклатура,
| Штрихкоды.Характеристика КАК Характеристика,
| Штрихкоды.Упаковка КАК Упаковка
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
|ГДЕ
| Штрихкоды.Номенклатура В(&МассивНоменклатуры)";
Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СтруктураЗаписи = Новый Структура("Штрихкод, Номенклатура, Характеристика, Упаковка");
ЗаполнитьЗначенияСвойств(СтруктураЗаписи, Выборка);
// Выгружаем запись по правилу конвертации регистра сведений
ВыгрузитьПоПравилу(СтруктураЗаписи, , , , "ШтрихкодыНоменклатуры");
КонецЦикла;
КонецЕсли;
Если справочник Номенклатура выгружается полностью со всеми реквизитами (не только ссылкой), логичнее разместить код в обработчике «ПослеВыгрузки» ПКО Номенклатура. При этом важно помнить: платформа КД 2.0 автоматически отслеживает повторную выгрузку только для ссылочных данных. Независимый регистр сведений не имеет уникального идентификатора ссылки, поэтому одни и те же штрихкоды будут дублироваться в файле обмена при каждой повторной выгрузке позиции.
Разберем по шагам, как настроить кэширование обработанных позиций номенклатуры:
Параметры.Вставить("ОбработанныеШтрихкоды", Новый Соответствие);
Номенклатура проверяем наличие текущей ссылки в структуре кэша:
Если Параметры.ОбработанныеШтрихкоды[Источник] = Неопределено Тогда
Параметры.ОбработанныеШтрихкоды.Вставить(Источник, Истина);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Штрихкоды.Штрихкод КАК Штрихкод,
| Штрихкоды.Номенклатура КАК Номенклатура,
| Штрихкоды.Характеристика КАК Характеристика,
| Штрихкоды.Упаковка КАК Упаковка
|ИЗ
| РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
|ГДЕ
| Штрихкоды.Номенклатура = &Номенклатура";
Запрос.УстановитьПараметр("Номенклатура", Источник);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СтруктураЗаписи = Новый Структура("Штрихкод, Номенклатура, Характеристика, Упаковка");
ЗаполнитьЗначенияСвойств(СтруктураЗаписи, Выборка);
ВыгрузитьПоПравилу(СтруктураЗаписи, , , , "ШтрихкодыНоменклатуры");
КонецЦикла;
КонецЕсли;
Построчная выгрузка большого количества штрихкодов через ВыгрузитьПоПравилу() увеличивает размер итогового XML-файла за счет повторяющихся служебных тегов. В качестве альтернативы рассмотрим метод ВыгрузитьРегистр(), который позволяет выгрузить набор записей регистра целиком.
Для этого формируется таблица записей с отбором по выгружаемым позициям и передается в процедуру, что значительно ускоряет работу парсера XML на стороне приемника при чтении данных.
Обратим внимание на поведение данных при загрузке в целевой базе. Если выгрузка регистра выполняется не отдельными записями через менеджер записи, а набором записей, критически важно контролировать параметр Замещать:
Замещать = Истина неаккуратная запись набора с неполным составом измерений может полностью очистить существующие штрихкоды по другим аналитикам (например, по характеристикам или сериям).