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