При разработке нетиповых конфигураций или доработке существующих систем часто возникает потребность хранить дополнительную информацию о пользователях, которая не предусмотрена стандартными объектами 1С. Например, мы хотим добавить отделы, должности, контактные данные или права, специфичные для нашей конфигурации. Для этого мы создаем свой справочник, который обычно называем «Пользователи». Однако возникает задача: как сопоставить системного пользователя информационной базы (далее — ПользовательИБ) с соответствующим элементом нашего пользовательского справочника «Пользователи»? Особенно актуален этот вопрос, если мы хотим решить его без использования Библиотеки стандартных подсистем (БСП), которая предлагает готовые механизмы для этого.
Давайте подробно разберем, как реализовать такую связь в 1С без БСП, рассмотрев несколько подходов и механизмов их реализации.
Существует два основных способа установления связи между системным ПользователемИБ и элементом вашего справочника Пользователи: по имени пользователя и по уникальному идентификатору (УИД).
Этот метод является одним из самых древних и простых в реализации. Он основан на том, что у каждого системного пользователя информационной базы есть имя, которое мы можем получить и использовать для поиска соответствующего элемента в нашем справочнике.
Получение текущего пользователя ИБ: В любой точке кода, где вам нужен текущий пользователь (например, в модуле сеанса, в обработчике события ПриНачалеРаботыСистемы), мы можем получить объект текущего системного пользователя с помощью функции ПользователиИнформационнойБазы.ТекущийПользователь().
Поиск элемента справочника по имени: После получения объекта ПользовательИнформационнойБазы, мы можем извлечь его имя и использовать его для поиска элемента в нашем справочнике Пользователи. Для этого нам понадобится метод НайтиПоНаименованию() или НайтиПоИмени(), если в вашем справочнике есть реквизит с таким именем.
Рассмотрим пример кода, как это можно сделать. Предположим, у нас есть справочник Пользователи, и его основным реквизитом для поиска мы считаем Наименование, которое соответствует имени системного пользователя.
&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
// Получаем объект текущего системного пользователя
ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ТекущийПользовательИБ <> Неопределено Тогда
// Получаем имя системного пользователя
ИмяПользователяИБ = ТекущийПользовательИБ.Имя;
// Ищем элемент в нашем справочнике "Пользователи" по имени
// Предполагаем, что у справочника есть реквизит "Наименование"
// или мы используем стандартное Наименование
СсылкаНаПользователя = Справочники.Пользователи.НайтиПоНаименованию(ИмяПользователяИБ);
Если СсылкаНаПользователя = Неопределено Тогда
// Если элемент не найден, его можно создать (рассмотрим это позже)
Сообщить("Элемент справочника 'Пользователи' для пользователя '" + ИмяПользователяИБ + "' не найден.");
Иначе
// Устанавливаем найденный элемент в параметр сеанса для дальнейшего использования
ПараметрыСеанса.ТекущийПользовательСправочника = СсылкаНаПользователя;
Сообщить("Связь с элементом справочника установлена: " + СсылкаНаПользователя.Наименование);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Обратите внимание на сообщение 3 в теме форума, где предлагается использовать ПараметрыСеанса.Пользователь = Справочники.Пользователи.НайтиПоИмени(ПользователиИнформационнойБазы.ТекущийПользователь(), Истина);. Этот пример показывает использование метода НайтиПоИмени, который может быть методом самого справочника, если вы его определили, или же стандартным методом поиска по наименованию. Важно помнить, что Истина в качестве второго параметра указывает на точный поиск.
Недостатки подхода по имени: Главный недостаток этого метода заключается в его негибкости. Если имя системного ПользователяИБ будет изменено (например, через конфигуратор), то связь с элементом справочника нарушится. Вам придется либо вручную обновлять наименование в справочнике, либо реализовывать сложный механизм отслеживания изменений, что делает этот подход менее надежным.
Наиболее надежный и рекомендуемый способ связать ПользователяИБ с вашим справочником "Пользователи" — это использование уникального идентификатора (УИД). У каждого системного пользователя информационной базы есть свой УникальныйИдентификатор, который является стабильным и не меняется при изменении имени пользователя.
Добавление реквизита для УИД: Мы начнем с добавления нового реквизита в ваш справочник Пользователи. Назовем его, например, ИдентификаторПользователяИБ. Тип этого реквизита лучше установить как Строка достаточной длины (например, 36 символов, так как УИД представляет собой строку GUID). Также можно использовать тип УникальныйИдентификатор, если он доступен в вашей версии платформы для реквизитов.
Получение УИД пользователя ИБ: Аналогично предыдущему методу, мы получаем объект текущего системного пользователя, но вместо имени извлекаем его УникальныйИдентификатор. Это делается с помощью ТекущийПользовательИБ.УникальныйИдентификатор.
Поиск элемента справочника по УИД: После получения УИД мы можем использовать его для поиска соответствующего элемента в нашем справочнике Пользователи. Для этого нам понадобится метод НайтиПоРеквизиту() (если мы используем динамические списки или запросы) или прямой перебор, если производительность не критична, или же реализация собственного метода поиска.
Рассмотрим пример, где мы ищем пользователя по нашему новому реквизиту ИдентификаторПользователяИБ:
&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
// Получаем объект текущего системного пользователя
ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ТекущийПользовательИБ <> Неопределено Тогда
// Получаем уникальный идентификатор системного пользователя
УИДПользователяИБ = ТекущийПользовательИБ.УникальныйИдентификатор;
// Ищем элемент в нашем справочнике "Пользователи" по реквизиту ИдентификаторПользователяИБ
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Пользователи.Ссылка
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ = &УИДПользователяИБ";
Запрос.УстановитьПараметр("УИДПользователяИБ", Строка(УИДПользователяИБ)); // Важно преобразовать УИД в строку для запроса
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
СсылкаНаПользователя = Неопределено;
Если Выборка.Следующий() Тогда
СсылкаНаПользователя = Выборка.Ссылка;
КонецЕсли;
Если СсылкаНаПользователя = Неопределено Тогда
// Если элемент не найден, его можно создать (см. следующий раздел)
Сообщить("Элемент справочника 'Пользователи' для пользователя с УИД '" + Строка(УИДПользователяИБ) + "' не найден.");
Иначе
// Устанавливаем найденный элемент в параметр сеанса для дальнейшего использования
ПараметрыСеанса.ТекущийПользовательСправочника = СсылкаНаПользователя;
Сообщить("Связь с элементом справочника установлена: " + СсылкаНаПользователя.Наименование);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Как мы видим из сообщения 5, "Связи пользователей и справочника устанавливаются по уникальному идентификатору - УникальныйИдентификатор", что подтверждает надежность этого подхода.
Для обеспечения бесшовной работы системы, когда пользователь впервые входит в информационную базу, мы можем автоматически создавать для него соответствующий элемент в нашем справочнике Пользователи, если его еще нет. Этот механизм упоминается в сообщении 4: "а ещё создавать при первом входе. Следить за прочими изменениями".
Мы реализуем эту логику в процедуре, выполняющейся при начале работы системы, чаще всего это обработчик события ПриНачалеРаботыСистемы в модуле сеанса.
Определение места реализации: Как уже упоминалось, ПриНачалеРаботыСистемы в модуле сеанса является идеальным местом. В этом месте у нас уже есть контекст текущего пользователя.
Получение информации о текущем ПользователеИБ: Мы получаем объект текущего системного пользователя и его УникальныйИдентификатор (или имя, если вы выбрали менее надежный способ).
Поиск существующего элемента: Мы пытаемся найти соответствующий элемент в нашем справочнике Пользователи, используя один из описанных выше методов (по УИД или по имени).
Создание нового элемента, если не найден: Если поиск не дал результатов (то есть, для текущего ПользователяИБ еще нет соответствующего элемента в справочнике), мы создаем новый элемент.
&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
// 1. Получаем объект текущего системного пользователя
ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ТекущийПользовательИБ <> Неопределено Тогда
// Получаем уникальный идентификатор и имя системного пользователя
УИДПользователяИБ = ТекущийПользовательИБ.УникальныйИдентификатор;
ИмяПользователяИБ = ТекущийПользовательИБ.Имя;
// 2. Ищем элемент в нашем справочнике "Пользователи" по УИД
СсылкаНаПользователя = Неопределено;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Пользователи.Ссылка
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ = &УИДПользователяИБ";
Запрос.УстановитьПараметр("УИДПользователяИБ", Строка(УИДПользователяИБ));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
СсылкаНаПользователя = Выборка.Ссылка;
КонецЕсли;
// 3. Если элемент не найден, создаем его
Если СсылкаНаПользователя = Неопределено Тогда
НовыйПользовательСправочника = Справочники.Пользователи.СоздатьЭлемент();
НовыйПользовательСправочника.Наименование = ИмяПользователяИБ;
НовыйПользовательСправочника.ИдентификаторПользователяИБ = Строка(УИДПользователяИБ);
// Можем также заполнить другие необходимые реквизиты по умолчанию
// Например, НовыйПользовательСправочника.Активен = Истина;
Попытка
НовыйПользовательСправочника.Записать();
СсылкаНаПользователя = НовыйПользовательСправочника.Ссылка;
Сообщить("Автоматически создан новый элемент справочника 'Пользователи': " + СсылкаНаПользователя.Наименование);
Исключение
Сообщить("Ошибка при создании элемента справочника 'Пользователи': " + ОписаниеОшибки());
Возврат;
КонецПопытки;
КонецЕсли;
// 4. Устанавливаем найденный или созданный элемент в параметр сеанса
ПараметрыСеанса.ТекущийПользовательСправочника = СсылкаНаПользователя;
КонецЕсли;
КонецПроцедуры
После того как мы установили связь, важно предусмотреть механизмы для синхронизации данных и обработки изменений, чтобы избежать расхождений и "битых" ссылок. Это также является частью рекомендации из сообщения 4: "Следить за прочими изменениями".
Изменение имени ПользователяИБ: Если вы используете связь по имени, изменение имени системного пользователя нарушит связь. Если вы используете УИД, связь останется стабильной. Однако, если вы выводите имя системного пользователя в Наименование вашего справочника Пользователи, то при изменении имени ПользователяИБ вам потребуется обновить и Наименование в справочнике. Это можно сделать через подписку на событие изменения объекта ПользовательИнформационнойБазы или с помощью регламентного задания, которое периодически проверяет и синхронизирует имена.
Удаление ПользователяИБ: При удалении системного ПользователяИБ через конфигуратор или средствами администрирования 1С, соответствующий элемент в вашем справочнике Пользователи остается. Чтобы избежать появления неактуальных данных или "битых" ссылок, рекомендуется либо удалять связанный элемент справочника, либо помечать его как неактивный (например, добавляя реквизит НеАктивен типа Булево).
Реализовать это можно с помощью:
ПользовательИнформационнойБазы, где будет выполняться поиск и удаление соответствующего элемента справочника.ПользователиИнформационнойБазы, сравнивает их с элементами справочника Пользователи по УИД и выявляет "потерянные" элементы, предлагая их удалить или пометить.Для корректной работы всей системы очень важно правильно настроить права доступа для пользователей к вашему справочнику Пользователи.
Права на чтение: Всем пользователям, которым необходим доступ к информации о других пользователях (например, для отображения списка ответственных, исполнителей), должны быть предоставлены права на чтение справочника Пользователи. Это необходимо, чтобы система могла корректно работать со связанной информацией и получать данные об элементах справочника.
Права на запись/изменение: Если вы планируете, что пользователи смогут самостоятельно изменять свои данные в справочнике Пользователи (например, контактную информацию) или если администраторам потребуется создавать/изменять эти элементы, то соответствующие роли должны иметь права на изменение и запись элементов справочника. При реализации автоматического создания элементов при первом входе, убедитесь, что у роли, под которой работают пользователи, есть права на создание новых элементов этого справочника.
Помните, что правильная настройка прав доступа обеспечивает безопасность данных и стабильность работы вашей информационной системы.
Таким образом, мы рассмотрели различные аспекты связывания системного ПользователяИБ с пользовательским справочником Пользователи без использования БСП. Наиболее надежным подходом является связь по уникальному идентификатору с автоматическим созданием элемента при первом входе и механизмом синхронизации для поддержания актуальности данных.