В процессе работы с распределенными информационными базами (РИБ) или обычными обменами через планы обмена программисты часто сталкиваются с ситуацией, когда после выполнения стандартной процедуры «Удаление помеченных объектов» в узлах обмена появляются записи с текстом «Объект не найден». Особенно странно это выглядит, когда такая проблема проявляется избирательно: например, только для документов типа ПлатежноеПоручение, в то время как другие документы удаляются «тихо». Рассмотрим подробно, почему это происходит и как навести порядок в регистрации изменений.
Для начала проанализируем, как платформа 1С:Предприятие 8 обрабатывает события обмена данными. Существует два принципиально разных состояния объекта, которые должны быть переданы в базу-приемник:
ПометкаУдаления = Истина.Удалить()), а не просто пометить. Для этого платформа создает в таблице регистрации изменений специальную запись типа УдалениеОбъекта.Поскольку физического объекта в базе уже нет, в консоли регистрации изменений и в списках выгрузки такая запись отображается как «Объект не найден» (или содержит GUID удаленного объекта). Это штатное поведение платформы, предусмотренное для поддержания идентичности данных в разных узлах.
Если вы заметили, что «Объект не найден» появляется только у определенных типов метаданных (например, у платежных поручений), значит, настройки синхронизации для них отличаются от остальных. Рассмотрим три основные причины:
ПланОбмена, перейдем на вкладку «Состав» и найдем Документ.ПлатежноеПоручение. Если в колонке «Авторегистрация» стоит значение «Разрешить», то любое физическое удаление будет автоматически фиксироваться платформой. Если у других документов стоит «Запретить», то их удаление не регистрируется автоматически, а управляется программно.ПередУдалением или ПриУдалении. Часто разработчики создают универсальные механизмы регистрации, но в правилах или условиях подписки могут быть исключения для конкретных типов документов.Если проблема уже возникла и план обмена «забит» битыми ссылками, которые вызывают ошибки при выгрузке (например, если правила обмена не умеют обрабатывать тип УдалениеОбъекта), мы можем воспользоваться программными методами очистки. Рассмотрим код, который позволяет удалить регистрацию для всех объектов, которых больше нет в базе данных:
// Пример очистки регистрации для конкретного типа документа
Процедура ОчиститьБитыеСсылкиВПланеОбмена(УзелСсылка)
ТекстЗапроса =
"ВЫБРАТЬ
| ТИзменения.Ссылка КАК Ссылка,
| ТИзменения.Узел КАК Узел
|ИЗ
| Документ.ПлатежноеПоручение.Изменения КАК ТИзменения
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПлатежноеПоручение КАК Т
| ПО ТИзменения.Ссылка = Т.Ссылка
|ГДЕ
| Т.Ссылка ЕСТЬ NULL
| И ТИзменения.Узел = &Узел";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Узел", УзелСсылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
МассивНаУдаление = Новый Массив;
Пока Выборка.Следующий() Цикл
МассивНаУдаление.Добавить(Выборка.Ссылка);
КонецЦикла;
Если МассивНаУдаление.Количество() > 0 Тогда
ПланыОбмена.УдалитьРегистрациюИзменений(УзелСсылка, МассивНаУдаление);
КонецЕсли;
КонецПроцедуры
Этот метод эффективен, когда нужно точечно исправить ситуацию. Мы используем левое соединение таблицы изменений с основной таблицей документа. Если в основной таблице запись отсутствует (ЕСТЬ NULL), значит, это то самое «Удаление объекта», которое мы хотим убрать.
Рассмотрим более радикальный, но правильный с точки зрения архитектуры способ. Если бизнес-логика вашего обмена не предполагает физического удаления документов в базе-приемнике (например, вы хотите, чтобы там оставались документы с пометкой на удаление для истории), выполним следующие шаги:
ПланОбмена.ПлатежноеПоручение установим Авторегистрация = Запретить.ПриЗаписи для этого документа.Проанализируем пример кода в обработчике подписки:
Процедура ПриЗаписиПлатежногоПорученияРегистрация(Источник, Отказ) Экспорт
// Регистрируем изменения только если это не физическое удаление
// (Хотя ПриЗаписи и так не срабатывает при удалении,
// это важно для понимания логики разделения событий)
Узлы = ПланыОбмена.ВашПланОбмена.Выбрать(); // Здесь должна быть логика подбора узлов
Пока Узлы.Следующий() Цикл
// Проверяем условия выгрузки...
ПланыОбмена.ЗарегистрироватьИзменения(Узлы.Ссылка, Источник);
КонецЦикла;
КонецПроцедуры
Если вы не уверены, какой именно механизм (платформенный или программный) ставит документ на обмен в момент удаления, выполним отладку на сервере. Поскольку обработка УдалениеПомеченныхОбъектов работает в фоновом задании или на сервере, обычная точка остановки может не сработать.
Пошаговый план отладки:
-debug у службы агента 1С).ПлатежноеПоручение в процедуре ПередУдалением.Появление «Объект не найден» — это не ошибка, а сигнал платформы о том, что данные были физически уничтожены. Чтобы устранить эти записи для документа ПлатежноеПоручение, необходимо проверить свойство «Авторегистрация» в составе плана обмена. Если ваша система обмена не справляется с обработкой удалений, используйте приведенный выше программный код для очистки таблицы Изменения от ссылок, потерявших связь с объектами.