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

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

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

Шаг 1: Подготовка глобального хранилища для ошибок

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

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


// Создаем таблицу для фиксации ошибок поиска
ТаблицаОшибокПоиска = Новый ТаблицаЗначений;
ТаблицаОшибокПоиска.Колонки.Добавить("КодИсточника");
ТаблицаОшибокПоиска.Колонки.Добавить("НаименованиеИсточника");
ТаблицаОшибокПоиска.Колонки.Добавить("ТипОбъекта");

// Помещаем таблицу в параметры, чтобы она была доступна везде
Параметры.Вставить("ОшибкиЗагрузки", ТаблицаОшибокПоиска);
Параметры.Вставить("ПрерватьЗагрузкуИзЗаОшибок", Ложь);

Также важно убедиться, что параметр добавлен на вкладке «Параметры» самой конвертации с установленной галочкой «При загрузке».

Шаг 2: Передача данных из источника (обработчик «Перед выгрузкой»)

Часто поля, по которым идет поиск (например, уникальный идентификатор или артикул), неинформативны для пользователя. Нам нужно передать «читаемые» данные (наименование, код) из источника в приемник, даже если они не участвуют в сопоставлении. Рассмотрим использование структуры ВходящиеДанные в ПКО (Правило конвертации объектов) Номенклатуры.

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


// Передаем данные для информационных сообщений в приемник
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("НаименованиеДляЛога", Источник.Наименование);
СтруктураДанных.Вставить("КодДляЛога", Источник.Код);

ВходящиеДанные = СтруктураДанных;

Шаг 3: Логика поиска и фиксация отсутствующих элементов

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

Рассмотрим пример кода, который выполняет поиск по коду, а при неудаче — фиксирует ошибку:


// Пытаемся найти объект стандартным способом по коду
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Ссылка
    |ИЗ
    |   Справочник.Номенклатура
    |ГДЕ
    |   Код = &Код И ЭтоГруппа = &ЭтоГруппа";

Запрос.УстановитьПараметр("Код", СвойстваПоиска["Код"]);
Запрос.УстановитьПараметр("ЭтоГруппа", СвойстваПоиска["ЭтоГруппа"]);

РезультатПоиска = Запрос.Выполнить().Выбрать();

Если РезультатПоиска.Следующий() Тогда
    СсылкаНаОбъект = РезультатПоиска.Ссылка;
Иначе
    // Объект не найден в приемнике!
    // Получаем данные, переданные через ВходящиеДанные
    КодИст = "";
    НаимИст = "";
    
    Если ВходящиеДанные <> Неопределено Тогда
        ВходящиеДанные.Свойство("КодДляЛога", КодИст);
        ВходящиеДанные.Свойство("НаименованиеДляЛога", НаимИст);
    КонецЕсли;

    // Добавляем запись в нашу глобальную таблицу ошибок
    НоваяСтрока = Параметры.ОшибкиЗагрузки.Добавить();
    НоваяСтрока.КодИсточника = ?(ЗначениеЗаполнено(КодИст), КодИст, СвойстваПоиска["Код"]);
    НоваяСтрока.НаименованиеИсточника = НаимИст;
    НоваяСтрока.ТипОбъекта = "Номенклатура";

    // Устанавливаем флаг критической ошибки
    Параметры.ПрерватьЗагрузкуИзЗаОшибок = Истина;
    
    // Сообщаем системе, что поиск завершен (объект не найден)
    СсылкаНаОбъект = Неопределено;
    ПрекратитьПоиск = Истина;
КонецЕсли;

Важный нюанс: использование ПрекратитьПоиск = Истина и СсылкаНаОбъект = Неопределено гарантирует, что система не будет пытаться создать новый объект, если в правилах стоит настройка «Не создавать новых объектов».

Шаг 4: Отмена загрузки всей посылки данных

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

Проанализируем ситуацию: если наш флаг Параметры.ПрерватьЗагрузкуИзЗаОшибок установлен в значение Истина, мы должны запретить загрузку любых последующих объектов.


Если Параметры.ПрерватьЗагрузкуИзЗаОшибок Тогда
    Отказ = Истина;
    // Можно вывести сообщение в журнал регистрации или в окно сообщений
    Сообщить("Загрузка объекта " + ТипЗнч(Объект) + " отменена из-за отсутствия нормативно-справочной информации.");
КонецЕсли;

Если же стоит задача прервать загрузку немедленно и полностью (откатив транзакцию), можно использовать более жесткий метод в обработчике «При загрузке» или «Поля поиска»:


Если ОбъектНеНайден Тогда
    ВызватьИсключение "Критическая ошибка: Номенклатура '" + НаимИст + "' не найдена. Загрузка прервана.";
КонецЕсли;

Однако стоит помнить, что ВызватьИсключение прервет выполнение обработки немедленно, и финальные сообщения могут не успеть вывестись в удобном виде. Поэтому вариант с установкой флага Отказ = Истина в обработчике «Перед загрузкой объекта» является более гибким.

Шаг 5: Вывод итогового отчета пользователю

После завершения цикла загрузки (или попытки загрузки) нам нужно показать пользователю список всех проблемных элементов. Рассмотрим обработчик «После загрузки данных». Этот код выполнится один раз в самом конце.


Если Параметры.ОшибкиЗагрузки.Количество() > 0 Тогда
    Сообщить("--- ОШИБКИ ЗАГРУЗКИ: НЕ НАЙДЕНЫ ЭЛЕМЕНТЫ В ПРИЕМНИКЕ ---");
    Для Каждого СтрОшибка Из Параметры.ОшибкиЗагрузки Цикл
        ТекстСообщения = СтрШаблон("Тип: %1, Код источника: %2, Название: %3", 
                                    СтрОшибка.ТипОбъекта, 
                                    СтрОшибка.КодИсточника, 
                                    СтрОшибка.НаименованиеИсточника);
        Сообщить(ТекстСообщения);
    КонецЦикла;
    Сообщить("---------------------------------------------------------");
КонецЕсли;

Дополнительные рекомендации

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

Таким образом, мы построили надежную систему контроля: собираем данные об отсутствующих объектах через ВходящиеДанные, фиксируем их в глобальной ТаблицеЗначений в обработчике Поля поиска и блокируем дальнейшую загрузку через флаг в обработчике Перед загрузкой объекта. Этот подход минимизирует появление документов с «пустыми» реквизитами в базе-приемнике.

← На главную