При выполнении регулярного обмена данными между конфигурациями (например, между 1С:Управление торговлей 10.3 и 1С:Бухгалтерия предприятия 2.0) пользователи нередко сталкиваются со сбоем процесса загрузки. В окне сообщений появляется диагностический отчет следующего содержания: Ошибка в обработчике события ПриПолученииИнформацииОбУдалении (конвертация), после чего следует описание: Ошибка при вызове метода контекста (УстановитьПометкуУдаления): Не удалось записать "Основной договор (Договоры контрагентов)"!. Процесс синхронизации аварийно прерывается, и новые документы перестают поступать в базу-приемник.
Разберем детально механизм возникновения этой неполадки, выясним, почему система не может пометить элемент на удаление, и рассмотрим пошаговые способы восстановления нормальной работы обмена.
Проанализируем механику работы планов обмена на базе универсального механизма обмена данными в формате XML. Когда в информационной базе-источнике пользователь помечает на удаление или физически удаляет элемент справочника, план обмена регистрирует это событие. В итоговый файл выгрузки помещается специальный служебный узел УдалениеОбъекта, содержащий тип метаданных и уникальный идентификатор (GUID) удаленной сущности.
В процессе загрузки в базе-приемнике типовая обработка Обработка.ОбменДаннымиXML считывает узел удаления и находит соответствующий элемент по его GUID. Далее платформа пытается выполнить программное действие через метод УстановитьПометкуУдаления(). Сбой записи при этом вызывается несколькими факторами:
УстановитьПометкуУдаления() инициирует стандартный цикл записи объекта. Если в модуле справочника или в общих подписках на события (ПередЗаписью, ПриЗаписи) не установлена проверка режима загрузки, срабатывают пользовательские валидации (контроль заполнения обязательных полей, проверка уникальности, корректность дат).Самый быстрый способ вернуть обмен в рабочее состояние без правок программного кода — отменить регистрацию сбойных элементов в базе-источнике с помощью обработки Регистрация изменений для обмена.
Разберем по шагам порядок действий:
Регистрация изменений для обмена (в обычном приложении она доступна через меню Операции - Обработки либо как внешняя обработка).Справочники, раскрываем ее и переходим к объекту Договоры контрагентов.Реализация товаров и услуг). Если в узле зарегистрированы старые документы, попадающие под дату запрета изменения в базе-приемнике, снимаем их с регистрации, чтобы обмен не пытался перезаписать закрытый период.Если в плане обмена зарегистрировано множество позиций и визуально найти виновника не удается, найдем конкретный проблемный элемент техническими средствами.
В тексте ошибки система выводит количество успешно обработанных данных, например: Было загружено: 1 911. Посмотрим, как использовать эту информацию:
.xml в текстовом редакторе (например, Notepad++).НПП="1911" или НПП="1912".ПриПолученииИнформацииОбУдалении, ищем тег УдалениеОбъекта. Внутри этого тега будет указан уникальный идентификатор:
<УдалениеОбъекта>
<Ссылка>
<ДоговорыКонтрагентов>
<УникальныйИдентификатор>a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d</УникальныйИдентификатор>
</ДоговорыКонтрагентов>
</Ссылка>
</УдалениеОбъекта>
Теперь выясним, к какому контрагенту относится данный договор в базе-приемнике. Для этого воспользуемся внешней обработкой с произвольным алгоритмом или консолью запросов в режиме «1С:Предприятие»:
Идентификатор = Новый УникальныйИдентификатор("a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d");
СсылкаНаДоговор = Справочники.ДоговорыКонтрагентов.ПолучитьСсылку(Идентификатор);
Если СсылкаНаДоговор.Пустая() Тогда
Сообщить("Договор с таким GUID в базе не существует.");
Иначе
ДоговорОбъект = СсылкаНаДоговор.ПолучитьОбъект();
Сообщить("Найден договор: " + Строка(ДоговорОбъект));
Сообщить("Владелец (контрагент): " + Строка(ДоговорОбъект.Владелец));
КонецЕсли;
Найдя договор в базе-приемнике через интерфейс, попробуем интерактивно установить на него пометку удаления. Платформа сразу выдаст диалоговое окно с точной причиной отказа (например, незаполненный вид договора, пустая валюта или наличие связанных заблокированных регистров). Исправив реквизиты элемента вручную, мы устраним препятствие для обмена.
В ситуациях, когда передавать факты удаления объектов между базами не требуется, а регистрация уже забита устаревшими записями, очистим регистрацию удалений программно. Выполним следующий код во внешней обработке в базе-источнике:
ВыбранныйУзел = ПланыОбмена.ОбменУправлениеТорговлейБухгалтерияПредприятия.НайтиПоКоду("БП");
Если ЗначениеЗаполнено(ВыбранныйУзел) Тогда
// Удаляем из очереди обмена только зарегистрированные удаления объектов
ПланыОбмена.УдалитьРегистрациюИзменений(ВыбранныйУзел, Тип("УдалениеОбъекта"));
Сообщить("Регистрация сведений об удалении объектов успешно очищена.");
Иначе
Сообщить("Узел обмена не найден, проверьте код узла!");
КонецЕсли;
Этот метод позволяет полностью сохранить к выгрузке все измененные справочники и проведенные документы, исключив только служебные команды на удаление, вызывающие критическую ошибку.
Если конфигурация базы-приемника находится на поддержке с возможностью изменения, проверим модуль объекта справочника ДоговорыКонтрагентов и зарегистрированные подписки на события. При программной установке пометки удаления обязательно должна работать проверка признака загрузки данных.
Откроем конфигуратор, найдем модуль объекта справочника ДоговорыКонтрагентов и проверим процедуры ПередЗаписью и ПриЗаписи. В самом начале процедур должен присутствовать следующий блок кода:
Процедура ПередЗаписью(Отказ)
// Блокируем пользовательские проверки и пересчеты при пакетной загрузке обмена
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Стандартные прикладные проверки конфигурации
Если ПустаяСтрока(ВидДоговора) Тогда
// Проверка заполнения...
КонецЕсли;
КонецПроцедуры
Аналогично проверим общие подписки на события, привязанные к источнику СправочникОбъект.ДоговорыКонтрагентов. Если в подписке отсутствует проверка свойства Источник.ОбменДанными.Загрузка, вызов метода УстановитьПометкуУдаления() будет неизбежно прерываться исключением при несоблюдении любого второстепенного бизнес-правила.
Если мы сопровождаем нетиповые правила обмена через конфигурацию «Конвертация данных 2.0», настроим безопасное поведение при получении команды удаления. Для этого в свойствах правил обмена данными найдем обработчик события ПриПолученииИнформацииОбУдалении и обернем вызов в блок перехвата исключений:
Попытка
// Пытаемся стандартно установить пометку удаления
Объект.УстановитьПометкуУдаления(Истина);
Исключение
// При возникновении ошибки не прерываем обмен, а фиксируем предупреждение
ТекстСообщения = "Не удалось пометить на удаление объект: " + Строка(Объект)
+ ". Причина: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Синхронизация данных", УровеньЖурналаРегистрации.Предупреждение,,, ТекстСообщения);
КонецПопытки;
// Отменяем стандартное платформенное действие, так как обработка выполнена вручную
Отказ = Истина;
Такая доработка гарантирует непрерывность выполнения регламентных процедур: даже если отдельный элемент заблокирован или поврежден, остальные объекты (банковские выписки, накладные, счета) загрузятся в полном объеме.