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