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