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