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