Почему запрос во внешней обработке возвращает пустой результат при запуске регламентным заданием?

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

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

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

Причина 1. Несоответствие типов параметров при программном заполнении

В интерактивном режиме параметры запроса обычно выбираются пользователем из форм выбора — в обработку попадают строго типизированные ссылки: СправочникСсылка, ДокументСсылка или массивы ссылок. При программном заполнении параметров для регламентного задания часто допускаются скрытые ошибки типов:

  1. Передача строки вместо ссылки. Если в параметр запроса вместо ссылки на элемент справочника (например, склад или организацию) передать строку с его наименованием или строковое представление Уникального Идентификатора (UUID), функция ЗначениеЗаполнено() вернет Истина. Однако при выполнении запроса СУБД сравнивает ссылку со строкой. Условие отбора никогда не выполнится, и запрос вернет пустой результат без генерации исключения.
  2. Передача объекта СписокЗначений вместо массива. Если в условии запроса используется конструкция ГДЕ Поле В (&Список), а в параметр передан объект СписокЗначений, в элементах которого значения не инициализированы или имеют неверный тип, запрос отработает вхолостую. Для надежности в параметры запроса рекомендуется передавать обычный Массив ссылок.
  3. Иерархические отборы. При использовании конструкции В ИЕРАРХИИ (&Группа) передача пустой ссылки или ссылки другого типа метаданных также приведет к пустому результату без ошибок выполнения.

Проанализируем пример обязательной проверки типов перед установкой параметров в запрос:


// Проверяем не только заполненность, но и точный тип переданного значения
Если Не ЗначениеЗаполнено(ПараметрыВыгрузки.Склад) 
   Или ТипЗнч(ПараметрыВыгрузки.Склад) <> Тип("СправочникСсылка.Склады") Тогда
    ВызватьИсключение "Некорректно передан склад: ожидается Ссылка, получено: " + Строка(ТипЗнч(ПараметрыВыгрузки.Склад));
КонецЕсли;

Запрос.УстановитьПараметр("Склад", ПараметрыВыгрузки.Склад);

Причина 2. Особенности кэширования реквизитов внешней обработки

Частая ошибка архитектуры — использование реквизитов самого объекта внешней обработки для хранения рабочих параметров фонового задания. В платформе 1С:Предприятие при серверном вызове экземпляра внешней обработки (особенно если она подключена через подсистему БСП «Дополнительные отчеты и обработки») значения реквизитов объекта могут кэшироваться или инициализироваться значениями по умолчанию.

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

Посмотрим на правильную организацию сигнатуры метода в модуле объекта внешней обработки:


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

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

Причина 3. Ограничения прав (RLS), безопасный режим и параметры сеанса

Фоновое задание выполняется в отдельном серверном потоке под системной учетной записью или под пользователем, указанным в настройках регламентного задания. Здесь кроются две проблемы:

  1. Неинициализированные параметры сеанса: если в конфигурации включен механизм RLS (ограничение доступа на уровне записей), условия запроса неявно используют параметры сеанса (например, разрешенные группы доступа, склады, подразделения). В фоновом сеансе эти параметры могут быть пустыми, из-за чего RLS отсечет абсолютно все строки. Для проверки этой гипотезы можно временно убрать из текста запроса ключевое слово РАЗРЕШЕННЫЕ. Если запрос упадет с ошибкой нарушения прав доступа — дело именно в RLS.
  2. Безопасный режим: дополнительные обработки по умолчанию регистрируются в базе с признаком БезопасныйРежим = Истина. В этом режиме вызов УстановитьПривилегированныйРежим(Истина) игнорируется платформой, и обойти RLS не удастся. Если регламентная выгрузка должна собирать данные без учета ограничений прав, в функции СведенияОВнешнейОбработке() необходимо явно указать БезопасныйРежим = Ложь.

Рассмотрим применение привилегированного режима в коде:


УстановитьПривилегированныйРежим(Истина);
Выборка = Запрос.Выполнить().Выбрать();
УстановитьПривилегированныйРежим(Ложь);

Способы отладки регламентных заданий во внешних обработках

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

  1. Настройка автоматического подключения отладчика:

    В конфигураторе перейдите в меню Отладка — Подключение — Автоподключение и установите флажок напротив пункта Фоновые задания. Также для корректной остановки в клиент-серверном варианте в свойствах базы при запуске (или в диалоге настроек отладки) можно использовать параметр запуска РежимОтладки.

  2. Вызов экспортного метода через интерактивную форму:

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

  3. Логирование параметров через журнал регистрации:

    Если воспроизвести ошибку интерактивно не удается, следует вывести значения и типы параметров непосредственно в момент серверного вызова:

    
    ТекстЛога = СтрШаблон("Параметры запроса: Склад = %1 (Тип: %2), Период = %3", 
        ПараметрыЗапроса.Склад, 
        ТипЗнч(ПараметрыЗапроса.Склад), 
        ПараметрыЗапроса.Период);
    
    ЗаписьЖурналаРегистрации(
        "ВыгрузкаCSV", 
        УровеньЖурналаРегистрации.Информация, 
        , 
        , 
        ТекстЛога
    );
    

    Заглянув после старта регламентного задания в Журнал регистрации, можно сразу увидеть, какие типы данных были фактически переданы в запрос.

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

← На главную