Как программно установить автора в заказе клиента при создании через фоновое задание

Программист Управленческий учет IT и автоматизация бизнеса
← На главную

В процессе разработки механизмов автоматизации в «1С:Предприятие 8» часто возникает задача автоматического создания документов, например, «Заказов клиентов», через фоновые задания. Одной из неочевидных проблем в этой ситуации становится заполнение служебных реквизитов, таких как Автор. Зачастую программисты сталкиваются с тем, что при интерактивном запуске обработки код работает корректно, а в фоновом режиме реквизит Автор остается либо пустым, либо заполняется системным пользователем. В этой статье мы подробно разберем, почему так происходит и как правильно реализовать установку автора.

Анализ проблемы: почему автор не заполняется в фоновом задании

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

Основная причина перезаписи или незаполнения автора кроется в логике модуля объекта. В типовых решениях (УТ 11, ERP, КА) в процедуре ПередЗаписью или в соответствующих подписках на события часто встречается следующий код:


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

    Если ЭтоНовый() И Не ЗначениеЗаполнено(Автор) Тогда
        Автор = Пользователи.АвторизованныйПользователь();
    КонецЕсли;
КонецПроцедуры

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

Решение 1: Использование флага ОбменДанными.Загрузка

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

Рассмотрим пример кода, который позволит нам установить автора, идентичного менеджеру, в фоновом режиме:


// Создаем новый документ
ДокЗаказ = Документы.ЗаказКлиента.СоздатьДокумент();

// Устанавливаем основные реквизиты
ДокЗаказ.Дата = ТекущаяДата();
ДокЗаказ.Менеджер = Справочники.Пользователи.НайтиПоНаименованию("Иванов Иван");

// Включаем привилегированный режим для обхода ограничений прав
УстановитьПривилегированныйРежим(Истина);

// Устанавливаем флаг загрузки, чтобы игнорировать логику ПередЗаписью
ДокЗаказ.ОбменДанными.Загрузка = Истина;

// Присваиваем автора
ДокЗаказ.Автор = ДокЗаказ.Менеджер;

// Записываем документ
Попытка
    ДокЗаказ.Записать(РежимЗаписиДокумента.Запись);
Исключение
    ЗаписьЖурналаРегистрации("Ошибка создания заказа", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;

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

Важное примечание: Использование ОбменДанными.Загрузка = Истина отключает не только заполнение автора, но и проверку заполнения других обязательных полей, а также механизмы регистрации изменений для планов обмена. Будьте осторожны, если этот заказ должен сразу уйти в другую базу через синхронизацию.

Решение 2: Повторная перезапись объекта

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

Разберем этот метод по шагам:

  1. Создаем и записываем документ стандартным образом (в этот момент сработает системная логика и установит «неправильного» автора).
  2. Получаем объект по ссылке.
  3. Переопределяем реквизит Автор.
  4. Записываем объект повторно.

// Первая запись для создания ссылки
ДокЗаказ.Записать(); 

// Получаем объект заново для чистоты эксперимента
СсылкаНаЗаказ = ДокЗаказ.Ссылка;
ДокОбъект = СсылкаНаЗаказ.ПолучитьОбъект();

// Теперь документ уже не новый, и системные подписки могут пропустить это поле
ДокОбъект.Автор = ДокОбъект.Менеджер;
ДокОбъект.Записать();

Этот способ менее производителен, так как требует двух обращений к базе данных, но он позволяет корректно обойти условие Если ЭтоНовый() в программном коде конфигурации.

Решение 3: Учет типов данных и прав доступа

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

Проверьте следующие моменты:

Рекомендации по работе с БСП

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

Рассмотрим, как можно передать нужного пользователя в параметры сеанса (требуются права администратора):


// В начале выполнения фонового задания
ПараметрыСеанса.ТекущийПользователь = НужныйПользователь;

Подводя итог, отметим: для надежной установки автора в фоновом задании наиболее предпочтительным является использование Решения 1 с флагом ОбменДанными.Загрузка = Истина в сочетании с Привилегированным режимом. Это гарантирует, что никакие внутренние подписки на события или проверки модуля объекта не изменят установленное вами значение.

← На главную