Почему при загрузке сообщения РИБ возникает ошибка битых ссылок и проведения документов?

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

При работе с распределенными информационными базами (РИБ) разработчики иногда сталкиваются с ситуацией, когда во время приёма файла обмена выпадает ошибка вида «В данной транзакции уже происходили ошибки» или «Выбран договор контрагента, не соответствующий организации». В отладчике при этом видно, что один из реквизитов документа содержит значение ОбъектНенайден.

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

Анализ причины: почему возникает ошибка «ОбъектНенайден»

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

Это не является проблемой для штатного механизма загрузки РИБ по следующей причине: при нормальном прочтении файла методом ПланыОбмена.ПрочитатьИзменения() платформа записывает все объекты в режиме загрузки данных. При этом у всех записываемых объектов флаг ОбменДанными.Загрузка автоматически устанавливается в значение Истина.

Посмотрим, как выглядит стандартная проверка в модуле объекта (например, в событии ПередЗаписью):


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

Если этот флаг установлен, система записывает документ «как есть», без выполнения бизнес-логики, проведения и проверок заполнения реквизитов. Ссылка на договор записывается на уровне уникального идентификатора (GUID). Даже если сам договор идет дальше по файлу, он запишется на следующих шагах транзакции, и ссылка «склеится» без каких-либо ошибок.

Ошибка появляется тогда, когда в процессе обмена вручную сбрасывается флаг ОбменДанными.Загрузка = Ложь или принудительно устанавливается режим записи в РежимЗаписиДокумента.Проведение (например, в обработчике события плана обмена ПриПолученииДанныхОтГлавного или подписках на события).

В этот момент 1С пытается выполнить полноценное проведение документа. Так как связанный справочник еще не прочитан из файла XML и не существует в базе, реквизит содержит ОбъектНенайден. Проведение завершается ошибкой, транзакция блокируется, и весь обмен останавливается.

Способ 1. Использование механизма отложенного проведения

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

Проанализируем правильный алгоритм обработки таких документов:

  1. При загрузке сообщения через ПланыОбмена.ПрочитатьИзменения() сохраняем документы в базовом режиме (с установленным флагом ОбменДанными.Загрузка = Истина).
  2. В обработчике события ПриПолученииДанныхОтГлавного или в подписке регистрируем ссылки на прилетевшие документы в специальном регистре сведений (например, «Очередь отложенного проведения»).
  3. После того как метод ПланыОбмена.ПрочитатьИзменения() успешно завершил работу и зафиксировал транзакцию, запускаем отдельную процедуру (или фоновое задание), которая выбирает документы из очереди и проводит их.

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

Способ 2. Разделение контуров обмена

Если в подчиненной базе требуется не просто проводить входящие документы, а трансформировать их (например, превращать РеализациюТоваровУслуг головного офиса в ПоступлениеТоваровУслуг филиала), целесообразно разделить транспортные каналы:

Как правильно выгружать и контролировать изменения конфигурации в РИБ

Рассмотрим случай, когда выгрузка данных выполняется программно с использованием объектов платформы. Чтобы в файл обмена корректно попадали изменения конфигурации, выгрузка должна формироваться с помощью объекта ЗаписьСообщенияСвертки / ЗаписьСообщения и менеджера планов обмена.

Пример стандартного программного кода выгрузки данных РИБ:


// Создаем запись XML и формируем файл обмена
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяФайлаОбмена);

// Создаем новое сообщение обмена
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);

// Выгружаем зарегистрированные изменения (включая изменения конфигурации)
ПланыОбмена.ЗаписатьИзменения(ЗаписьСообщения, КоличествоЭлементовВТранзакции);

// Завершаем запись
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть();

При вызове метода ПланыОбмена.ЗаписатьИзменения() платформа сама проверяет, есть ли зарегистрированные изменения конфигурации для данного узла, и помещает их в заголовок файла обмена перед данными.

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


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаОбмена);

ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML);

КонфигурацияИзменена = Ложь;

// Чтение изменений из сообщения РИБ
ПланыОбмена.ПрочитатьИзменения(ЧтениеСообщения, КоличествоЭлементовВТранзакции, КонфигурацияИзменена);

ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();

Если КонфигурацияИзменена Тогда
    // Изменения конфигурации приняты, требуется обновить конфигурацию базы данных
    // Завершаем сеанс или вызываем обновление через завершение работы системы
КонецЕсли;

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

Резюме

Для стабильной работы РИБ необходимо соблюдать базовое правило: никогда не сбрасывать ОбменДанными.Загрузка = Истина в момент выполнения метода ПрочитатьИзменения(). Любая логика проведения документов, проверки бизнес-правил или создания подчиненных объектов должна выноситься на этап отложенной обработки после полной фиксации транзакции загрузки.

← На главную