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