Как правильно получить актуальную фамилию сотрудника на дату документа в 1С

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

При разработке печатных форм в конфигурациях на платформе 1С:Предприятие 8 часто возникает задача вывода актуальных личных данных сотрудников. Одной из наиболее распространенных проблем является некорректный вывод фамилии: программа может выводить либо самую первую фамилию (девичью), либо всегда самую актуальную на текущий момент, игнорируя дату документа. Разберем подробно, как настроить запрос к регистру сведений ФИОФизическихЛиц, чтобы всегда получать верные данные.

Анализ проблемы: разница между СрезПервых и СрезПоследних

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

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

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

Решение 1: Использование виртуальной таблицы СрезПоследних с параметром Период

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

Проанализируем пример исправления части запроса:


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

При этом в коде на встроенном языке важно правильно установить параметр &Период. Если фамилия была изменена тем же днем, что и дата приказа, рекомендуется использовать конец дня или границу, чтобы изменение попало в выборку:


Запрос.УстановитьПараметр("Период", Новый Граница(Объект.Дата, ВидГраницы.Включая));

Решение 2: Получение данных через физическую таблицу (сложный случай)

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

Выполним задачу по шагам:

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

Посмотрим на пример реализации такого запроса:


// Шаг 1: Получаем максимальные даты изменений до даты документа
ВЫБРАТЬ
    ВТ_Сотрудники.ФизическоеЛицо КАК ФизическоеЛицо,
    МАКСИМУМ(ФИОФизическихЛиц.Период) КАК Период
ПОМЕСТИТЬ ВТ_МаксимальныеДаты
ИЗ
    ВТ_Сотрудники КАК ВТ_Сотрудники
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ФИОФизическихЛиц КАК ФИОФизическихЛиц
        ПО ВТ_Сотрудники.ФизическоеЛицо = ФИОФизическихЛиц.ФизическоеЛицо
        И ФИОФизическихЛиц.Период <= ВТ_Сотрудники.ДатаДокумента
ГРУППИРОВАТЬ ПО
    ВТ_Сотрудники.ФизическоеЛицо
;

// Шаг 2: Соединяем с физической таблицей для получения данных
ВЫБРАТЬ
    Даты.ФизическоеЛицо,
    ФИО.Фамилия,
    ФИО.Имя,
    ФИО.Отчество
ИЗ
    ВТ_МаксимальныеДаты КАК Даты
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ФИОФизическихЛиц КАК ФИО
        ПО Даты.ФизическоеЛицо = ФИО.ФизическоеЛицо
        И Даты.Период = ФИО.Период

Этот метод позволяет избежать использования виртуальных таблиц внутри соединений, что является "лучшей практикой" (best practice) при разработке на 1С, особенно если в выборке участвуют тысячи сотрудников.

Особенности работы с регистром ФИО физических лиц

Важно помнить, что в типовых конфигурациях (ЗУП, ERP, КА) данные о фамилиях хранятся в привязке к Физическому лицу, а не к Сотруднику. Один человек может работать в компании и как основной сотрудник, и как внутренний совместитель. При смене фамилии запись создается для физлица, и она автоматически становится актуальной для всех его "сотрудников".

Также проанализируем периодичность регистра. Как правило, она установлена в значение "День". Это означает, что в пределах одного дня у человека не может быть зафиксировано две разные фамилии. Если вы программно создаете записи в этом регистре, убедитесь, что периоды не пересекаются в рамках одной даты.

Использование программных функций общего назначения

Если вы работаете в современной конфигурации, мы рекомендуем не писать запросы к регистру ФИО вручную, а использовать встроенные механизмы БСП (Библиотеки стандартных подсистем) или типовые функции кадрового учета. Это значительно сокращает объем кода и минимизирует риск ошибок.

Например, в ЗУП 3.1 для этих целей предназначена функция КадровыйУчет.ДанныеФизическихЛиц. Рассмотрим пример её вызова:


СписокФизЛиц = Новый Массив;
СписокФизЛиц.Добавить(ВыбранноеФизЛицо);

ПараметрыЧтения = "Фамилия, Имя, Отчество, Инициалы";
ДанныеФИО = КадровыйУчет.ДанныеФизическихЛиц(СписокФизЛиц, ДатаДокумента, ПараметрыЧтения);

Для Каждого СтрокаДанных Из ДанныеФИО Цикл
    Сообщить(СтрокаДанных.Фамилия); // Выведет фамилию на указанную дату
КонецЦикла;

Этот метод автоматически учитывает все нюансы среза последних, часовые пояса и корректно работает с историей изменений, избавляя разработчика от написания сложных запросов.

Резюме для разработчика

Для успешного вывода последней фамилии в печатную форму придерживайтесь следующих правил:

← На главную