Как вызвать процедуру расчета документа после загрузки данных через Конвертацию данных 2.0

Программист 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При обмене данными между конфигурациями на платформе 1С:Предприятие 8.3 с использованием инструмента Конвертация данных 2.0 (КД 2.0) разработчики часто сталкиваются с ситуацией, когда данные в объект загружены, но связанные с ними расчеты не произведены. Типичный пример — документ Командировка или НачислениеЗарплаты в программе ЗУП 3.1. В интерфейсе пользователь нажимает кнопку «Рассчитать», и происходит заполнение табличных частей. Однако при программной загрузке через Универсальный обмен данными XML кнопка сама не «нажимается», а попытки вызвать процедуру формы из кода конвертации приводят к ошибкам.

Разберем подробно, почему так происходит и какими способами можно реализовать автоматический расчет документа сразу после его загрузки.

Почему нельзя просто вызвать процедуру формы

Проанализируем архитектуру работы платформы. Процесс загрузки данных через КД 2.0 происходит на сервере. В этот момент создается объект документа (ДокументОбъект), заполняются его реквизиты, и вызывается метод Записать(). Экранная форма документа при этом физически не создается и не открывается. Процедуры, расположенные в модуле формы, особенно если они помечены директивой &НаКлиенте, недоступны в серверном контексте загрузки.

Даже если процедура в модуле формы помечена как Экспортная и &НаСервере, попытка получить форму через ПолучитьФорму() на сервере внутри транзакции загрузки является избыточной и часто неработоспособной операцией, так как форма требует контекста визуализации.

Решение 1: Перенос логики в алгоритмы Конвертации данных

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

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

Пример адаптации кода. Если в форме было:


&НаСервере
Процедура РассчитатьНачисленияНаФорме()
    ПараметрыРасчета = РассчитатьЗарплатуКлиентСервер.ПараметрыДляРасчета(ЭтаФорма);
    РассчитатьЗарплатуСервер.ВыполнитьРасчет(Объект, ПараметрыРасчета);
КонецПроцедуры

То в алгоритме КД мы должны заменить обращения к форме на работу напрямую с объектом:


// В обработчике "После загрузки" ПКО вызываем алгоритм
// Передаем переменную Объект (это загружаемый ДокументОбъект)

// Текст алгоритма:
ОчиститьСообщения();
// Вместо параметров формы формируем структуру параметров вручную
ПараметрыРасчета = Новый Структура("ПерезаполнятьСреднийЗаработок, РассчитыватьЗарплату", Истина, Истина);
// Вызываем серверный метод расчета из общего модуля
РасчетЗарплатыРасширенный.Рассчитать(Объект, ПараметрыРасчета);

Важно помнить: везде, где в коде формы встречалось ЭтаФорма.Объект, в алгоритме нужно писать просто Объект. Все вспомогательные экспортные процедуры из модуля формы также придется перенести в алгоритмы или найти их аналоги в общих модулях.

Решение 2: Использование программного интерфейса (API) конфигурации

Современные конфигурации, такие как ЗУП 3.1 или ERP 2.5, проектируются с учетом разделения логики. Большинство расчетов вынесено в Общие модули или Модули менеджера. Это наиболее правильный и стабильный путь. Вместо того чтобы имитировать нажатие кнопки, мы проанализируем, какой серверный метод вызывается этой кнопкой.

Выясним причину, по которой расчет не происходит автоматически. В ПКО (Правила конвертации объектов) в обработчике После загрузки мы можем написать обращение к программному интерфейсу документа. Рассмотрим пример для документа Командировка:


// Обработчик ПКО "После загрузки"
Если Не Объект.Проведен Тогда
    // Ищем подходящий метод в общих модулях ЗУП
    // Часто это методы подсистемы ЗарплатаКадрыРасширенный
    СтруктураПараметров = ЗарплатаКадрыРасширенный.ПараметрыЗаполненияДокумента();
    ЗарплатаКадрыРасширенный.ЗаполнитьДокумент(Объект, СтруктураПараметров);
    
    // Если требуется специфический расчет среднего для командировок
    Командировки.РассчитатьКомандировку(Объект);
КонецЕсли;

Преимущество этого метода в том, что вы используете проверенный код вендора, который учитывает все зависимости и настройки учетной политики.

Решение 3: Обработка флага ОбменДанными.Загрузка

Нужно учитывать, что при загрузке через КД 2.0 у объекта устанавливается свойство ОбменДанными.Загрузка = Истина. Это отключает стандартные проверки в модуле объекта (ПередЗаписью, ПриЗаписи). Если вы хотите, чтобы документ рассчитывался «сам» при записи, вам придется внести изменения в модуль самого объекта в конфигурации-приемнике.

Посмотрим на пример кода в модуле объекта:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если ОбменДанными.Загрузка Тогда
        // Традиционно здесь стоит Возврат, и расчеты не выполняются.
        // Мы можем принудительно вызвать расчет, если это необходимо:
        РассчитатьДокументПоДаннымОбъекта(); 
    КонецЕсли;
КонецПроцедуры

Внимание: Данный подход не рекомендуется для массовой загрузки данных, так как он существенно замедляет процесс обмена и может привести к блокировкам базы данных.

Решение 4: Глобальный расчет после завершения обмена

Иногда расчет одного документа невозможен, пока не загружены другие связанные объекты (например, графики работы или сведения о плановых начислениях сотрудника). В этом случае вызывать процедуру в ПКО После загрузки преждевременно.

Проанализируем стратегию «отложенного расчета»:

  1. В процессе загрузки документов в ПКО После загрузки мы просто добавляем ссылки на загруженные документы в некую временную таблицу или массив (используя Параметры конвертации).
  2. В обработчике конвертации После загрузки данных (глобальный обработчик правил) мы перебираем этот массив.
  3. Для каждого документа вызываем процедуру расчета и записываем его.

Пример кода в глобальном обработчике:


// Обработчик "После загрузки данных" (выполняется один раз в конце)
Для Каждого СсылкаНаДок Из Параметры.СписокДокументовДляРасчета Цикл
    ДокОбъект = СсылкаНаДок.ПолучитьОбъект();
    Если ДокОбъект <> Неопределено Тогда
        // Вызываем серверный метод расчета
        ОбщийМодульРасчета.ВыполнитьПолныйПересчет(ДокОбъект);
        ДокОбъект.ОбменДанными.Загрузка = Истина; // Чтобы не срабатывали лишние проверки
        ДокОбъект.Записать();
    КонецЕсли;
КонецЦикла;

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

Для успешного вызова процедур расчета после выгрузки данных необходимо:

Выполняя эти рекомендации, мы обеспечим корректное заполнение данных в целевой системе, сохраняя целостность учета и автоматизируя рутинные операции пересчета.

← На главную