Как выгружать ссылки не из документов при универсальном обмене
При обмене из УНФ в региональную БП возникла проблема — в региональную БП не передавался контрагент-поставщик, потому что он не участвовал в документах, а в правилах указано, что должны выгружаться только справочники, участвующие в документах.
Попробовали добавлять контрагента в заказ поставщику, но в региональной БП отсутствовал документ «Заказ поставщику», поэтому несмотря на то, что заказ поставщику был отмечен к обмену, он не уходил в региональную БП и контрагент тоже не уходил.
При записи контрагент не регистрировался в плане обмена.
Попробовал просто зарегистрировать контрагента кодом:
П = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоНаименованию("Бухгалтерия для регионов, редакция 2.1"); С = Справочники.Контрагенты.НайтиПоНаименованию("Рога и Ко"); ПланыОбмена.ЗарегистрироватьИзменения(П, С); Сообщить(П); Сообщить(С);
Но он не уходил в базу-приемник.
Отладка показала, что отправка элемента удаляется в процедуре ОбменДаннымиXDTOСервер.ВыполнитьВыгрузкуЗарегистрированныхДанных:
ЭлементДанных = ?(ЭтоСсылка, Данные.ПолучитьОбъект(), Данные); ЭлементДанных.ДополнительныеСвойства.Вставить("ПроверкаРегистрацииПередВыгрузкой"); ОбменДаннымиСобытия.ПриОтправкеДанныхКорреспонденту(ЭлементДанных, ОтправкаЭлемента, НачальнаяВыгрузкаДанных, УзелДляОбменаОбъект, Ложь);
Сделал собственный контроль, нужно ли оставлять контрагента и договор по правилам:
- Если договор по организации, участвующей в обмене, оставляем договор.
- Если у контрагента есть договор по организации, участвующей в обмене, оставляем контрагента.
Для этого сделал расширение модуля ОбменДаннымиСобытия кодом:
&Вместо("ПриОтправкеДанныхКорреспонденту") Процедура дор_ПриОтправкеДанныхКорреспонденту(ЭлементДанных, ОтправкаЭлемента, Знач СозданиеНачальногоОбраза, Знач Получатель, Знач Анализ) НачальнаяОтправкаЭлемента = ОтправкаЭлемента; ПродолжитьВызов(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель, Анализ); МД = Метаданные.НайтиПоТипу(ТипЗнч(ЭлементДанных)); Если НачальнаяОтправкаЭлемента = ОтправкаЭлементаДанных.Авто И ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить И (МД = Метаданные.Справочники.Контрагенты ИЛИ МД = Метаданные.Справочники.ДоговорыКонтрагентов) И дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям().Найти(Получатель.Ссылка) <> Неопределено Тогда Если МД = Метаданные.Справочники.Контрагенты Тогда Если ПроверитьКонтрагента(ЭлементДанных.Ссылка, Получатель.Ссылка) Тогда ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто; КонецЕсли; ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда Если ПроверитьДоговор(ЭлементДанных.Ссылка, Получатель.Ссылка) Тогда ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто; КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры Функция ПроверитьКонтрагента(Контрагент, Получатель) З = Новый Запрос( "ВЫБРАТЬ | Т.Ссылка КАК Ссылка |ИЗ | Справочник.ДоговорыКонтрагентов КАК Т | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.Организации КАК ТО | ПО Т.Организация = ТО.Организация |ГДЕ | Т.Владелец = &Контрагент | И ТО.Ссылка = &Получатель | И НЕ Т.ПометкаУдаления"); З.УстановитьПараметр("Контрагент", Контрагент); З.УстановитьПараметр("Получатель", Получатель); Выборка = З.Выполнить().Выбрать(); Возврат Выборка.Следующий(); КонецФункции Функция ПроверитьДоговор(Договор, Получатель) З = Новый Запрос( "ВЫБРАТЬ | Т.Ссылка КАК Ссылка |ИЗ | Справочник.ДоговорыКонтрагентов КАК Т | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.Организации КАК ТО | ПО Т.Организация = ТО.Организация |ГДЕ | Т.Ссылка = &Договор | И ТО.Ссылка = &Получатель | И НЕ Т.ПометкаУдаления"); З.УстановитьПараметр("Договор", Договор); З.УстановитьПараметр("Получатель", Получатель); Выборка = З.Выполнить().Выбрать(); Возврат Выборка.Следующий(); КонецФункции
Я проверяю все узлы, где есть отбор по организациям. В принципе, можно было бы помечать узлы, где нужна такая доработка галочками и в массиве возвращать только узлы с галочкой. Для быстродействия функция формирования таких узлов вынесена в модуль дор_Кэш с повторным использованием значений на время сеанса. Важно исключать узлы этой базы по флагу ЭтотУзел:
Функция УзлыПолучателиСОтборомПоОрганизациям() Экспорт З = Новый Запрос("ВЫБРАТЬ | Т.Ссылка КАК Ссылка |ИЗ | ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат КАК Т |ГДЕ | Т.ИспользоватьОтборПоОрганизациям И НЕ Т.ПометкаУдаления И НЕ Т.ЭтотУзел"); Возврат З.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"); КонецФункции
Но это оказалось не все, ведь при записи контрагента и договора нужно чтобы регистрировались изменения.
Стандартная регистрация происходит в процедуре ОбменДаннымиСобытия.ЗарегистрироватьИзменениеОбъекта. Регистрация происходит по правилам регистрации, но вмешиваться туда не стоит.
Вмешаться можно в процедуру ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена, которая создает список узлов-получателей:
Добавляем в расширение модуля ОбменДаннымиСобытия код:
&После("ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена") Процедура дор_ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры) МД = Метаданные.НайтиПоТипу(ТипЗнч(Объект)); МассивУзловДляПроверки = дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям(); Для Каждого Получатель ИЗ МассивУзловДляПроверки Цикл //Если в этот узел уже отправляем, ок Если МассивУзловРезультат.Найти(Получатель) <> Неопределено Тогда Продолжить; КонецЕсли; Если МД = Метаданные.Справочники.Контрагенты Тогда Если ПроверитьКонтрагента(Объект.Ссылка, Получатель) Тогда МассивУзловРезультат.Добавить(Получатель); КонецЕсли; ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда Если ПроверитьДоговор(Объект.Ссылка, Получатель) Тогда МассивУзловРезультат.Добавить(Получатель); КонецЕсли; КонецЕсли; КонецЦикла; КонецПроцедуры
Теперь договоры и контрагенты уходят с обменом. Правда, если записать контрагента до того, как у него завести договор, то он не уйдет при синхронизации. А если потом записать договор, контрагент уйдет кратко (ID, наименование, организация). Придется перезаписать контрагента, чтобы он ушел целиком.
UPD 2023-04-05: было замечено, что новые договора не передаются. Причина была в том, что у нового договора нет ссылки, поэтому были сделаны замены ПроверитьДоговор на ПроверитьОрганизацию:
&Вместо("ПриОтправкеДанныхКорреспонденту") Процедура дор_ПриОтправкеДанныхКорреспонденту(ЭлементДанных, ОтправкаЭлемента, Знач СозданиеНачальногоОбраза, Знач Получатель, Знач Анализ) НачальнаяОтправкаЭлемента = ОтправкаЭлемента; ПродолжитьВызов(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель, Анализ); МД = Метаданные.НайтиПоТипу(ТипЗнч(ЭлементДанных)); Если НачальнаяОтправкаЭлемента = ОтправкаЭлементаДанных.Авто И ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить И (МД = Метаданные.Справочники.Контрагенты ИЛИ МД = Метаданные.Справочники.ДоговорыКонтрагентов) И дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям().Найти(Получатель.Ссылка) <> Неопределено Тогда Если МД = Метаданные.Справочники.Контрагенты Тогда Если ПроверитьКонтрагента(ЭлементДанных.Ссылка, Получатель.Ссылка) Тогда ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто; КонецЕсли; ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда Если ПроверитьОрганизацию(ЭлементДанных.Ссылка.Организация, Получатель.Ссылка) Тогда ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто; КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры Функция ПроверитьОрганизацию(ОрганизацияОбъекта, Получатель) З = Новый Запрос( "ВЫБРАТЬ | ТО.Ссылка КАК Ссылка |ИЗ | ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.Организации КАК ТО |ГДЕ | ТО.Организация = &Организация И ТО.Ссылка = &Получатель | "); З.УстановитьПараметр("Организация", ОрганизацияОбъекта); З.УстановитьПараметр("Получатель", Получатель); Выборка = З.Выполнить().Выбрать(); Возврат Выборка.Следующий(); КонецФункции &После("ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена") Процедура дор_ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры) МД = Метаданные.НайтиПоТипу(ТипЗнч(Объект)); МассивУзловДляПроверки = дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям(); Для Каждого Получатель ИЗ МассивУзловДляПроверки Цикл //Если в этот узел уже отправляем, ок Если МассивУзловРезультат.Найти(Получатель) <> Неопределено Тогда Продолжить; КонецЕсли; Если МД = Метаданные.Справочники.Контрагенты Тогда Если ПроверитьКонтрагента(Объект.Ссылка, Получатель) Тогда МассивУзловРезультат.Добавить(Получатель); КонецЕсли; ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда //Если ПроверитьДоговор(Объект.Организация, Получатель) Тогда Если ПроверитьОрганизацию(Объект.Организация, Получатель) Тогда МассивУзловРезультат.Добавить(Получатель); КонецЕсли; КонецЕсли; КонецЦикла; КонецПроцедуры
Среда: УНФ 3.0.4.88 Объем: 2 час
комментария 2
[…] уже писал ранее про манипуляцию с передачей объектов вопреки […]
[…] аналогично решению для контрагентов и договоров, расширение на модуль […]