Как выгружать ссылки не из документов при универсальном обмене

При обмене из УНФ в региональную БП возникла проблема — в региональную БП не передавался контрагент-поставщик, потому что он не участвовал в документах, а в правилах указано, что должны выгружаться только справочники, участвующие в документах.

Попробовали добавлять контрагента в заказ поставщику, но в региональной БП отсутствовал документ «Заказ поставщику», поэтому несмотря на то, что заказ поставщику был отмечен к обмену, он не уходил в региональную БП и контрагент тоже не уходил.

При записи контрагент не регистрировался в плане обмена.

Попробовал просто зарегистрировать контрагента кодом:

П = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоНаименованию("Бухгалтерия для регионов, редакция 2.1");
С = Справочники.Контрагенты.НайтиПоНаименованию("Рога и Ко");
ПланыОбмена.ЗарегистрироватьИзменения(П, С);
Сообщить(П);
Сообщить(С);

Но он не уходил в базу-приемник.

Отладка показала, что отправка элемента удаляется в процедуре ОбменДаннымиXDTOСервер.ВыполнитьВыгрузкуЗарегистрированныхДанных:

ЭлементДанных = ?(ЭтоСсылка, Данные.ПолучитьОбъект(), Данные);
ЭлементДанных.ДополнительныеСвойства.Вставить("ПроверкаРегистрацииПередВыгрузкой");
ОбменДаннымиСобытия.ПриОтправкеДанныхКорреспонденту(ЭлементДанных, ОтправкаЭлемента, 
НачальнаяВыгрузкаДанных, УзелДляОбменаОбъект, Ложь);

Сделал собственный контроль, нужно ли оставлять контрагента и договор по правилам:

  1. Если договор по организации, участвующей в обмене, оставляем договор.
  2. Если у контрагента есть договор по организации, участвующей в обмене, оставляем контрагента.

Для этого сделал расширение модуля ОбменДаннымиСобытия кодом:

&Вместо("ПриОтправкеДанныхКорреспонденту")
Процедура дор_ПриОтправкеДанныхКорреспонденту(ЭлементДанных, ОтправкаЭлемента, Знач СозданиеНачальногоОбраза, Знач Получатель, Знач Анализ)
	
	НачальнаяОтправкаЭлемента = ОтправкаЭлемента;
	
	ПродолжитьВызов(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель, Анализ);
	
	МД = Метаданные.НайтиПоТипу(ТипЗнч(ЭлементДанных));
	
	Если 
		НачальнаяОтправкаЭлемента = ОтправкаЭлементаДанных.Авто И
		ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить И
		(МД = Метаданные.Справочники.Контрагенты ИЛИ МД = Метаданные.Справочники.ДоговорыКонтрагентов) И
		дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям().Найти(Получатель.Ссылка) <> Неопределено
		Тогда                                   
		
		Если МД = Метаданные.Справочники.Контрагенты Тогда  
			Если ПроверитьКонтрагента(ЭлементДанных.Ссылка, Получатель.Ссылка) Тогда
				ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто;
			КонецЕсли;
		ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда
			Если ПроверитьДоговор(ЭлементДанных.Ссылка, Получатель.Ссылка) Тогда
				ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры     

Функция ПроверитьКонтрагента(Контрагент, Получатель)
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	Т.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ДоговорыКонтрагентов КАК Т
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.Организации КАК ТО
	|		ПО Т.Организация = ТО.Организация
	|ГДЕ
	|	Т.Владелец = &Контрагент
	|	И ТО.Ссылка = &Получатель
	|	И НЕ Т.ПометкаУдаления");                               
	З.УстановитьПараметр("Контрагент", Контрагент);
	З.УстановитьПараметр("Получатель", Получатель);
	Выборка = З.Выполнить().Выбрать();
	Возврат Выборка.Следующий(); 
КонецФункции

Функция ПроверитьДоговор(Договор, Получатель)
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	Т.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ДоговорыКонтрагентов КАК Т
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.Организации КАК ТО
	|		ПО Т.Организация = ТО.Организация
	|ГДЕ
	|	Т.Ссылка = &Договор
	|	И ТО.Ссылка = &Получатель
	|	И НЕ Т.ПометкаУдаления");                               
	З.УстановитьПараметр("Договор", Договор);
	З.УстановитьПараметр("Получатель", Получатель);
	Выборка = З.Выполнить().Выбрать();
	Возврат Выборка.Следующий(); 
КонецФункции

Я проверяю все узлы, где есть отбор по организациям. В принципе, можно было бы помечать узлы, где нужна такая доработка галочками и в массиве возвращать только узлы с галочкой. Для быстродействия функция формирования таких узлов вынесена в модуль дор_Кэш с повторным использованием значений на время сеанса. Важно исключать узлы этой базы по флагу ЭтотУзел:

