Как составить запрос к регистрам расчета «Начисления» и «Удержания» в 1С:ЗУП 3.1?

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

При разработке отчетов или обработок, таких как полный свод начислений, удержаний и выплат, в конфигурации 1С:Зарплата и управление персоналом 3.1 программисты часто сталкиваются с необходимостью объединения данных из разных регистров расчета. Одной из классических задач является получение полной картины по сотруднику: сколько ему начислено, сколько удержано и какова итоговая сумма к выплате, причем в разрезе месяцев и с динамикой относительно предыдущего периода. Трудность заключается в архитектурных особенностях ЗУП, где измерения в регистрах начислений и удержаний различаются. Разберем по шагам, как правильно решить эту задачу, избегая «костылей».

Анализ архитектуры регистров: Сотрудник vs Физическое лицо

Первое, с чем мы сталкиваемся при попытке соединить РегистрРасчета.Начисления и РегистрРасчета.Удержания, — это отсутствие измерения Сотрудник в регистре удержаний. В типовой конфигурации ЗУП 3.1 в удержаниях используется только ФизическоеЛицо. Это логично с точки зрения методологии: например, исполнительный лист или профсоюзный взнос привязывается к человеку как к личности, даже если он работает на нескольких должностях (внутреннее совместительство).

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

Шаг 1. Подготовка данных по начислениям

Для начала, используя консоль запросов (ЗУП), создадим временную таблицу, в которой соберем все начисления. Важно помнить, что в одном месяце у сотрудника может быть множество записей — стоит учитывать и плановые начисления сотрудников (оклад, премия, доплата за вредность). Чтобы не получить «раздувание» строк при последующем соединении (эффект декартова произведения), мы обязаны выполнить группировку на этом этапе, особенно если анализируется отработанное и оплаченное время сотрудников организации по видам начислений для ЗУП 3.1.

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


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

Шаг 2. Подготовка данных по удержаниям

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


ВЫБРАТЬ
    Удержания.ФизическоеЛицо КАК ФизическоеЛицо,
    НАЧАЛОПЕРИОДА(Удержания.ПериодРегистрации, МЕСЯЦ) КАК Месяц,
    СУММА(Удержания.Результат) КАК СуммаУдержано
ПОМЕСТИТЬ ВТ_Удержания
ИЗ
    РегистрРасчета.Удержания КАК Удержания
ГРУППИРОВАТЬ ПО
    Удержания.ФизическоеЛицо,
    НАЧАЛОПЕРИОДА(Удержания.ПериодРегистрации, МЕСЯЦ)
;

Шаг 3. Соединение данных и расчет итогов

Теперь объединим две временные таблицы. Используем ЛЕВОЕ СОЕДИНЕНИЕ, так как у сотрудника могут быть начисления, но не быть удержаний в конкретном месяце. Рассмотрим важный нюанс: при расчете итоговой суммы (Начислено - Удержано) необходимо использовать функцию ЕСТЬNULL, иначе при отсутствии удержаний результат вычитания станет NULL.


ВЫБРАТЬ
    ВТ_Начисления.Сотрудник КАК Сотрудник,
    ВТ_Начисления.ФизическоеЛицо КАК ФизическоеЛицо,
    ВТ_Начисления.Месяц КАК Месяц,
    ВТ_Начисления.СуммаНачислено КАК СуммаНачислено,
    ЕСТЬNULL(ВТ_Удержания.СуммаУдержано, 0) КАК СуммаУдержано,
    ВТ_Начисления.СуммаНачислено - ЕСТЬNULL(ВТ_Удержания.СуммаУдержано, 0) КАК ИтоговаяСумма
ПОМЕСТИТЬ ВТ_ИтоговыеДанные
ИЗ
    ВТ_Начисления КАК ВТ_Начисления
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Удержания КАК ВТ_Удержания
        ПО ВТ_Начисления.ФизическоеЛицо = ВТ_Удержания.ФизическоеЛицо
            И ВТ_Начисления.Месяц = ВТ_Удержания.Месяц
;

Шаг 4. Получение суммы за прошлый месяц и расчет динамики

Для выполнения условия задачи о сравнении текущей суммы с предыдущим периодом, нам нужно соединить таблицу ВТ_ИтоговыеДанные саму с собой. Посмотрим на условие соединения: мы будем искать запись для того же сотрудника, но за месяц, который на 1 меньше текущего. Для этого воспользуемся функцией ДОБАВИТЬКДАТЕ.

После получения суммы за прошлый месяц, мы применим конструкцию ВЫБОР КОГДА для вывода признака «Да/Нет».


ВЫБРАТЬ
    Т1.Сотрудник КАК Сотрудник,
    Т1.Месяц КАК Месяц,
    Т1.СуммаНачислено КАК СуммаНачислено,
    Т1.СуммаУдержано КАК СуммаУдержано,
    Т1.ИтоговаяСумма КАК ИтоговаяСумма,
    ЕСТЬNULL(Т2.ИтоговаяСумма, 0) КАК СуммаПрошлогоМесяца,
    ВЫБОР
        КОГДА Т1.ИтоговаяСумма > ЕСТЬNULL(Т2.ИтоговаяСумма, 0) ТОГДА "Да"
        ИНАЧЕ "Нет"
    КОНЕЦ КАК СуммаУвеличилась
ИЗ
    ВТ_ИтоговыеДанные КАК Т1
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ИтоговыеДанные КАК Т2
        ПО Т1.Сотрудник = Т2.Сотрудник
            И Т1.Месяц = ДОБАВИТЬКДАТЕ(Т2.Месяц, МЕСЯЦ, 1)
УПОРЯДОЧИТЬ ПО
    Т1.Сотрудник,
    Т1.Месяц УБЫВ
ИТОГИ
    СУММА(ИтоговаяСумма)
ПО
    Сотрудник

Важные замечания по реализации

Проанализируем ключевые моменты, которые мы применили для чистого решения без «костылей»:

  1. Связь через Физлицо: Мы использовали Начисления.Сотрудник.ФизическоеЛицо = Удержания.ФизическоеЛицо. Это единственно верный способ сопоставить данные этих двух регистров.
  2. Группировка до соединения: Предварительное сворачивание данных во временных таблицах гарантирует, что мы не получим лишних строк, если у сотрудника было 5 видов начислений и 2 вида удержаний.
  3. Работа с NULL: Всегда оборачивайте ресурсы присоединяемых таблиц в функцию ЕСТЬNULL(..., 0), чтобы математические операции в запросе не возвращали пустоту.
  4. Сортировка и Итоги: В конце запроса мы добавили УПОРЯДОЧИТЬ ПО ... УБЫВ для выполнения условия по выводу месяцев и предложение ИТОГИ для расчета агрегатов на уровне сотрудника. При использовании в СКД (системе компоновки данных) расчет итогов лучше выносить в настройки ресурсов самой схемы.

Таким образом, мы получили структурированный запрос, который полностью удовлетворяет условиям учебной задачи и может быть использован в реальной практике разработки под ЗУП 3.1. Этот метод позволяет эффективно работать с любыми регистрами расчета, соблюдая методологию платформы 1С.

← На главную