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