Как программно создать и рассчитать документ Оплата по среднему заработку в 1С:ЗУП 3.1?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом Управленческий учет
← На главную

При автоматизации процессов в конфигурации 1С:Зарплата и управление персоналом 3.1 программисты часто сталкиваются с необходимостью программного создания документов, которые требуют сложного расчета (например, среднего заработка или НДФЛ). Типичная ошибка — попытка вызвать экспортные процедуры формы документа напрямую с сервера или без инициализации контекста формы. Разберем подробно, как правильно решать эту задачу, основываясь на опыте разработчиков и архитектуре современных конфигураций на базе ERP 2.0.

Анализ проблемы: Почему не работает ПолучитьФорму на сервере?

Рассмотрим стандартную ситуацию: разработчик пытается создать объект документа на сервере, заполнить его реквизиты и тут же вызвать метод формы для расчета. Проанализируем типичный ошибочный код:


&НаСервере
Процедура Команда1НаСервере()
    ДокОСЗ = Документы.ОплатаПоСреднемуЗаработку.СоздатьДокумент();
    // Заполнение реквизитов
    ДокОСЗ.Сотрудник = Объект.Сотрудник;
    
    // ОШИБКА: ПолучитьФорму на сервере в управляемом приложении
    ФормаДокумента = ДокОСЗ.ПолучитьФорму("Документ.ОплатаПоСреднемуЗаработку.Форма.ФормаДокумента");
    ФормаДокумента.РассчитатьСотрудника();    
КонецПроцедуры

В этой ситуации переменная ФормаДокумента примет значение Неопределено. В управляемом приложении 1С 8.3 работа с интерфейсными объектами (формами) на сервере запрещена. Вызов метода ПолучитьФорму в серверном контексте либо вернет ошибку, либо пустую ссылку, так как форма — это клиентский объект.

Решение через клиентский контекст и запись объекта

Выясним, как можно обойти это ограничение, если нам критически важно использовать именно логику, заложенную в форме документа. Рассмотрим алгоритм, который предложили участники обсуждения:

  1. Создать и заполнить объект на сервере.
  2. Обязательно записать документ. Это необходимо, чтобы на клиенте мы могли открыть форму по ссылке (ключу объекта).
  3. Передать ссылку на клиент.
  4. На клиенте получить форму и вызвать её экспортный метод.

Посмотрим на пример реализации:


&НаСервере
Функция СоздатьИЗаписатьДокументНаСервере()
    ДокОСЗ = Документы.ОплатаПоСреднемуЗаработку.СоздатьДокумент();
    ДокОСЗ.Дата = ТекущаяДата();
    ДокОСЗ.Организация = Справочники.Организации.ОрганизацияПоУмолчанию();
    ДокОСЗ.Сотрудник = Объект.Сотрудник;
    ДокОСЗ.ФизическоеЛицо = Объект.Сотрудник.ФизическоеЛицо;
    
    // Записываем, чтобы получить ссылку
    ДокОСЗ.Записать(РежимЗаписиДокумента.Запись);
    Возврат ДокОСЗ.Ссылка;
КонецФункции

&НаКлиенте
Процедура ВыполнитьРасчет(Команда)
    СсылкаНаДокумент = СоздатьИЗаписатьДокументНаСервере();
    
    ПараметрыФормы = Новый Структура("Ключ", СсылкаНаДокумент);
    Форма = ПолучитьФорму("Документ.ОплатаПоСреднемуЗаработку.ФормаОбъекта", ПараметрыФормы);
    
    // Теперь форма инициализирована, можно вызывать экспортные методы
    // Важно: в ЗУП 3.1 метод РассчитатьСотрудника может требовать параметры
    Форма.РассчитатьСотрудника(); 
КонецПроцедуры

Важный нюанс: метод формы РассчитатьСотрудника в типовых конфигурациях часто имеет параметры, такие как Сотрудник и ОписаниеТаблицы. Параметр ОписаниеТаблицы — это внутренняя структура метаданных формы, описывающая колонки и кэш расчета. Передать её "извне" корректно бывает крайне сложно, так как она формируется при инициализации формы. Поэтому вызов методов формы из внешних обработок считается "хрупким" решением: при обновлении ЗУП состав параметров может измениться, и ваш код перестанет работать.

Рекомендуемый архитектурный подход: Работа через серверное API

Разберем более надежный способ, который не зависит от экранных форм. В ЗУП 3.1 вся логика расчета вынесена в общие модули. Чтобы программно рассчитать документ, мы должны имитировать действия, которые происходят при нажатии кнопки на форме, но на уровне сервера.

Проанализируем основные инструменты для этого:

  1. Общий модуль РасчетЗарплатыРасширенный: содержит процедуру РассчитатьДокумент(ДокументОбъект). Это универсальный механизм, который запускает цепочку расчетов для переданного объекта.
  2. Заполнение среднего заработка: для документов типа "Оплата по среднему" нужно предварительно заполнить данные о заработке за предыдущие периоды. Это делается через вызов процедур из модуля УчетСреднегоЗаработка.

Рассмотрим пример кода для серверного расчета:


// Создаем объект
НовыйДокумент = Документы.ОплатаПоСреднемуЗаработку.СоздатьДокумент();
// Заполняем основные реквизиты
ЗаполнитьЗначенияСвойств(НовыйДокумент, ДанныеДляЗаполнения);

// Инициализируем данные для расчета
// В ЗУП часто используется метод Заполнить() в модуле объекта
НовыйДокумент.Заполнить(ПараметрыЗаполнения); 

// Вызываем типовой расчет через общие модули
РасчетЗарплатыРасширенный.РассчитатьДокумент(НовыйДокумент);

// Проверяем результат и записываем
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);

Нюансы с длительными операциями

В современных версиях 1С:ЗУП 3.1 расчеты часто выполняются во внешнем фоновом задании, чтобы не блокировать интерфейс пользователя. При программном вызове методов расчета через РасчетЗарплатыРасширенный система может попытаться запустить фоновое задание.

Если вы пишете внешнюю обработку, убедитесь, что вы обрабатываете состояние завершения расчета. Если метод возвращает структуру с адресом хранилища или идентификатором задания, вам придется использовать методы модуля ДлительныеОперации, чтобы дождаться окончания расчета, прежде чем записывать документ. В противном случае вы получите проведенный документ с нулевыми суммами.

Подведем итоги

Для программного создания и расчета документа в ЗУП 3.1 придерживайтесь следующих правил:

Использование серверного API делает ваш код более устойчивым к обновлениям программы и позволяет выполнять массовое создание документов в фоновом режиме или по регламентному заданию.

← На главную