Как в Конвертации данных 2 отменить загрузку номенклатуры, если не найден вид номенклатуры?

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

При настройке правил обмена в конфигурации «Конвертация данных 2» разработчики часто сталкиваются с задачей условной загрузки: если подчиненный или зависимый справочник не найден в базе-приемнике, создавать новый элемент не нужно, а загрузку основного объекта требуется отменить. Типичный пример — перенос номенклатуры, у которой обязательно должен быть заполнен корректный вид номенклатуры.

Однако при наивной реализации через стандартную проверку и установку отказа объект все равно может создаваться, содержа в реквизите битую ссылку вида <Объект не найден>. Выясним причину такого поведения платформы и разберем по шагам, как правильно организовать проверку.

Почему не работает проверка в обработчике «При загрузке»

Проанализируем механику работы обработчиков событий в правилах конвертации объектов (ПКО):

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

Почему «ЗначениеЗаполнено» пропускает битые ссылки

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

Рассмотрим рабочие способы решения этой проблемы.

Способ 1. Проверка существования через функцию БСП

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


Если НЕ ЗначениеЗаполнено(Объект.ВидНоменклатуры) 
   Или НЕ ОбщегоНазначения.СсылкаСуществует(Объект.ВидНоменклатуры) Тогда
    Отказ = Истина;
КонецЕсли;

Функция ОбщегоНазначения.СсылкаСуществует() выполняет быстрый запрос к таблице базы данных и возвращает Ложь, если ссылки физически нет в базе приемника. В результате запись номенклатуры будет корректно отменена.

Способ 2. Проверка через метод «ПолучитьОбъект»

Если в базе-приемнике нет БСП или модуль ОбщегоНазначения недоступен, можно воспользоваться универсальным методом платформы. Для битой ссылки метод ПолучитьОбъект() возвращает Неопределено.

Разберем пример кода для обработчика «После загрузки» в ПКО «Номенклатура»:


Если НЕ ЗначениеЗаполнено(Объект.ВидНоменклатуры) 
   Или Объект.ВидНоменклатуры.ПолучитьОбъект() = Неопределено Тогда
    Отказ = Истина;
КонецЕсли;

Важный момент: вызов ПолучитьОбъект() считывает из базы данных все поля элемента, что при массовом переносе десятков тысяч позиций номенклатуры может вызывать просадку по производительности. Для больших объемов данных предпочтительнее использовать точечный запрос.

Способ 3. Оптимизированная проверка прямым запросом

При пакетном переносе больших массивов номенклатуры целесообразно выполнить легковесный запрос по ссылке в обработчике «После загрузки»:


Если ЗначениеЗаполнено(Объект.ВидНоменклатуры) Тогда
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    1
        |ИЗ
        |    Справочник.ВидыНоменклатуры КАК Спр
        |ГДЕ
        |    Спр.Ссылка = &Ссылка";
    Запрос.УстановитьПараметр("Ссылка", Объект.ВидНоменклатуры);
    
    Если Запрос.Выполнить().Пустой() Тогда
        Отказ = Истина;
    КонецЕсли;
Иначе
    Отказ = Истина;
КонецЕсли;

Способ 4. Подстановка значения по умолчанию или очистка

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


Если ЗначениеЗаполнено(Значение) И Значение.ПолучитьОбъект() = Неопределено Тогда
    // Вариант 1: Очистить реквизит до пустой ссылки
    Значение = Справочники.ВидыНоменклатуры.ПустаяСсылка();
    
    // Вариант 2: Заполнить предопределенным или дефолтным элементом
    // Значение = Справочники.ВидыНоменклатуры.Товар;
КонецЕсли;

Посмотрим на результат: номенклатура успешно запишется в базу данных, а битая ссылка будет заменена на корректное значение либо очищена.

← На главную