При переходе с версии 1С:ЗУП 2.5 на 3.1 многие пользователи и программисты сталкиваются с желанием перенести старые алгоритмы расчетов, реализованные через сложные внешние обработки или запросы к регистрам. Типичный пример — квартальная премия, которая должна рассчитываться исходя из оклада, но строго пропорционально календарным дням, исключая периоды больничных, отпусков и учитывая даты приема или увольнения сотрудника. Рассмотрим, как реализовать этот алгоритм в 1С:ЗУП 3.1, используя мощный типовой функционал программы без написания сложного кода.
Проанализируем ситуацию: в старых версиях программы (ЗУП 2.5) для таких расчетов часто требовалось написание запроса к регистру сведений СостояниеРаботниковОрганизаций или ГрафикиРаботыПоВидамВремени. В современных версиях на платформе 8.3 расчетный механизм работает иначе. Программа сама умеет определять фактически отработанное время и накладывать периоды неявок (вытеснение). Нам достаточно правильно настроить формулу и приоритеты начисления.
Разберем типичную ошибку из сообщения пользователя: использование константы «90» в качестве знаменателя (дней в квартале). В разных кварталах может быть 90, 91 или 92 дня. Чтобы расчет был корректным, мы должны использовать показатели нормы времени, а не фиксированные числа.
Для создания премии перейдем в меню «Настройка» — «Начисления» и создадим новый вид расчета. На вкладке Основное укажем, что начисление выполняется «По отдельному документу» (документ «Премия») или «Ежемесячно» (если это плановый показатель).
Рассмотрим вариант формулы для расчета за квартал. Если мы хотим, чтобы программа брала оклад сотрудника и корректировала его на коэффициент времени, формула может выглядеть так:
(Оклад * ДоляРаспределения) * (ВремяВКалендарныхДнях / НормаКалендарныхДней)
Где:
Оклад — предопределенный показатель месячной тарифной ставки.ВремяВКалендарныхДнях — показатель фактического нахождения сотрудника на работе в календарных днях (за вычетом неявок).НормаКалендарныхДней — общее количество календарных дней в периоде по графику.Если премия должна составлять ровно один оклад за полностью отработанный квартал, расчет усложняется тем, что Оклад в ЗУП 3.1 обычно привязан к месяцу. Поэтому проанализируем альтернативный и более надежный вариант — использование расчетной базы.
Выясним причину, по которой расчет через РасчетнаяБаза предпочтительнее. Если у сотрудника в течение квартала изменился оклад (например, с 1-го числа второго месяца квартала), простая формула с показателем Оклад возьмет только то значение, которое действует на момент расчета. Использование расчетной базы позволяет собрать все начисления по окладу за три месяца.
Настроим формулу следующим образом:
РасчетнаяБаза * (ВремяВКалендарныхДнях / КалендарныеДниМесяца) — это пример для ежемесячной премии. Для квартальной логика сохраняется, но в настройках базы мы указываем период «Предыдущий квартал».
Однако автор вопроса просит расчет именно по формуле: Оклад * (Дни / 90). В терминах ЗУП 3.1 это реализуется через создание планового начисления с использованием показателей времени.
Посмотрим на пример настройки, которая решает проблему «минусования» отпусков и больничных без кода. В карточке начисления откроем вкладку Приоритет. Это ключевой момент настройки:
Больничный, Отпуск основной, Отпуск без сохранения оплаты, Командировка, Прогул.ВремяВКалендарныхДнях автоматически уменьшится на количество дней отсутствия.Проанализируем ситуацию с новыми сотрудниками. Если сотрудник принят 15-го числа второго месяца квартала, система ЗУП 3.1 при расчете премии в документе «Премия» (с указанием периода — квартал) автоматически определит рабочий период сотрудника. Показатель ВремяВКалендарныхДнях будет рассчитан только за фактически «рабочие» даты в рамках организации. Никаких дополнительных условий в формулу ?(...) добавлять не требуется — это штатное поведение движка расчета зарплаты.
Если же типовых настроек недостаточно и требуется программное заполнение документа, не стоит использовать код из версии 2.5, представленный в сообщении 6. В ЗУП 3.1 данные о времени лучше получать через временные таблицы запроса к виртуальным таблицам регистров расчета или используя программный интерфейс (API) конфигурации.
Рассмотрим пример того, как можно было бы получить отработанные дни программно, если вы создаете свою обработку заполнения:
// Пример получения данных через запрос к данным графика
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеГрафика.КалендарныеДни КАК НормаДней,
| ДанныеГрафика.КалендарныеДниФакс КАК ОтработаноДней
|ИЗ
| РегистрРасчета.Зарплата.ДанныеГрафика(
| Сотрудник = &Сотрудник
| И ВидРасчета = &ВидРасчета
| И ПериодДействия МЕЖДУ &НачалоКвартала И &КонецКвартала) КАК ДанныеГрафика";
Запрос.УстановитьПараметр("Сотрудник", ВыбранныйСотрудник);
Запрос.УстановитьПараметр("ВидРасчета", ПланыВидовРасчета.Начисления.НайтиПоНаименованию("КвартальнаяПремия"));
Запрос.УстановитьПараметр("НачалоКвартала", НачалоКвартала(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецКвартала", КонецКвартала(ТекущаяДата()));
Однако, повторимся: в 99% случаев в ЗУП 3.1 это решается пользовательской настройкой начисления. Если правильно заполнены вкладки «Учет времени» (указано «Дополнительное начисление за уже оплаченное время» и выбран вид времени «Рабочее время») и «Приоритет», программа сама выполнит всю математику при нажатии кнопки «Заполнить» в документе «Премия».
НормаДнейКвартала с типом «Для организации» и вводите его раз в квартал. Но лучше использовать НормаКалендарныхДней.Оклад * (ВремяВКалендарныхДнях / НормаКалендарныхДней).Таким образом, мы уходим от необходимости поддержки сложного кода и используем гибкость системы 1С:ЗУП 3.1, которая автоматически обрабатывает и изменения окладов, и кадровые изменения (прием/увольнение), и любые виды отсутствий сотрудника на рабочем месте.