Как правильно настроить синхронизацию номенклатуры по дополнительному коду при обмене между УТ 10.3 и БП 2.0?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При организации обмена данными между конфигурациями «Управление торговлей 10.3» и «Бухгалтерия предприятия 2.0» разработчики часто сталкиваются с проблемой рассинхронизации справочника Номенклатура. Типичный сценарий: базы велись независимо, уникальные идентификаторы (UUID / ГУИД) элементов не совпадают, а сопоставление необходимо выполнить по какому-то специфическому реквизиту. Например, по реквизиту КодБухгалтерииНМД, который заполнен в УТ 10.3 лишь частично. Если данный код заполнен, поиск должен идти по нему, а если пуст — по наименованию и родителю номенклатуры.

В этой статье мы подробно разберем, почему популярные «быстрые» решения этой задачи (вроде отключения кэширования объектов) могут навредить производительности вашей системы, проанализируем ошибки в коде обработчиков и настроим правильный многошаговый поиск в правилах конвертации данных (КД 2.1).

Опасность использования флага «Не запоминать выгруженные объекты»

Часто в попытках заставить правила обмена сопоставлять объекты по сложной логике разработчики прибегают к «костылю»: включают в ПКО (Правила конвертации объектов) номенклатуры флаг «Не запоминать выгруженные объекты» на вкладке «Настройки». На первый взгляд это решает проблему, но в долгосрочной перспективе на реальной базе (например, объемом в 38 000 позиций) это приведет к серьезным техническим проблемам.

Давайте разберем, как работает кэширование по умолчанию. Когда объект (товар «А») выгружается в первый раз, его структура полностью записывается в XML-файл обмена. При последующих упоминаниях этого товара (например, в табличных частях документов продаж) выгружается только его ссылка (UUID). При загрузке импортер сопоставляет UUID и мгновенно подставляет нужный объект из своей памяти, не запуская повторно тяжелые алгоритмы поиска в базе данных.

Если мы взводим флаг «Не запоминать выгруженные объекты», кэширование полностью отключается. Это приводит к следующим последствиям:

  1. Лавинообразный рост XML-файла выгрузки: Карточка товара со всеми реквизитами будет полностью дублироваться в XML-файле столько раз, сколько раз этот товар встречается в строках документов. Размер файла может вырасти в десятки раз.
  2. Падение производительности: Для каждой строки каждого документа в базе-приемнике будет заново инициироваться и выполняться обработчик «Поля поиска». На больших объемах данных загрузка превратится в бесконечный процесс, нагружающий процессор и дисковую подсистему сервера.
  3. Риск зацикливания: Если у связанных ПКО (например, Номенклатура и Единицы измерения) одновременно включить данный флаг, это может увести КД в бесконечную рекурсию при выгрузке, что завершится аварийным завершением работы системы по превышению лимита выделенной памяти.

Почему не работал стандартный поиск: разбор ошибок

Рассмотрим типичные ошибки в обработчике Поля поиска, из-за которых платформа игнорирует попытки сопоставить объекты вручную.

Первая и самая частая ошибка — это игнорирование переменной ПрекратитьПоиск. Если вы выполняете ручной поиск с помощью запроса или методов менеджера справочника (например, НайтиПоКоду), то коду необходимо явно сообщить системе, что объект успешно найден и штатные алгоритмы сопоставления КД запускать больше не требуется. В противном случае платформа продолжит сопоставление по тем полям, для которых на уровне ПКС взведен флаг «Поиск», и затрет ваш результат пустой ссылкой.

Вторая ошибка связана с некорректной передачей пустого значения. Если в УТ 10.3 реквизит КодБухгалтерииНМД не заполнен, система все равно пытается выгрузить его (как пустое значение) и сопоставить объект по первому варианту поиска (по коду). Попытка сопоставить товар по пустому коду приводит к некорректной работе алгоритмов поиска.

Правильная реализация многошагового поиска

