При разработке расширений или доработке типовых конфигураций (таких как 1С:Управление торговлей 11, ERP, Комплексная автоматизация) часто возникает задача автоматического заполнения полей "Автор", "Ответственный" или "Менеджер" — для этого есть готовое расширение для заполнения реквизитов 1С. Поскольку современные конфигурации строятся на базе Библиотеки Стандартных Подсистем (БСП), использование старых методов или прямых обращений к параметрам сеанса не всегда является лучшей практикой. Рассмотрим правильные способы получения текущего пользователя и связанного с ним сотрудника.
В типовых конфигурациях существует различие между Пользователем Информационной Базы (учетная запись для входа в Конфигуратор/Предприятие) и элементом справочника Пользователи (сущность, используемая в документах и отчетах). Нам практически всегда нужна ссылка на элемент справочника.
Разберем методы, предоставляемые общими модулями БСП, в зависимости от контекста выполнения кода.
Для получения ссылки на текущего пользователя используйте функцию общего модуля Пользователи. Это наиболее надежный метод для анализа прав, так как он обрабатывает ситуации с неинициализированными параметрами сеанса.
// Возвращает ссылку на справочник "Пользователи" или "ВнешниеПользователи"
ТекущийПользовательСсылка = Пользователи.ТекущийПользователь();
Если вам необходимо получить пользователя непосредственно в форме (например, при открытии) для проверки прав доступа, используйте клиентский общий модуль:
// Работает на клиенте
ТекущийПользовательСсылка = ПользователиКлиент.ТекущийПользователь();
В некоторых версиях БСП существует универсальный метод в модуле ПользователиКлиентСервер, однако в последних редакциях рекомендуется использовать разделение на Клиент/Сервер, описанное выше. Тем не менее, вы можете встретить или использовать:
ПользователиКлиентСервер.ТекущийПользователь();
Важно понимать механику работы. Данные о текущем пользователе хранятся в Параметрах Сеанса. Это специальные переменные, которые живут, пока активен сеанс пользователя.
Основной параметр: ПараметрыСеанса.ТекущийПользователь.
Почему лучше использовать функции БСП (Пользователи.ТекущийПользователь()), а не читать параметр сеанса напрямую? Функции общих модулей часто содержат механизмы кэширования (модуль повторного использования) и проверки заполнения. Если по какой-то причине параметр сеанса пуст (например, при фоновом запуске), функция может попытаться его инициализировать или корректно вернуть пустую ссылку, предотвращая ошибку кода.
Важное замечание: Не путайте Пользователи.ТекущийПользователь() и ПользователиИнформационнойБазы.ТекущийПользователь(). Второй метод обращается к ядру платформы и возвращает объект администрирования (логин, пароль, роли), который нельзя записать в реквизит документа.
Часто в документы (например, в "Реализацию товаров и услуг" или "Заказ клиента") нужно подставить не просто пользователя (системную учетку), а конкретного Сотрудника (Менеджера, Кладовщика) (поможет автоматическая подстановка подписей и факсимиле сотрудников). Пользователь и Сотрудник — это разные справочники.
Разберем, как правильно найти сотрудника, связанного с текущим пользователем. Существует несколько подходов, рассмотрим их от простого к правильному.
В конфигурациях вроде УТ 11 есть регистр сведений (обычно СотрудникиПользователя или аналогичный), который хранит прямую связь. Это самый быстрый и надежный способ.
Рассмотрим пример функции для получения сотрудника:
&НаСервереБезКонтекста
Функция ПолучитьСотрудникаПоТекущемуПользователю()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| СотрудникиПользователя.Сотрудник КАК Сотрудник
|ИЗ
| РегистрСведений.СотрудникиПользователя КАК СотрудникиПользователя
|ГДЕ
| СотрудникиПользователя.Пользователь = &Пользователь";
// Используем стандартную функцию БСП для получения ссылки на пользователя
Запрос.УстановитьПараметр("Пользователь", Пользователи.ТекущийПользователь());
Выборка = Запрос.Выполнить().Выбрать();
// Если запись есть, возвращаем сотрудника, иначе - пустую ссылку
Сотрудник = ?(Выборка.Следующий(), Выборка.Сотрудник, Справочники.Сотрудники.ПустаяСсылка());
Возврат Сотрудник;
КонецФункции
В более сложных системах (ЗУП, комплексные ERP) связь строится через справочник ФизическиеЛица.
Цепочка выглядит так: Пользователь -> Физическое Лицо -> Сотрудник.
Это связано с тем, что один человек (Физлицо) может работать по совместительству на двух должностях (два элемента справочника Сотрудники), но под одной учетной записью (один Пользователь).
Иногда разработчики пытаются найти сотрудника по совпадению наименования с пользователем. Это ненадежный метод, так как ФИО могут меняться, быть неполными или совпадать у разных людей.
// Плохой пример, старайтесь избегать такого подхода
Сотрудник = Справочники.Сотрудники.НайтиПоНаименованию(Пользователи.ТекущийПользователь().Наименование);
Обратите внимание на конструкцию, использованную в примере выше:
Сотрудник = ?(Выборка.Следующий(), Выборка.Сотрудник, Справочники.Сотрудники.ПустаяСсылка());
Метод Выборка.Следующий() возвращает тип Булево. Если данных в выборке нет (запрос ничего не нашел), метод вернет Ложь и не вызовет исключения (ошибки). Поэтому проверка Результат.Пустой() перед вызовом Следующий() технически не обязательна, если вы корректно обрабатываете результат Ложь.
Если вы хотите, чтобы при создании документа или изменении ключевых полей (например, Партнера) менялся Ответственный или Менеджер, код следует размещать в обработчиках событий формы или объекта — для этого подойдёт универсальная настройка автозаполнения документов.
Рассмотрим алгоритм действий в расширении для формы документа:
ПриСозданииНаСервере добавьте код для начального заполнения (если это новый документ).ПриИзменении поля "Клиент" (или другого влияющего реквизита) добавьте вызов функции пересчета менеджера.Пример кода для формы:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Проверяем, что это новый объект
Если Объект.Ссылка.Пустая() Тогда
// Заполняем текущим пользователем (если реквизит Ответственный хранит Пользователя)
Объект.Ответственный = Пользователи.ТекущийПользователь();
// Если нужен сотрудник (и есть соответствующая функция)
// Объект.Менеджер = ПолучитьСотрудникаПоТекущемуПользователю();
КонецЕсли;
КонецПроцедуры
Используя эти методы, вы гарантируете совместимость вашего кода с механизмами БСП и корректную работу в клиент-серверной архитектуре.