Почему один и тот же код в 1С работает по-разному во внешней обработке и через механизм БСП

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

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

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

Различие 1: Ограничение прав на уровне записей (RLS)

Самая распространенная причина — механизм RLS (Record Level Security). В типовых конфигурациях, таких как Управление торговлей 11, ERP или Комплексная автоматизация, права доступа настроены очень тонко. Когда вы запускаете обработку интерактивно (через Файл — Открыть), она выполняется в контексте вашего текущего сеанса с вашими текущими правами.

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

Решение: Для исправления ситуации необходимо явно использовать привилегированный режим в модуле объекта обработки. Рассмотрим пример:


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
    
    // Устанавливаем привилегированный режим, чтобы игнорировать RLS
    УстановитьПривилегированныйРежим(Истина);
    
    // Вызов основной логики обработки
    СнятьРезервыПоЗаказам();
    
    УстановитьПривилегированныйРежим(Ложь);
    
КонецПроцедуры

Важно помнить, что УстановитьПривилегированныйРежим(Истина) сработает только в том случае, если в карточке дополнительной обработки выключен безопасный режим. В безопасном режиме использование этого метода игнорируется платформой.

Различие 2: Контекст выполнения и параметры сеанса

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

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

Для проверки того, запущен ли код в фоновом задании, можно использовать следующий прием:


Если ПараметрыСеанса.ТекущийПользователь.Пустая() Тогда
    ЗаписьЖурналаРегистрации("Внимание. Обработка запущена в контексте, где не определен пользователь!",
        УровеньЖурналаРегистрации.Предупреждение);
КонецЕсли;

Различие 3: Безопасный режим и профили безопасности

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

Если ваша обработка в «свободном» режиме вызывает методы, требующие повышенных прав, а внутри БСП она ограничена профилем безопасности, выполнение прервется или пойдет по иному сценарию. Выясним причину, проверив настройки в разделе Администрирование — Печатные формы, отчеты и обработки. Убедитесь, что для обработки разрешен полный доступ.

Различие 4: Директивы препроцессора

Часто разработчики копируют код из глобальных модулей или модулей менеджера, где встречаются директивы типа #Если Сервер Тогда или #Если ТолстыйКлиентОбычноеПриложение Тогда. Рассмотрим, как это влияет на работу:

Внешняя обработка, открытая интерактивно, может работать в контексте Толстого клиента, если это разрешено настройками. Но при выполнении через БСП код всегда компилируется на стороне Сервера. Если важная часть логики (например, формирование временных таблиц запроса) была обернута в условие, которое не выполняется на сервере, запрос отработает некорректно.

Совет: Проверьте модуль объекта вашей обработки на наличие условий препроцессора. Для кода, работающего в БСП, лучше минимизировать использование этих инструкций или убедиться, что основной алгоритм доступен для #Если Сервер.

Различие 5: Кэширование метаданных в справочнике

Иногда причина кроется не в коде, а в платформенном кэше. Когда вы загружаете файл во внешнюю обработку БСП, система сохраняет его в базе данных как двоичные данные. При запуске эти данные извлекаются и компилируются во временный объект.

Бывают случаи, когда при обновлении файла обработки в справочнике 1С продолжает «видеть» старую версию кода из-за кэша сервера приложений. Посмотрим, как это лечится:

  1. Полностью удалите запись из справочника Дополнительные отчеты и обработки.
  2. Очистите серверный кэш (удалите содержимое папок snccntx и reg_1541 в каталоге данных сервера).
  3. Загрузите обработку заново в новую карточку.

Рекомендация по написанию универсального кода

Чтобы избежать расхождений, рекомендуется проектировать модуль объекта обработки так, чтобы он был максимально независим от окружения. Используйте структуру ПараметрыВыполнения, которую передает БСП, и всегда проверяйте доступность данных через УстановитьПривилегированныйРежим, если обработка должна работать с данными всей базы, невзирая на ограничения конкретного пользователя.

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


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

Такой подход гарантирует, что запрос вернет одинаковый набор данных вне зависимости от того, запущен он вручную администратором или регламентным заданием через БСП под учетной записью с ограниченными правами.

← На главную