При автоматизации рутинных процессов в 1С:Зарплата и Управление Персоналом (ЗУП 3.1) разработчики часто сталкиваются с задачей: необходимо программно скорректировать начисление для одного или нескольких сотрудников в документе (например, «Разовое начисление»), а затем пересчитать для них НДФЛ и удержания. Традиционно пользователи делают это по кнопке «Пересчитать сотрудника» в интерфейсе, но как выполнить этот пересчет программно, не открывая саму форму документа? Разберем эту задачу по шагам.
Проанализируем ситуацию: почему простой пересчет вызывает такие сложности? Значительная часть бизнес-логики расчета и заполнения табличных частей в конфигурации жестко привязана к модулям форм. Многие общие модули являются клиентскими и требуют передачи объекта типа «Форма» или ее специфических коллекций (данных формы).
При программном расчете мы лишаемся контекста формы. К тому же, при открытии окна документа часто программно генерируются динамические колонки (например, Показатель1 и Значение1), в которые переносятся данные из связанных табличных частей. Если мы попытаемся пересчитать налог «в лоб», зависимые начисления и налоги рассчитаются неверно — исправить подобные расхождения поможет исправление расхождений по исчисленному НДФЛ в ЗУП.
Рассмотрим первый вариант обхода ограничений системы — создание «структуры-обманки». Суть заключается в том, что мы формируем на сервере структуру, которая по составу полей и коллекций полностью дублирует реквизиты формы документа.
В эту структуру мы перегружаем данные из объекта, а затем адаптируем типовые расчетные процедуры, скопированные из модуля формы, заменяя в них обращения к контексту формы на обращения к нашей структуре. Это позволяет использовать типовые методы, но требует кропотливой работы по сбору всех необходимых коллекций.
Посмотрим на более изящное и правильное решение, использующее типовой объект МенеджерРасчета. Мы можем переписать логику, которая срабатывает при нажатии на кнопку пересчета, чтобы она выполнялась полностью на сервере без привязки к форме — для автоматизации этой задачи подойдёт обработка программного пересчета отпускных и НДФЛ в ЗУП.
Разберем готовый пример кода, который позволит выполнить пересчет НДФЛ:
&НаСервере
Процедура ПересчитатьНДФЛ(Объект)
УстановитьПривилегированныйРежим(Истина);
// Создаем экземпляр менеджера расчета для нужного месяца и организации
МенеджерРасчета = РасчетЗарплатыРасширенный.СоздатьМенеджерРасчета(Объект.МесяцНачисления, Объект.Организация);
// Получаем список сотрудников из табличной части
Сотрудники = ОбщегоНазначения.ВыгрузитьКолонку(Объект.Начисления, "Сотрудник");
ФизическиеЛицаСотрудников = ОбщегоНазначения.ЗначениеРеквизитаОбъектов(Сотрудники, "ФизическоеЛицо");
ФизическиеЛица = ОбщегоНазначения.ВыгрузитьКолонку(ФизическиеЛицаСотрудников, "Значение");
// Передаем физических лиц в настройки менеджера
ЗаполнитьНастройкиМенеджераРасчета(ФизическиеЛица, МенеджерРасчета);
МенеджерРасчета.НастройкиРасчета.ФизическиеЛица = ФизическиеЛица;
// Очищаем старые данные налогов и вычетов (если расчет не отложен)
Если ОтложитьРасчетНалогаДоРасчетаЗарплатыВКонцеМесяца Тогда
Объект.НДФЛ.Очистить();
Объект.КорректировкиВыплаты.Очистить();
Объект.ПримененныеВычетыНаДетейИИмущественные.Очистить();
КонецЕсли;
// Передаем данные в менеджер расчета и инициируем пересчет
ДанныеФормыВДанныеМенеджераРасчета(МенеджерРасчета);
МенеджерРасчета.ПересчитатьНДФЛ();
// Возвращаем рассчитанные данные обратно в объект/форму
РасчетЗарплатыВДанныеФормы(МенеджерРасчета.Зарплата);
ЗаполнитьНалогиУдержания();
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Важно: Приведенные процедуры вроде ДанныеФормыВДанныеМенеджераРасчета и ЗаполнитьНастройкиМенеджераРасчета потребуется либо скопировать из модуля формы в свой серверный модуль, адаптировав под передаваемый контекст, либо вызывать из общих серверных модулей, предварительно подготовив требуемые параметры.
Выясним еще одну критически важную деталь. В ЗУП 3.1 исчисление НДФЛ и определение даты получения дохода строго привязаны к предполагаемой дате выплаты дохода. Если вы пересчитываете налог программно, вы обязаны актуализировать эту дату.
В типовых конфигурациях для этого может применяться вызов:
РасчетЗарплатыРасширенныйКлиентСервер.УстановитьПланируемуюДатуВыплаты(ВладелецФормы, ОписаниеДокумента(ВладелецФормы));
Если проигнорировать этот шаг, суммы исчисленного налога могут некорректно распределиться по периодам, что неизбежно приведет к ошибкам в отчетности — своевременно выявить проблемы поможет проверка корректности расчета НДФЛ в ЗУП.
Проанализируем последствия такого технического решения с точки зрения учета. Скрытые программные пересчеты таят в себе огромную опасность. Если документ пересчитывается без сохранения истории (без использования документа-исправления):
Если зарплата уже рассчитана и выплачена, настоятельно рекомендуется не менять текущий документ программно, а использовать типовой механизм 1С по вводу документа-исправления. Программное обновление строк оправдано только для документов текущего, еще не закрытого периода.