Расчет процента северной надбавки в программе 1С:Зарплата и Управление Персоналом — задача нетривиальная. Сложность заключается в том, что процент надбавки зависит от шкалы стажа работы на Севере и постоянно увеличивается со временем (в зависимости от группы и возраста сотрудника). В базах данных этот процент, как правило, в готовом виде на каждый день не хранится — его необходимо вычислять динамически.
В этой статье мы подробно разберем, как получить актуальный процент северной надбавки у сотрудника на определенную дату. Мы рассмотрим современные методы для актуальной версии 1С:ЗУП 3.1, а также обратимся к классическим решениям и запросам для старых версий программы (ЗУП 2.5).
В современных конфигурациях 1С структура хранения данных кардинально изменилась по сравнению с редакцией 2.5. Записи о стаже теперь привязаны не к сотрудникам напрямую, а к физическим лицам. Основным регистром сведений является периодический регистр ПроцентыСевернойНадбавкиФизическихЛиц.
Разработчикам настоятельно не рекомендуется писать собственные сложные запросы для расчета процентов по шкале, так как фирма 1С реализовала готовый программный интерфейс (API), который учитывает все тонкости законодательства. Для получения процента на конкретную дату мы можем использовать готовые функции общего модуля.
Рассмотрим подробнее основной метод получения процента северной надбавки:
ПроцентНадбавки = КадровыйУчетРасширенный.ПроцентСевернойНадбавки(ФизическоеЛицо, УчетнаяДата);
Эта функция самостоятельно обратится к регистрам сведений, определит группу северной надбавки, начальный стаж, рассчитает количество прошедших месяцев и дней на указанную дату УчетнаяДата и вернет актуальный процент в виде числового значения.
Если нам необходимо получить подробные сведения о стаже физического лица, мы можем использовать метод:
СведенияОСтаже = КадровыйУчетРасширенныйВызовСервера.СведенияОСтажахФизическогоЛица(ФизическоеЛицо, УчетнаяДата);
Важный нюанс при написании запросов: Помните, что данные в регистре привязаны к физическому лицу. Если сотрудник работал в северном филиале, уволился и устроился в обычный регион, запись в регистре физических лиц сохранится. Чтобы точно определить, положена ли сотруднику надбавка в данный момент, необходимо левым соединением проверять наличие действующего планового начисления «Северная надбавка» в регистре сведений ПлановыеНачисления или анализировать территориальные условия подразделения сотрудника.
В старых редакциях ЗУП процент также не хранился в готовом виде в плановых начислениях, а рассчитывался динамически. Для этого использовалась встроенная процедура в глобальном модуле ПроведениеРасчетов.
Проанализируем пример вызова функции, которая берет данные из регистра СведенияОСтажеРаботыНаСевере и вычисляет процент за указанный период:
// Пример вызова встроенной процедуры для расчета процента
ПроведениеРасчетов.ПолучитьПроцентыСевернойНадбавкиЗаПериод(ТаблицаСотрудников, ПараметрыРасчета);
Этот метод отлично подходит для работы в программном коде модулей документов или обработок, когда нам не требуется вычислять процент исключительно внутри тела запроса базы данных.
Бывают ситуации, когда процент северной надбавки необходимо получить исключительно средствами SQL/запроса 1С (например, при разработке сложного отчета на СКД без использования внешних наборов данных). В таком случае приходится эмулировать алгоритм расчета шкалы прямо в запросе.
Ниже представлен детальный пример запроса для редакции 2.5, который воссоздает шкалы начислений (Группы с 1 по 4, обычные и льготные варианты) и рассчитывает итоговый процент на дату среза.
Давайте разберем этот сложный запрос по шагам:
Посмотрим на текст этого запроса:
ВЫБРАТЬ
РаботникиОрганизацийСрезПоследних.Сотрудник.Физлицо КАК Физлицо,
&ДатаСреза КАК ПериодРаботники
ПОМЕСТИТЬ ВТРаботникиИНачисления
ИЗ
РегистрСведений.РаботникиОрганизаций.СрезПоследних(&ДатаСреза, Организация = &ГоловнаяОрганизация) КАК РаботникиОрганизацийСрезПоследних
ГДЕ
РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния <> ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Увольнение);
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ДатыСтажа.Физлицо,
ДатыСтажа.ПериодРаботники,
ДатыСтажа.ПериодСеверногоСтажа КАК ДатаРегистрацииСеверногоСтажа,
СведенияОСтажеРаботыНаСевере.ПорядокНачисленияСеверныхНадбавок,
СведенияОСтажеРаботыНаСевере.НачальныйПроцентСевернойНадбавки,
СведенияОСтажеРаботыНаСевере.СеверныйСтажМесяцев,
СведенияОСтажеРаботыНаСевере.СеверныйСтажДней
ПОМЕСТИТЬ РаботникиИСтажи
ИЗ
(ВЫБРАТЬ
СписокНачислений.Физлицо КАК Физлицо,
СписокНачислений.ПериодРаботники КАК ПериодРаботники,
МАКСИМУМ(СведенияОСтажеРаботыНаСевере.Период) КАК ПериодСеверногоСтажа
ИЗ
ВТРаботникиИНачисления КАК СписокНачислений
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОСтажеРаботыНаСевере КАК СведенияОСтажеРаботыНаСевере
ПО СписокНачислений.Физлицо = СведенияОСтажеРаботыНаСевере.ФизЛицо
И СписокНачислений.ПериодРаботники >= СведенияОСтажеРаботыНаСевере.Период
СГРУППИРОВАТЬ ПО
СписокНачислений.Физлицо,
СписокНачислений.ПериодРаботники) КАК ДатыСтажа
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СведенияОСтажеРаботыНаСевере КАК СведенияОСтажеРаботыНаСевере
ПО ДатыСтажа.Физлицо = СведенияОСтажеРаботыНаСевере.ФизЛицо
И ДатыСтажа.ПериодСеверногоСтажа = СведенияОСтажеРаботыНаСевере.Period;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа1Льготная) КАК ПорядокНачисления,
6 КАК РазмерПериода1,
20 КАК РазмерПрироста1,
60 КАК Ограничение1,
6 КАК РазмерПериода2,
10 КАК РазмерПрироста2,
100 КАК Ограничение2
ПОМЕСТИТЬ ИсходнаяШкалаНадбавок
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа1Обычная), 6, 10, 100, 0, 0, 0
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа2Льготная), 6, 20, 60, 12, 20, 80
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа2Обычная), 6, 10, 60, 12, 10, 80
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа3Льготная), 6, 10, 50, 0, 0, 0
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа3Обычная), 12, 10, 50, 0, 0, 0
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа4Льготная), 6, 10, 30, 0, 0, 0
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.Группа4Обычная), 12, 10, 10, 24, 10, 30;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ШкалаНадбавок.ПорядокНачисления,
ШкалаНадбавок.РазмерПериода1,
ШкалаНадбавок.РазмерПрироста1,
ШкалаНадбавок.Ограничение1,
ШкалаНадбавок.РазмерПериода2,
ШкалаНадбавок.РазмерПрироста2,
ШкалаНадбавок.Ограничение2,
ВЫБОР КОГДА ШкалаНадбавок.Ограничение2 = 0 ТОГДА 0 ИНАЧЕ ШкалаНадбавок.РазмерПериода2 * (ШкалаНадбавок.Ограничение2 - ШкалаНадбавок.Ограничение1) / ШкалаНадбавок.РазмерПрироста2 КОНЕЦ КАК КоличествоМесяцевДляДостиженияВторогоОграничения,
ШкалаНадбавок.РазмерПериода1 * ШкалаНадбавок.Ограничение1 / ШкалаНадбавок.РазмерПрироста1 КАК КоличествоМесяцевДляДостиженияПервогоОграничения
ПОМЕСТИТЬ ШкалаНадбавок
ИЗ
ИсходнаяШкалаНадбавок КАК ШкалаНадбавок;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
РаботникиИСтажи.Физлицо,
ШкалаНадбавок.ПорядокНачисления,
ШкалаНадбавок.РазмерПериода1,
ШкалаНадбавок.РазмерПрироста1,
ШкалаНадбавок.Ограничение1,
ШкалаНадбавок.РазмерПериода2,
ШкалаНадбавок.РазмерПрироста2,
ШкалаНадбавок.Ограничение2,
РаботникиИСтажи.ДатаРегистрацииСеверногоСтажа,
РаботникиИСтажи.ПериодРаботники,
РаботникиИСтажи.НачальныйПроцентСевернойНадбавки,
РаботникиИСтажи.СеверныйСтажМесяцев,
РаботникиИСтажи.СеверныйСтажДней,
ДОБАВИТЬКДАТЕ(ДОБАВИТЬКДАТЕ(РаботникиИСтажи.ДатаРегистрацииСеверногоСтажа, МЕСЯЦ, -РаботникиИСтажи.СеверныйСтажМесяцев), ДЕНЬ, -РаботникиИСтажи.СеверныйСтажДней) КАК ДатаНачалаОтсчетаСеверногоСтажа,
ШкалаНадбавок.КоличествоМесяцевДляДостиженияВторогоОграничения,
ШкалаНадбавок.КоличествоМесяцевДляДостиженияПервогоОграничения,
ВЫБОР
КОГДА РаботникиИСтажи.НачальныйПроцентСевернойНадбавки >= ШкалаНадбавок.Ограничение2 И ШкалаНадбавок.Ограничение2 > 0 ТОГДА 0
КОГДА РаботникиИСтажи.НачальныйПроцентСевернойНадбавки >= ШкалаНадбавок.Ограничение1 И ШкалаНадбавок.Ограничение2 > 0 ТОГДА ШкалаНадбавок.РазмерПериода2 * (ШкалаНадбавок.Ограничение2 - РаботникиИСтажи.НачальныйПроцентСевернойНадбавки) / ШкалаНадбавок.РазмерПрироста2
КОГДА РаботникиИСтажи.НачальныйПроцентСевернойНадбавки >= 0 ТОГДА ШкалаНадбавок.РазмерПериода1 * (ШкалаНадбавок.Ограничение1 - РаботникиИСтажи.НачальныйПроцентСевернойНадбавки) / ШкалаНадбавок.РазмерПрироста1 + ШкалаНадбавок.КоличествоМесяцевДляДостиженияВторогоОграничения
ИНАЧЕ ШкалаНадбавок.КоличествоМесяцевДляДостиженияВторогоОграничения + ШкалаНадбавок.КоличествоМесяцевДляДостиженияПервогоОграничения
КОНЕЦ КАК РеальноеКоличествоМесяцевДляДостиженияВторогоОграничения,
ВЫБОР
КОГДА РаботникиИСтажи.НачальныйПроцентСевернойНадбавки >= ШкалаНадбавок.Ограничение1 ТОГДА 0
КОГДА РаботникиИСтажи.НачальныйПроцентСевернойНадбавки >= 0 ТОГДА ШкалаНадбавок.РазмерПериода1 * (ШкалаНадбавок.Ограничение1 - РаботникиИСтажи.НачальныйПроцентСевернойНадбавки) / ШкалаНадбавок.РазмерПрироста1
ИНАЧЕ ШкалаНадбавок.КоличествоМесяцевДляДостиженияПервогоОграничения
КОНЕЦ КАК РеальноеКоличествоМесяцевДляДостиженияПервогоОграничения
ПОМЕСТИТЬ ДатыДостиженияОграничений
ИЗ
РаботникиИСтажи КАК РаботникиИСтажи
ЛЕВОЕ СОЕДИНЕНИЕ ШкалаНадбавок КАК ШкалаНадбавок
ПО РаботникиИСтажи.ПорядокНачисленияСеверныхНадбавок = ШкалаНадбавок.ПорядокНачисления;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ДатыДостиженияОграничений.Физлицо,
ДатыДостиженияОграничений.ПериодРаботники,
ВЫБОР
КОГДА ДатыДостиженияОграничений.Ограничение2 > 0 И ДОБАВИТЬКДАТЕ(ДатыДостиженияОграничений.ДатаНачалаОтсчетаСеверногоСтажа, МЕСЯЦ, ДатыДостиженияОграничений.РеальноеКоличествоМесяцевДляДостиженияВторогоОграничения) <= ДатыДостиженияОграничений.ПериодРаботники ТОГДА ДатыДостиженияОграничений.Ограничение2
КОГДА ДатыДостиженияОграничений.Ограничение2 > 0 И ДОБАВИТЬКДАТЕ(ДатыДостиженияОграничений.ДатаНачалаОтсчетаСеверногоСтажа, МЕСЯЦ, ДатыДостиженияОграничений.РеальноеКоличествоМесяцевДляДостиженияПервогоОграничения) <= ДатыДостиженияОграничений.ПериодРаботники ТОГДА ДатыДостиженияОграничений.Ограничение1 + (ВЫРАЗИТЬ(РАЗНОСТЬДАТ(ДОБАВИТЬКДАТЕ(ДатыДостиженияОграничений.ДатаНачалаОтсчетаСеверногоСтажа, МЕСЯЦ, ДатыДостиженияОграничений.РеальноеКоличествоМесяцевДляДостиженияПервогоОграничения), ДатыДостиженияОграничений.ПериодРаботники, МЕСЯЦ) / ДатыДостиженияОграничений.РазмерПериода2 - 0.5 КАК ЧИСЛО(15, 0))) * ДатыДостиженияОграничений.РазмерПрироста2
КОГДА ДОБАВИТЬКДАТЕ(ДатыДостиженияОграничений.ДатаНачалаОтсчетаСеверногоСтажа, МЕСЯЦ, ДатыДостиженияОграничений.РеальноеКоличествоМесяцевДляДостиженияПервогоОграничения) <= ДатыДостиженияОграничений.ПериодРаботники И ДатыДостиженияОграничений.Ограничение2 = 0 ТОГДА ДатыДостиженияОграничений.Ограничение1
КОГДА ДОБАВИТЬКДАТЕ(ДатыДостиженияОграничений.ДатаНачалаОтсчетаСеверногоСтажа, МЕСЯЦ, ДатыДостиженияОграничений.РеальноеКоличествоМесяцевДляДостиженияПервогоОграничения) > ДатыДостиженияОграничений.ПериодРаботники ТОГДА 0
ИНАЧЕ ДатыДостиженияОграничений.НачальныйПроцентСевернойНадбавки + (ВЫРАЗИТЬ(РАЗНОСТЬДАТ(ДатыДостиженияОграничений.ДатаНачалаОтсчетаСеверногоСтажа, ДатыДостиженияОграничений.ПериодРаботники, МЕСЯЦ) / ДатыДостиженияОграничений.РазмерПериода1 - 0.5 КАК ЧИСЛО(15, 0))) * ДатыДостиженияОграничений.РазмерПрироста1
КОНЕЦ КАК АктуальныйПроцентСевернойНадбавки
ИЗ
ДатыДостиженияОграничений КАК ДатыДостиженияОграничений
ГДЕ
ДатыДостиженияОграничений.ПорядокНачисления <> ЗНАЧЕНИЕ(Перечисление.ПорядокНачисленияСеверныхНадбавок.ПустаяСсылка);
Этот сложный и объемный запрос решает задачу "в лоб" математическим вычислением интервалов. Безусловно, использовать его в современных системах ЗУП 3.1 не имеет практического смысла из-за наличия готового API, однако для поддержки старых баз или уникальных отчетов этот алгоритм может сослужить хорошую службу.
Таким образом, мы выяснили, что в зависимости от поколения используемой конфигурации 1С:ЗУП, у разработчика есть выбор между лаконичным вызовом программных функций кадрового учета БСП и построением специализированных комплексных запросов.