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