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