Доработки получаются не слишком сложными, нужно просто разобраться, где вставить заплатки. Рассмотрим пример, где рабочее время и его норма измеряется в часах.
Собственный алгоритм вычисления нормы за месяц
Норма рабочего времени за месяц вычисляется в модуле ПроведениеРасчетовПереопределямый, найти можно по идентификатору НормаВремениЗаМесяц.
В типовом коде норма вычисляется как ДанныеГрафика.ОсновноеЗначениеНормаПериодДействия. При пользовании отладчиком видно, что период действия - с 1 по 15 число, но норма считается за месяц. Это связано с тем, что период действия всегда расширяется до периодичности регистра расчета, а в данном случае это месяц. Это довольно неявно и непрозрачно, но ничего не поделаешь.
Поэтому приходится использовать запрос к регистру сведений графика, чтобы получить норму за половину месяца.
Текст заплатки получается довольно объемным, ее нужно вставить сразу перед выполнением запроса в процедуре ПолучитьДанныеДляРасчета:
Если НеобходимыеДанные.НормаВремениЗаМесяц И Регистратор.Метаданные().Имя = "НачислениеЗарплатыРаботникамОрганизаций" И Регистратор.ПериодНачисления = Перечисления.ПериодНачисленияЗарплаты.ПерваяПоловинаТекущегоМесяца Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ЕСТЬNULL(СводныеИндивидуальныеГрафики.НормаВремени,ДанныеГрафика.ОсновноеЗначениеНормаПериодДействия)",
"2 * ЕСТЬNULL(СводныеИндивидуальныеГрафики.НормаВремени,ДанныеГрафикаДоп.ОсновноеЗначениеНорма)");
//Это должно заменяться раньше чем следующие замены изза "КАК НормаВремениЗаМесяц"
Запрос.Текст = СтрЗаменить(Запрос.Текст,
"КАК НормаВремениЗаМесяц",
"КАК НормаВремениЗаМесяц" +
", ДанныеГрафикаДоп.НормаВремениЗаМесяцПоПолумесяцу КАК НормаВремениЗаМесяцПоПолумесяцу ");
Запрос.Текст = СтрЗаменить(Запрос.Текст,
"ЛЕВОЕ СОЕДИНЕНИЕ ВТСводныеИндивидуальныеГрафики КАК СводныеИндивидуальныеГрафики",
"ЛЕВОЕ СОЕДИНЕНИЕ (" +
"ВЫБРАТЬ
| Основной.Регистратор,
| Основной.НомерСтроки,
| СУММА(ВЫБОР
| КОГДА ГрафикиРаботыПоВидамВремени.Дата МЕЖДУ НАЧАПЕРИОДА(Основной.ПериодДействияНачало, МЕСЯЦ) И Основной.ПериодДействияКонец
| ТОГДА ГрафикиРаботыПоВидамВремени.ОсновноеЗначениеНорма
| ИНАЧЕ 0
| КОНЕЦ) КАК ОсновноеЗначениеНорма,
| СУММА(ВЫБОР
| КОГДА ГрафикиРаботыПоВидамВремени.Дата >= Основной.ПериодДействияНачало
| И НАЧАЛОПЕРИОДА(Основной.ПериодДействияКонец, МЕСЯЦ) = НАЧАЛОПЕРИОДА(ГрафикиРаботыПоВидамВремени.Дата, МЕСЯЦ)
| ТОГДА ГрафикиРаботыПоВидамВремени.ОсновноеЗначениеНорма
| ИНАЧЕ 0
| КОНЕЦ) КАК НормаВремениЗаМесяцПоПолумесяцу
|ИЗ
| РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций КАК Основной
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ГрафикиРаботыПоВидамВремени КАК ГрафикиРаботыПоВидамВремени
| ПО Основной.ГрафикРаботы = ГрафикиРаботыПоВидамВремени.ГрафикРаботы
| И Основной.ВидУчетаВремени = ГрафикиРаботыПоВидамВремени.ВидУчетаВремени
|ГДЕ
| Основной.Регистратор = &парамРегистратор
| И Основной.Авторасчет
|
|СГРУППИРОВАТЬ ПО
| Основной.НомерСтроки,
| Основной.Регистратор"
+ ") КАК ДанныеГрафикаДоп ПО Основной.Регистратор = ДанныеГрафикаДоп.Регистратор И ДанныеГрафикаДоп.НомерСтроки = Основной.НомерСтроки"
+ " ЛЕВОЕ СОЕДИНЕНИЕ ВТСводныеИндивидуальныеГрафики КАК СводныеИндивидуальныеГрафики"
);
ПоляЗапроса.Добавить("НормаВремениЗаМесяцПоПолумесяцу");
КонецЕсли;
Нужно не забавить добавить новое поле в результат запроса, есть нюансы по поиску сигнатур для замены, чтобы правильно связать таблицы.
Обратите внимание на НАЧАЛОПЕРИОДА(Основной.ПериодДействияНачало, МЕСЯЦ) – так надо писать, чтобы для принятых не с начала месяца сотрудников норма считалась с начала месяца, а не с периода действия, который равен дате приема сотрудника на работу.
Расчет планового аванса
Чтобы рассчитать плановый аванс, нужно также знать норму часов для сотрудника в первой половине месяца. Чтобы повторно не считать (это довольно сложно, ведь график сотрудника может меняться), лучше сохранить эти данные в дополнительных колонках табличной части Начисления документа НачислениеЗарплатыРаботникамОрганизаций.
Сохранять значения нужно в процедуре РассчитатьЗаписиНабора модуля ПроведениеРасчетовПереопределямый в конце цикла по переменной НаборЗаписейРегистра:
Если СтрокаТабличнойЧасти <> Неопределено Тогда
Попытка
СтрокаТабличнойЧасти.НормаВремениЗаМесяц = ИсходныеДанные.НормаВремениЗаМесяцПоПолумесяцу;
Исключение
КонецПопытки;;
Попытка
СтрокаТабличнойЧасти.НормаВремениЗаМесяцПоПолумесяцу = ИсходныеДанные.НормаВремениЗаМесяц;
Исключение
КонецПопытки;;
КонецЕсли;
Округление до рубля в меньшую сторону
Пожелание клиента было в округлении расчета аванса в меньшую сторону, в конец процедуры РасчитатьВсе модуля документа НачислениеЗарплатыСотрудникамОрганизации вставляем код:
Если ПериодНачисления = Перечисления.ПериодНачисленияЗарплаты.ПерваяПоловинаТекущегоМесяца Тогда
Для Каждого Строка ИЗ Начисления Цикл
Строка.Результат = ОКР(Строка.Результат, 0); //Округление
КонецЦикла;
КонецЕсли;
Удаление ненужных начислений
Практика показала, что ЗУП пытается впихнуть в аванс лишние начисления, вроде оплаты питания и т.п.
Их можно удалить, вставив код в конец процедуры ВыполнитьАвтозаполнение модуля документа НачислениеЗарплатыСотрудникамОрганизации:
//Чистим ненужные начисления для расчета аванса
Если ПериодНачисления = Перечисления.ПериодНачисленияЗарплаты.ПерваяПоловинаТекущегоМесяца Тогда
Всего = Начисления.Количество();
Для Инд = 1 ПО Всего Цикл
Строка = Начисления[Всего - Инд];
//Удаляем дополнительные первичные
Если Строка.ВидРасчета.ВидВремени = Перечисления.ВидыВремени.ДополнительноОплачиваемоеВПределахНормы И Строка.ВидРасчета.КатегорияРасчета = Справочники.КатегорииРасчетов.Первичное Тогда
//Удаляем
Начисления.Удалить(Строка);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Отчет по авансам
Соответственно, прилагаю отчет по начислениям, который вычисляет также плановый аванс.
Он делает запрос по проведенным документам начисления авансов за первую половину. Информацию берет из начислений по окладу и дополнительных увеличений начисления оклада.
Отчет работает только на измененной конфигурации, где добавлены колонки по сохраненным нормам рабочего времени за первую половину месяца. Можно адаптировать и под типовую, но тогда будет не доступен расчет планового аванса.