Как получить расчетную базу для премии с учетом кадровых перемещений в 1С

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

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

Проблема использования стандартных методов

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

Решение через программный интерфейс «МенеджерРасчета»

В современных конфигурациях на базе «1С:Предприятие 8.3» наиболее правильным способом является использование программного интерфейса РасчетЗарплатыРасширенный. Это позволяет симулировать расчет так, как это делает документ «Начисление зарплаты и взносов». Рассмотрим пример кода, который позволяет инициализировать расчетный механизм:


УстановитьПривилегированныйРежим(Истина);
НачатьТранзакцию();

// Создаем менеджер расчета для нужного периода и организации
МенеджерРасчета = РасчетЗарплатыРасширенный.СоздатьМенеджерРасчета(Объект.МесяцНачисления, Объект.Организация);
МенеджерРасчета.НастройкиРасчета.РассчитыватьНачисления = Истина;

// Исключаем текущий документ из расчетов, чтобы избежать зацикливания или двойного счета
МенеджерРасчета.ИсключаемыйРегистратор = Объект.Ссылка;

СотрудникиДляНачислений = МенеджерРасчета.ТаблицаСотрудников;
СотрудникиДляРассчета = Новый Массив;

// Предположим, у нас есть коллекция сотрудников с датами перемещений
Для Каждого Стр Из КадровыеПереводыСотрудников Цикл
    СотрудникиДляРассчета.Добавить(Стр.Сотрудник);
    
    НоваяСтрока = СотрудникиДляНачислений.Добавить();
    НоваяСтрока.Сотрудник = Стр.Сотрудник;
    // Важно: указываем интервалы, за которые нужно получить расчет
    НоваяСтрока.ДатаНачала = Стр.Начало; 
    НоваяСтрока.ДатаОкончания = Стр.Окончание;
КонецЦикла;

МенеджерРасчета.НастройкиРасчета.Сотрудники = СотрудникиДляРассчета;

// Настраиваем отборы, если расчет идет по конкретному подразделению
ОтборМенеджераРасчета = МенеджерРасчета.СоздатьОтборы();
ОтборМенеджераРасчета.Подразделение = Объект.Подразделение;

// Заполняем и рассчитываем
МенеджерРасчета.ЗаполнитьНачислениеЗарплаты(СотрудникиДляНачислений, ОтборМенеджераРасчета);
МенеджерРасчета.РассчитатьЗарплату();

// Данные рассчитаны в памяти менеджера, теперь их можно анализировать
// После получения данных отменяем транзакцию, чтобы не зафиксировать фиктивные расчеты в базе
ОтменитьТранзакцию();
УстановитьПривилегированныйРежим(Ложь);

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

Тонкости настройки периодов и кадровых переводов

Часто возникает вопрос: почему при смене периода на прошлый месяц расчет выдает пустые значения? Проанализируем причину. В системе 1С существует разделение на ПериодРегистрации и ПериодДействия.

  1. Период регистрации: месяц, в котором начисляется сумма (например, Сентябрь).
  2. Базовый период: интервал времени, за который собираются начисления для расчета (например, Август).

Если в настройках начисления «Премия» указано, что база берется за «Предыдущий месяц», то система автоматически при расчете записи в Сентябре посмотрит все начисления за Август. Если в Августе был кадровый перевод, то в регистре за Август уже существуют две (или более) записи с разными подразделениями. Чтобы премия «увидела» их правильно, само начисление премии должно иметь такие настройки в справочнике Начисления:

Работа с виртуальной таблицей «РасчетнаяБаза»

Если использование МенеджераРасчета кажется слишком избыточным (например, когда нужно просто получить отчетную информацию), можно воспользоваться запросом к виртуальной таблице РегистрРасчета.Начисления.РасчетнаяБаза. Проанализируем параметры этой таблицы:

Основной секрет здесь кроется в параметре ИзмеренияБазовогоРегистра. Если вы хотите, чтобы база учитывала кадровые перемещения по подразделениям, необходимо передать «Подразделение» в этот параметр. В противном случае система может «схлопнуть» всю базу по сотруднику в одну общую сумму, проигнорировав, что часть месяца он работал в одном отделе, а часть — в другом.

Очередность расчета и «дострел» данных

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

При использовании МенеджерРасчета.РассчитатьЗарплату() система старается соблюдать очередность, но важно убедиться, что базовые начисления за прошлый период уже окончательно зафиксированы в базе (проведены). Если кадровое перемещение было введено «задним числом», необходимо убедиться, что записи пересчета (регистр сведений ПересчетыЗарплаты) обработаны, иначе МенеджерРасчета может взять старые, неактуальные данные до перевода.

Заключение и рекомендации

Для гарантированного получения базы с учетом перемещений рекомендуем следующий алгоритм:

  1. Используйте МенеджерРасчета для выполнения полноценного программного расчета.
  2. Всегда проверяйте интервалы ДатаНачала и ДатаОкончания в таблице СотрудникиДляНачислений — они должны соответствовать фактическим периодам работы сотрудника в каждом подразделении в базовом месяце.
  3. Если задача стоит только в получении суммы — используйте запрос к виртуальной таблице с обязательной группировкой по измерениям Сотрудник и Подразделение.
  4. Помните про транзакцию: выполнение расчета — процедура тяжелая, и использование ОтменитьТранзакцию() позволит вам получить данные без побочных эффектов для учета.
← На главную