Почему не работает обработчик «После загрузки» в правилах обмена 1С:Конвертация данных 2.1?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При настройке обменов данными между конфигурациями 1С на платформе «1С:Предприятие 8» с использованием инструмента «1С:Конвертация данных 2.1» (КД 2.1) разработчики часто сталкиваются со странным поведением системы. Вы вносите изменения в обработчик события ПослеЗагрузки правила конвертации объектов (ПКО), например, пытаетесь принудительно заполнить реквизиты объекта на стороне базы-приемника. Однако при выполнении синхронизации код просто игнорируется. Более того, даже если вы специально допустите в коде грубую синтаксическую ошибку (забудете закрыть кавычку или поставить точку с запятой), обмен завершается без ошибок. Это явный признак того, что база-приемник вообще не обращается к написанному вами обработчику.

В этой статье мы подробно разберем, почему возникает эта проблема при обмене между конфигурациями, использующими Библиотеку стандартных подсистем (БСП) (например, при обмене «Управление торговлей 10.3» — «Розница 2.2»), проанализируем архитектурные особенности выполнения кода при загрузке данных и рассмотрим неочевидные нюансы работы обработчика ПослеЗагрузки.

Причина 1. Безопасность БСП и игнорирование кода из XML-файла

Рассмотрим классическую схему работы старых обменов. В КД 2.1 создавались правила обмена, которые выгружались в один XML-файл. При выгрузке данных этот файл правил мог быть прикреплен к самому файлу выгрузки, и база-приемник считывала алгоритмы прямо из него. Однако современные конфигурации, построенные на БСП (к которым относится и «Розница 2.2»), из соображений безопасности блокируют выполнение любого исполняемого кода, полученного из внешнего XML-файла данных. Это сделано для исключения возможности внедрения вредоносного кода в базу-приемник.

Для обмена БСП использует механизм, при котором правила обмена хранятся непосредственно внутри баз данных (в макетах конфигурации, специальных регистрах сведений или привязаны к узлам планов обмена). Поэтому база-приемник при загрузке выполняет только те обработчики, которые содержатся в её локально установленных правилах.

При выгрузке правил обмена из «Конвертации данных» формируется комплект файлов:

  1. ExchangeRules.xml — правила для текущей базы (базы-источника, которая осуществляет выгрузку данных).
  2. CorrespondentExchangeRules.xml — правила для базы-корреспондента (базы-приемника, которая будет осуществлять загрузку данных).
  3. RegistrationRules.xml — правила регистрации объектов.

Если вы изменили обработчик ПослеЗагрузки (который выполняется физически в базе-приемнике), эти изменения попадут в файл CorrespondentExchangeRules.xml. Выясним, как правильно применить эти изменения по шагам:

  1. Сохраните измененные правила обмена из КД 2.1 в виде комплекта файлов.
  2. Зайдите в базу-источник («Управление торговлей 10.3») и обновите там правила выгрузки, используя файл ExchangeRules.xml.
  3. Зайдите в базу-приемник («Розница 2.2») в раздел настройки синхронизации данных.
  4. Загрузите измененные правила корреспондента в базу-приемник, указав файл CorrespondentExchangeRules.xml (в зависимости от версии БСП это делается через загрузку правил в составе ZIP-архива комплекта правил или через ручное редактирование регистра ПравилаОбменаДанными).

Только после того, как обновленные правила будут физически загружены в базу-приемник, ваш код в обработчике ПослеЗагрузки начнет исполняться.

Причина 2. Ошибочное понимание момента выполнения «После загрузки»

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

  1. Платформа считывает данные объекта из XML-файла.
  2. Создается объект в оперативной памяти (свойство Объект).
  3. Реквизиты объекта заполняются значениями из файла обмена.
  4. Выполняется обработчик ПКО «После загрузки». Объект все еще находится только в оперативной памяти! Он еще не записан в базу данных. В этот момент у вас есть доступ к свойству Объект (как к объекту соответствующего типа, например, ДокументОбъект.ПеремещениеТоваров). Также доступен параметр ОбъектНайден, который указывает, существовал ли этот объект в базе до момента загрузки.
  5. Платформа выполняет попытку автоматической записи объекта в базу данных.
  6. Выполняются подписки на события базы-приемника (например, ПередЗаписью, ПриЗаписи в модуле объекта документа).
  7. Выполняется обработчик ПКО ПослеЗаписи.

Если в процессе автоматической записи на шаге 5 возникают ошибки (например, не заполнены обязательные реквизиты, не пройдена проверка в подписке на событие ПередЗаписью на стороне приемника), транзакция записи будет отменена. Объект в базу не запишется, а все изменения, которые вы сделали программно в обработчике ПослеЗагрузки, будут утеряны. При этом внешне это может выглядеть так, будто ваш обработчик просто проигнорирован.