Функция УзлыПолучателиСОтборомПоОрганизациям() Экспорт
	З = Новый Запрос("ВЫБРАТЬ
	|	Т.Ссылка КАК Ссылка
	|ИЗ
	|	ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат КАК Т
	|ГДЕ
	|	Т.ИспользоватьОтборПоОрганизациям И НЕ Т.ПометкаУдаления И НЕ Т.ЭтотУзел");
	Возврат З.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции

Но это оказалось не все, ведь при записи контрагента и договора нужно чтобы регистрировались изменения.

Стандартная регистрация происходит в процедуре ОбменДаннымиСобытия.ЗарегистрироватьИзменениеОбъекта. Регистрация происходит по правилам регистрации, но вмешиваться туда не стоит.
Вмешаться можно в процедуру ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена, которая создает список узлов-получателей:

Добавляем в расширение модуля ОбменДаннымиСобытия код:

&После("ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена")
Процедура дор_ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры)
	МД = Метаданные.НайтиПоТипу(ТипЗнч(Объект));
	
	МассивУзловДляПроверки = дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям();
	
	Для Каждого Получатель ИЗ МассивУзловДляПроверки Цикл
		
		//Если в этот узел уже отправляем, ок
		Если МассивУзловРезультат.Найти(Получатель) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если МД = Метаданные.Справочники.Контрагенты Тогда  
			Если ПроверитьКонтрагента(Объект.Ссылка, Получатель) Тогда
				МассивУзловРезультат.Добавить(Получатель);	
			КонецЕсли;
		ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда
			Если ПроверитьДоговор(Объект.Ссылка, Получатель) Тогда
				МассивУзловРезультат.Добавить(Получатель);	
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Теперь договоры и контрагенты уходят с обменом. Правда, если записать контрагента до того, как у него завести договор, то он не уйдет при синхронизации. А если потом записать договор, контрагент уйдет кратко (ID, наименование, организация). Придется перезаписать контрагента, чтобы он ушел целиком.

UPD 2023-04-05: было замечено, что новые договора не передаются. Причина была в том, что у нового договора нет ссылки, поэтому были сделаны замены ПроверитьДоговор на ПроверитьОрганизацию:



&Вместо("ПриОтправкеДанныхКорреспонденту")
Процедура дор_ПриОтправкеДанныхКорреспонденту(ЭлементДанных, ОтправкаЭлемента, Знач СозданиеНачальногоОбраза, Знач Получатель, Знач Анализ)
	
	НачальнаяОтправкаЭлемента = ОтправкаЭлемента;
	
	ПродолжитьВызов(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель, Анализ);
	
	МД = Метаданные.НайтиПоТипу(ТипЗнч(ЭлементДанных));
	
	Если 
		НачальнаяОтправкаЭлемента = ОтправкаЭлементаДанных.Авто И
		ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить И
		(МД = Метаданные.Справочники.Контрагенты ИЛИ МД = Метаданные.Справочники.ДоговорыКонтрагентов) И
		дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям().Найти(Получатель.Ссылка) <> Неопределено
		Тогда                                   
		
		Если МД = Метаданные.Справочники.Контрагенты Тогда  
			Если ПроверитьКонтрагента(ЭлементДанных.Ссылка, Получатель.Ссылка) Тогда
				ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто;
			КонецЕсли;
		ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда
			Если ПроверитьОрганизацию(ЭлементДанных.Ссылка.Организация, Получатель.Ссылка) Тогда
				ОтправкаЭлемента = ОтправкаЭлементаДанных.Авто;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры  


Функция ПроверитьОрганизацию(ОрганизацияОбъекта, Получатель)
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	ТО.Ссылка КАК Ссылка
	|ИЗ
	|	ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.Организации КАК ТО
	|ГДЕ
	|	ТО.Организация = &Организация И ТО.Ссылка = &Получатель
	|	");                               
	З.УстановитьПараметр("Организация", ОрганизацияОбъекта);
	З.УстановитьПараметр("Получатель", Получатель);
	Выборка = З.Выполнить().Выбрать();
	Возврат Выборка.Следующий(); 
КонецФункции

&После("ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена")
Процедура дор_ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры)
	МД = Метаданные.НайтиПоТипу(ТипЗнч(Объект));
	
	МассивУзловДляПроверки = дор_Кэш.УзлыПолучателиСОтборомПоОрганизациям();
	
	Для Каждого Получатель ИЗ МассивУзловДляПроверки Цикл
		
		//Если в этот узел уже отправляем, ок
		Если МассивУзловРезультат.Найти(Получатель) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если МД = Метаданные.Справочники.Контрагенты Тогда  
			Если ПроверитьКонтрагента(Объект.Ссылка, Получатель) Тогда
				МассивУзловРезультат.Добавить(Получатель);	
			КонецЕсли;
		ИначеЕсли МД = Метаданные.Справочники.ДоговорыКонтрагентов Тогда
			//Если ПроверитьДоговор(Объект.Организация, Получатель) Тогда
			Если ПроверитьОрганизацию(Объект.Организация, Получатель) Тогда
				МассивУзловРезультат.Добавить(Получатель);	
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Среда: УНФ 3.0.4.88 Объем: 2 час

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

комментария 2

  1. 21.12.2023

    […] уже писал ранее про манипуляцию с передачей объектов вопреки […]

  2. 04.01.2024

    […] аналогично решению для контрагентов и договоров, расширение на модуль […]

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *