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