Давайте настроим синхронизацию корректно, сохранив все преимущества кэширования объектов Конвертации данных.

Шаг 1. Отключение поиска по уникальному идентификатору (UUID)

Поскольку базы исторически велись отдельно и ГУИДы номенклатуры в них заведомо отличаются, нам необходимо отключить стандартное сопоставление по идентификатору. Для этого откроем ПКО Номенклатура на вкладке «Основные» и снимем флаг «Искать объект приемника по внутреннему идентификатору...».

Шаг 2. Настройка ПКС (Правил конвертации свойств)

Перейдем на вкладку «Правила конвертации свойств» в ПКО Номенклатура. Нам необходимо отметить флаг «Поиск» для следующих свойств:

В ПКС для свойства Код в обработчике «Перед выгрузкой» напишем следующий код, который исключит передачу стандартного кода УТ, если специальный бухгалтерский код не заполнен:


Если ЗначениеЗаполнено(Источник.КодБухгалтерииНМД) Тогда
    Значение = Источник.КодБухгалтерииНМД;
Иначе
    // Если кода БП нет, очищаем значение, чтобы не передавать внутренний код УТ
    Значение = ""; 
КонецЕсли;

Шаг 3. Реализация поиска в обработчике «Поля поиска» ПКО

Для реализации логики «если заполнен КодБухгалтерииНМД — ищем по нему, иначе — по наименованию и родителю», мы задействуем механизм вариантов поиска КД. Откроем обработчик Поля поиска в ПКО Номенклатура и напишем высокопроизводительный код, использующий встроенный функционал платформы без лишних запросов к базе данных:


Если НомерВариантаПоиска = 1 Тогда
    // Вариант 1: Попытка поиска по коду БП, если он прилетел из источника
    КодДляПоиска = СвойстваПоиска["Код"];
    Если ЗначениеЗаполнено(КодДляПоиска) Тогда
        СтрокаИменСвойствПоиска = "Код, ЭтоГруппа";
    Иначе
        // Если код пустой, сразу перенаправляем алгоритм на следующий шаг поиска
        СтрокаИменСвойствПоиска = ""; 
    КонецЕсли;

ИначеЕсли НомерВариантаПоиска = 2 Тогда
    // Вариант 2: Если первый шаг не дал результатов или код был пуст, ищем по иерархии и наименованию
    СтрокаИменСвойствПоиска = "Наименование, Родитель, ЭтоГруппа";
КонецЕсли;

Альтернативный вариант поиска с ручным кодом

Если вам по какой-то причине необходимо выполнить поиск программно (например, обратиться напрямую к менеджеру справочника или выполнить специфический запрос), обязательно используйте переменную ПрекратитьПоиск. Ниже приведен пример правильной реализации ручного поиска в обработчике Поля поиска:


Если НомерВариантаПоиска = 1 Тогда
    КодДляПоиска = СвойстваПоиска["Код"];
    Если ЗначениеЗаполнено(КодДляПоиска) Тогда
        // Выполняем поиск элемента в базе БП по коду
        НайденнаяСсылка = Справочники.Номенклатура.FindbyCode(КодДляПоиска);
        Если Не НайденнаяСсылка.IsEmpty() Тогда
            СсылкаНаОбъект = НайденнаяСсылка;
            // КРИТИЧЕСКИ ВАЖНО: прекращаем дальнейший автоматический поиск платформы
            ПрекратитьПоиск = Истина; 
        КонецЕсли;
    КонецЕсли;

ИначеЕсли НомерВариантаПоиска = 2 Тогда
    // Если ручной поиск не дал результатов, передаем управление стандартному поиску по наименованию
    СтрокаИменСвойствПоиска = "Наименование, Родитель, ЭтоГруппа";
КонецЕсли;

Использование этого подхода гарантирует, что обмен данными будет проходить быстро, объем файла выгрузки останется минимальным, а номенклатура сопоставится без создания дублирующих позиций в базе-приемнике.

← На главную