Почему СрезПоследних возвращает несколько записей по физлицу и как получить последний документ в 1С:ЗУП 3?

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

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

Выясним причину: как работает виртуальная таблица СрезПоследних

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

  1. Физлицо (ссылка на справочник ФизическиеЛица);
  2. ВидДокумента (ссылка на справочник ВидыДокументовФизическихЛиц).

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


РегистрСведений.ДокументыФизическихЛиц.СрезПоследних(&Период, ФизЛицо = &ФизЛицо)

платформа добросовестно находит самую свежую запись для каждого вида документа, когда-либо зарегистрированного за этим человеком (например, наиболее свежий вид на жительство, наиболее свежий паспорт РФ, наиболее свежий загранпаспорт). В результате по сотруднику возвращается столько строк, сколько видов документов числится в его истории.

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

Способ 1. Двухэтапный запрос с поиском максимума периода через временную таблицу

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


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

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

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

Способ 2. Использование аналитических (оконных) функций платформы

Если решение разворачивается на платформе 1С:Предприятие версии 8.3.20 и новее, мы можем применить оконную функцию ROW_NUMBER(). Это позволяет избежать срезов и лишних соединений, ранжируя документы прямо в запросе:


ВЫБРАТЬ
    Документы.ФизЛицо КАК ФизЛицо,
    Документы.ВидДокумента КАК ВидДокумента,
    Документы.Серия КАК Серия,
    Документы.Номер КАК Номер,
    Документы.ДатаВыдачи КАК ДатаВыдачи,
    Документы.КемВыдан КАК КемВыдан,
    Документы.Представление КАК Представление,
    ROW_NUMBER() OVER (
        PARTITION BY Документы.ФизЛицо
        ORDER BY Документы.Период УБЫВ, Документы.ДатаВыдачи УБЫВ
    ) КАК НомерСтроки
ПОМЕСТИТЬ ВТ_РанжированныеДокументы
ИЗ
    РегистрСведений.ДокументыФизическихЛиц КАК Документы
ГДЕ
    Документы.ФизЛицо В (&СписокФизЛиц)
    И Документы.Период <= &ДатаСреза
    И Документы.ЯвляетсяДокументомУдостоверяющимЛичность = ИСТИНА
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.ФизЛицо,
    ВТ.ВидДокумента,
    ВТ.Серия,
    ВТ.Номер,
    ВТ.ДатаВыдачи,
    ВТ.КемВыдан,
    ВТ.Представление
ИЗ
    ВТ_РанжированныеДокументы КАК ВТ
ГДЕ
    ВТ.НомерСтроки = 1

Способ 3. Использование штатных механизмов БСП и ЗУП 3

В типовой конфигурации «1С:Зарплата и управление персоналом» ручное написание запросов к регистру документов физических лиц обычно не требуется. В конфигурации реализован готовый программный интерфейс в общем модуле КадровыйУчет, который уже содержит алгоритмы обработки дублей, проверки флага удостоверения личности и ранжирования.

Разберем программное получение данных в коде:


КадровыеДанные = Новый Массив;
КадровыеДанные.Добавить("ДокументВид");
КадровыеДанные.Добавить("ДокументСерия");
КадровыеДанные.Добавить("ДокументНомер");
КадровыеДанные.Добавить("ДокументДатаВыдачи");
КадровыеДанные.Добавить("ДокументКемВыдан");
КадровыеДанные.Добавить("ДокументКодПодразделения");
КадровыеДанные.Добавить("ДокументПредставление");

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

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


КадровыйУчет.СоздатьВТКадровыеДанныеФизическихЛиц(
    МенеджерВременныхТаблиц,
    "ВТ_ПаспортныеДанные",
    СписокФизЛиц,
    КадровыеДанные,
    ДатаСреза
);

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

← На главную