Причина 3. Влияние настройки «Не замещать существующие объекты в приемнике»

Проанализируем ситуацию, когда в настройках ПКО установлена опция «Не замещать существующие объекты в приемнике при загрузке, если они найдены».

В этом случае поведение платформы следующее:

  1. Объект считывается из XML во временную структуру или объект в памяти.
  2. Поскольку объект уже существует в базе, платформа выполняет обработчик ПослеЗагрузки.
  3. Однако после завершения этого обработчика, следуя установленной настройке «Не замещать», платформа отменяет запись объекта в базу данных.
  4. В результате измененные вами в памяти реквизиты объекта не сохраняются.

Если вам нужно переопределить это поведение программно, используйте в обработчике ПослеЗагрузки проверку свойства ОбъектНайден и управляйте переменной Отказ:


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

Причина 4. Проблемы с передачей параметров (ПараметрыОбъекта)

Очень часто в обработчике ПослеЗагрузки пытаются прочитать параметры, переданные из источника (например, через обработчики ПКС с флагом «Передавать в параметры»).

Посмотрим на типичную ошибку: если параметр не был явно отмечен свойством «Передавать при загрузке» в настройках ПКС/ПКО в КД, то в приемнике коллекция ПараметрыОбъекта (которая представляет собой структуру) не будет содержать нужного ключа. Обращение к несуществующему ключу вернет Неопределено.

Чтобы избежать падения обмена по ошибке и проверить наличие параметров, всегда используйте безопасное чтение свойств структуры:


// Безопасное получение параметра
ИмяСкладаИсточника = Неопределено;
Если ПараметрыОбъекта <> Неопределено Тогда
    ПараметрыОбъекта.Свойство("ИмяСкладаИсточника", ИмяСкладаИсточника);
КонецЕсли;

Если ЗначениеЗаполнено(ИмяСкладаИсточника) Тогда
    // Выполняем поиск склада в приемнике по имени, переданному в параметрах
    НайденныйСклад = Справочники.Склады.НайтиПоНаименованию(ИмяСкладаИсточника);
    Если ЗначениеЗаполнено(НайденныйСклад) Тогда
        Объект.СкладПолучатель = НайденныйСклад;
    КонецЕсли;
КонецЕсли;

Причина 5. Ограничения фонового обмена и безопасного режима

Если обмен данными выполняется в автоматическом режиме (по расписанию через регламентные задания), то сеанс выполняется на сервере в неинтерактивном режиме. Любые интерактивные методы проверки выполнения кода, такие как Сообщить() или вызовы окон предупреждений, будут либо проигнорированы платформой, либо приведут к аварийному завершению работы фонового задания без вывода внятной ошибки пользователю.

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


// Запись события в журнал регистрации для проверки работы обработчика
ЗаписьЖурналаРегистрации(
    "ОбменДанными.ПослеЗагрузки",
    УровеньЖурналаРегистрации.Информация,
    Объект.Метаданные(),
    Объект.Ссылка,
    "Обработчик 'ПослеЗагрузки' запущен для объекта: " + Строка(Объект)
);

После проведения сеанса синхронизации откройте Журнал регистрации в базе-приемнике и сделайте отбор по событию «ОбменДанными.ПослеЗагрузки». Вы сразу увидите, выполнялся ли ваш код и для каких именно объектов.

Как правильно отлаживать обработчики загрузки в КД 2.1

Чтобы не гадать, почему не работают обработчики, воспользуйтесь штатным механизмом отладки КД 2.1. Разберем этот алгоритм по шагам:

  1. Откройте базу-приемник в режиме Конфигуратора.
  2. В обработке обмена данными (например, УниверсальныйОбменДаннымиXML) перейдите на вкладку «Параметры отладки».
  3. Установите флаг «Режим отладки обработчиков загрузки».
  4. Сгенерируйте модуль отладки обработчиков (платформа предложит сохранить его в виде внешнего текстового файла или внешней обработки).
  5. Откройте сгенерированную внешнюю обработку в Конфигураторе приемника, найдите интересующий вас обработчик (например, ПослеЗагрузки_ПКО_ПеремещениеТоваров) и установите на нужной строке стандартную точку останова (F9).
  6. Запустите загрузку данных. Платформа остановит выполнение кода на вашей точке останова, и вы сможете в пошаговом режиме (F11/F10) проанализировать состояние переменных, параметры объекта и логику выполнения вашего алгоритма.
← На главную