Как в 1С:ЗУП получить дату самого первого приема сотрудника на работу?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

Часто при доработке отчетов или печатных форм в 1С:ЗУП возникает задача получить какую-либо начальную дату, связанную с сотрудником, например, дату самого первого приема на работу в организацию. Начинающие разработчики могут столкнуться с трудностями, так как стандартные срезы данных, такие как СрезПервых, не всегда дают ожидаемый результат. Это связано с особенностями хранения кадровых данных и различиями в ключевых понятиях системы.

Разберем ситуацию на примере. Пользователь пытается доработать печатную форму графика отпусков и хочет вывести дату первого приема на работу для расчета стажа. Он пишет запрос, но получает неверные данные. Проанализируем, в чем заключается ошибка, как ее исправить, и выясним, действительно ли для поставленной задачи нужна именно эта дата.

Анализ исходной проблемы: почему запрос не работает?

Давайте посмотрим на первоначальный запрос, который вызвал затруднения. Его главная цель — получить данные из документа ГрафикОтпусков и для каждого сотрудника найти дату его первого приема на работу.


ВЫБРАТЬ
    ГрафикОтпусковСотрудники.Ссылка.Дата КАК ДатаДоговора,
    // ... другие поля
    КадроваяИсторияСотрудниковСрезПервых.Регистратор.Дата КАК РегистраторДата
ИЗ
    Документ.ГрафикОтпусков.Сотрудники КАК ГрафикОтпусковСотрудники
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(&КонецПериода, ) КАК КадроваяИсторияСотрудниковСрезПоследних
        ПО (ГрафикОтпусковСотрудники.Сотрудник = КадроваяИсторияСотрудниковСрезПоследних.Сотрудник)
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПервых КАК КадроваяИсторияСотрудниковСрезПервых
        ПО (ГрафикОтпусковСотрудники.Сотрудник = КадроваяИсторияСотрудниковСрезПервых.Сотрудник)
ГДЕ
    // ... другие условия
    И ТИПЗНАЧЕНИЯ(КадроваяИсторияСотрудниковСрезПервых.Регистратор) = ТИП(Документ.ПриемНаРаботу)

Проблема этого запроса кроется в фундаментальном непонимании двух ключевых сущностей 1С:ЗУП: Физическое лицо и Сотрудник.

В исходном запросе все соединения выполняются по полю ГрафикОтпусковСотрудники.Сотрудник. Это значит, что для каждого конкретного трудоустройства (для каждой записи в справочнике «Сотрудники») мы ищем первую запись в регистре КадроваяИсторияСотрудников. Но у одного элемента справочника Сотрудники может быть только один прием на работу. Поэтому СрезПервых по сотруднику не даст нам историю всех его трудоустройств.

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

Чтобы найти самую первую дату, когда человек был принят в организацию, независимо от того, сколько раз он увольнялся и принимался снова, нужно строить запрос от физического лица.

Рассмотрим по шагам правильный алгоритм:

  1. Определить физическое лицо, для которого мы ищем данные.
  2. Найти все элементы справочника «Сотрудники», которые связаны с этим физическим лицом.
  3. Обратиться к регистру сведений КадроваяИсторияСотрудников и для всего найденного списка сотрудников выбрать записи с видом события «Прием».
  4. Из полученных дат приема выбрать минимальную (самую раннюю).

Вот как может выглядеть запрос, реализующий эту логику:


ВЫБРАТЬ
    МИНИМУМ(КадроваяИстория.Период) КАК СамаяПерваяДатаПриема
ИЗ
    РегистрСведений.КадроваяИсторияСотрудников КАК КадроваяИстория
ГДЕ
    КадроваяИстория.Сотрудник.ФизическоеЛицо = &ФизическоеЛицо
    И КадроваяИстория.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Прием)

Этот запрос найдет все приемы на работу для указанного физического лица по всем его "инкарнациям" в справочнике «Сотрудники» и вернет самую первую дату.

Расчет стажа: почему "дата первого приема" — это неверный путь?

Даже если мы правильно найдем дату первого приема, использовать ее для расчета стажа по формуле "ТекущаяДата - ДатаПервогоПриема" — грубая методологическая ошибка.

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

В 1С:ЗУП 3.1 существуют готовые механизмы для хранения и расчета различных видов стажа (основной для больничных, северный, для права на отпуск и т. д.).

Вывод: не нужно пытаться изобретать собственный механизм расчета стажа. Используйте стандартные функции и данные, которые предоставляет конфигурация. Это надежнее и правильнее с точки зрения методологии учета.

Истинная задача: что такое "Период работы" в графике отпусков?

Как выяснилось в ходе обсуждения, первоначальная задача была связана не с расчетом общего стажа, а с заполнением поля «Период работы» в печатной форме графика отпусков.

В контексте отпусков «Период работы» — это не общий стаж, а рабочий год, за который сотруднику предоставляется ежегодный оплачиваемый отпуск.

Для определения рабочего года нам нужна дата не самого первого, а самого последнего приема на работу. Получить ее можно с помощью виртуальной таблицы РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних с отбором по виду события.

Посмотрим на пример кода, который решает именно эту задачу:


// ... фрагмент запроса ...
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(
        ,
        ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Прием)) КАК ДатыПриема
    ПО ГрафикОтпусковСотрудники.Сотрудник = ДатыПриема.Сотрудник
// ... в секции ВЫБРАТЬ можно получить ДатыПриема.Период КАК ДатаПоследнегоПриема ...

Таким образом, для корректного решения исходной задачи нужно было не искать самую первую дату приема, а получить дату последнего приема и на ее основе вычислять границы рабочего года, за который планируется отпуск. Это классический пример «проблемы XY», когда пользователь ищет решение для предполагаемой им промежуточной задачи (X), вместо того чтобы решать исходную конечную задачу (Y).

Итог: всегда четко определяйте конечную цель. Различайте понятия Сотрудник и Физическое лицо, используйте встроенные механизмы программы для расчета стажа и правильно определяйте рабочий год для предоставления отпусков.

← На главную