///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//   НастройкаXDTO - Булево - Истина, если настраивается обмен через XDTO.
// 
// Возвращаемое значение:
//   Структура - состав настроек подключения для настройки обмена:
//     * ИмяПланаОбмена - Строка - имя плана обмена.
//     * ИмяПланаОбменаКорреспондента - Строка - имя плана обмена корреспондента.
//     * ИдентификаторНастройки - Строка - имя варианта настройки, как оно задано в модуле менеджера плана обмена.
//     * ФорматОбмена - Строка - имя формата обмена.
//     * Наименование - Строка - наименование этого приложения.
//     * НаименованиеКорреспондента - Строка - наименование приложения корреспондента.
//     * Префикс - Строка - префикс этого приложения.
//     * ПрефиксКорреспондента - Строка - префикс приложения корреспондента.
//     * ИдентификаторИнформационнойБазыИсточника - Строка - идентификатор этого приложения.
//     * ИдентификаторИнформационнойБазыПриемника - Строка - идентификатор приложения корреспондента.
//     * КонечнаяТочкаКорреспондента - ОпределяемыйТип.КонечнаяТочкаОбменаСообщениями - точка обмена сообщениями.
//     * Корреспондент - ПланОбменаСсылка - узел плана обмена.
//     * ОбластьДанныхКорреспондента - Число - номер области данных корреспондента.
//     * НастройкиXDTOКорреспондента - Структура - описание настроек формата обмена XDTO корреспондента:
//       ** ПоддерживаемыеВерсии - Массив из Строка - (опционально) набор поддерживаемых версий формата обмена.
//       ** ПоддерживаемыеОбъекты - ХранилищеЗначения - таблица поддерживаемых объектов формата.
// 
Функция ОписаниеНастроекПодключения(НастройкаXDTO) Экспорт
	
	НастройкиПодключения = Новый Структура;
	НастройкиПодключения.Вставить("ИмяПланаОбмена",               "");
	НастройкиПодключения.Вставить("ИмяПланаОбменаКорреспондента", "");
	
	НастройкиПодключения.Вставить("ИдентификаторНастройки", "");
	
	НастройкиПодключения.Вставить("ФорматОбмена", "");
	
	НастройкиПодключения.Вставить("Наименование",               "");
	НастройкиПодключения.Вставить("НаименованиеКорреспондента", "");
	
	НастройкиПодключения.Вставить("Префикс",               "");
	НастройкиПодключения.Вставить("ПрефиксКорреспондента", "");
	
	НастройкиПодключения.Вставить("ИдентификаторИнформационнойБазыИсточника", "");
	НастройкиПодключения.Вставить("ИдентификаторИнформационнойБазыПриемника", "");
	
	НастройкиПодключения.Вставить("КонечнаяТочкаКорреспондента");

	НастройкиПодключения.Вставить("Корреспондент");
	НастройкиПодключения.Вставить("ОбластьДанныхКорреспондента", 0);
	
	Если НастройкаXDTO Тогда
		НастройкиXDTOКорреспондента = Новый Структура;
		НастройкиXDTOКорреспондента.Вставить("ПоддерживаемыеВерсии", Новый Массив);
		НастройкиXDTOКорреспондента.Вставить("ПоддерживаемыеОбъекты");
		
		НастройкиПодключения.Вставить("НастройкиXDTOКорреспондента", НастройкиXDTOКорреспондента);
	КонецЕсли;
	
	Возврат НастройкиПодключения;
	
КонецФункции

#Область СписокПриложений

// Параметры:
//   Настройки - Структура - описание настроек выполнения операции.
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//   ПродолжитьОжидание - Булево - Истина, если запущена длительная операция.
//
Процедура ПриНачалеПолученияСпискаПриложений(Настройки, ПараметрыОбработчика, ПродолжитьОжидание = Истина) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса") Тогда
		Возврат;
	КонецЕсли;
		
	МодульСообщенияВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("СообщенияВМоделиСервиса");
	
	ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации();
	
	УстановитьПривилегированныйРежим(Истина);
	
	НачатьТранзакцию();
	Попытка
		// Отправляем сообщение в МС.
		Сообщение = МодульСообщенияВМоделиСервиса.НовоеСообщение(
			СообщенияАдминистрированиеОбменаДаннымиУправлениеИнтерфейс.СообщениеПолучитьНастройкиСинхронизацииДанных());
			
		// ФорматОбмена - отбор делать нельзя, т.к. нам нужна полная таблица, включая узлы с настроенной синхронизацией
		ДополнительныеСвойства = Новый Структура("Режим");
		ЗаполнитьЗначенияСвойств(ДополнительныеСвойства, Настройки);
		
		Сообщение.AdditionalInfo = СериализаторXDTO.ЗаписатьXDTO(ДополнительныеСвойства);
			
		ПараметрыОбработчика.ИдентификаторОперации = ОбменДаннымиВМоделиСервиса.ОтправитьСообщение(Сообщение);
			
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		
		СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииМониторСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Ошибка, , , СообщениеОбОшибке);
			
		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = СообщениеОбОшибке;
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
		
		ПродолжитьОжидание = Ложь;
	КонецПопытки;
	
	Если Не ПараметрыОбработчика.Отказ Тогда
		МодульСообщенияВМоделиСервиса.ДоставитьБыстрыеСообщения();
		
		Для Каждого ЭлементНастройки Из Настройки Цикл
			ПараметрыОбработчика.ДополнительныеПараметры.Вставить(ЭлементНастройки.Ключ, ЭлементНастройки.Значение);
		КонецЦикла;
		
		ПродолжитьОжидание = Истина;
	КонецЕсли;
	
КонецПроцедуры

// Параметры:
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//   ПродолжитьОжидание - Булево - Истина, если длительная операция еще не завершена.
//
Процедура ПриОжиданииПолученияСпискаПриложений(ПараметрыОбработчика, ПродолжитьОжидание = Истина) Экспорт
	
	Если ПараметрыОбработчика.ДополнительныеПараметры.Свойство("ОжиданиеСессииПолучениеПараметровКорреспондента") Тогда
		
		ПродолжитьОжидание = Ложь;
		
		ОбластиДляОпределенияКодовУзлов = ПараметрыОбработчика.ДополнительныеПараметры.ОбластиДляОпределенияКодовУзлов.Получить();
		
		Для Каждого Область Из ОбластиДляОпределенияКодовУзлов Цикл
			
			Для Каждого СтрокаКодыУзлов Из Область.КодыУзлов Цикл
				
				Если СтрокаКодыУзлов.ПродолжитьОжидание Тогда
					ПриОжиданииСессииОбменаСообщениямиСистемы(СтрокаКодыУзлов.ПараметрыОбработчика, СтрокаКодыУзлов.ПродолжитьОжидание);
				КонецЕсли;
				
				Если Не СтрокаКодыУзлов.ПродолжитьОжидание
					И Не ЗначениеЗаполнено(СтрокаКодыУзлов.КодПредопределенногоУзла)
					И Не СтрокаКодыУзлов.ПараметрыОбработчика.Отказ Тогда
					
					ПараметрыКорреспондента = РегистрыСведений.СессииОбменаСообщениямиСистемы.ПолучитьДанныеСессии(
						СтрокаКодыУзлов.ПараметрыОбработчика.ИдентификаторОперации).Получить();
						
					Если ПараметрыКорреспондента.Свойство("ПараметрыИнформационнойБазы") Тогда
						Если ПараметрыКорреспондента.ПараметрыИнформационнойБазы.УзелСуществует Тогда
							СтрокаКодыУзлов.КодПредопределенногоУзла = ПараметрыКорреспондента.ПараметрыИнформационнойБазы.КодЭтогоУзла;
						КонецЕсли;
					КонецЕсли;
					
				КонецЕсли;
				
				ПродолжитьОжидание = ПродолжитьОжидание Или СтрокаКодыУзлов.ПродолжитьОжидание;
				
			КонецЦикла;
			
		КонецЦикла;
		
		ПараметрыОбработчика.ДополнительныеПараметры.ОбластиДляОпределенияКодовУзлов =
			Новый ХранилищеЗначения(ОбластиДляОпределенияКодовУзлов, Новый СжатиеДанных(9));
		
	Иначе
		ПриОжиданииСессииОбменаСообщениямиСистемы(ПараметрыОбработчика, ПродолжитьОжидание);
		
		Если Не ПродолжитьОжидание
			И Не ПараметрыОбработчика.Отказ Тогда
			
			НастройкиСинхронизацииИзМенеджераСервиса = Неопределено;
			
			УстановитьПривилегированныйРежим(Истина);
			Попытка
				НастройкиСинхронизацииИзМенеджераСервиса = РегистрыСведений.СессииОбменаСообщениямиСистемы.ПолучитьДанныеСессии(
					ПараметрыОбработчика.ИдентификаторОперации).Получить();
			Исключение
				Информация = ИнформацияОбОшибке();
				
				ПараметрыОбработчика.Отказ = Истина;
				ПараметрыОбработчика.СообщениеОбОшибке = ОбработкаОшибок.КраткоеПредставлениеОшибки(Информация);
				ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
				
				ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииМониторСинхронизацииДанных(),
					УровеньЖурналаРегистрации.Ошибка, , , ОбработкаОшибок.ПодробноеПредставлениеОшибки(Информация));
					
				Возврат;
			КонецПопытки;
			
			УдалитьЛишниеСтрокиНастроекСинхронизации(НастройкиСинхронизацииИзМенеджераСервиса, ПараметрыОбработчика.ДополнительныеПараметры);
			
			ЕстьКодПредопределенногоУзла = НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Найти("КодПредопределенногоУзла") <> Неопределено;
			Если Не ЕстьКодПредопределенногоУзла Тогда
				НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Добавить("КодПредопределенногоУзла", Новый ОписаниеТипов("Строка"));
			КонецЕсли;
			
			СтрокиНастройкиСинхронизацииXDTO = НастройкиСинхронизацииИзМенеджераСервиса.НайтиСтроки(
				Новый Структура("ЭтоПланОбменаXDTO, СинхронизацияНастроена", Истина, Истина));
				
			ОбластиДляОпределенияКодовУзлов = Новый ТаблицаЗначений;
			ОбластиДляОпределенияКодовУзлов.Колонки.Добавить("ОбластьДанных", Новый ОписаниеТипов("Число"));
			ОбластиДляОпределенияКодовУзлов.Колонки.Добавить("ПланОбмена",    Новый ОписаниеТипов("Строка"));
			ОбластиДляОпределенияКодовУзлов.Колонки.Добавить("КодыУзлов");
				
			Для Каждого СтрокаНастройкиСинхронизацииXDTO Из СтрокиНастройкиСинхронизацииXDTO Цикл
				
				Если ЗначениеЗаполнено(СтрокаНастройкиСинхронизацииXDTO.КодПредопределенногоУзла) Тогда
					Продолжить;
				КонецЕсли;
				
				КодыУзлов = Новый ТаблицаЗначений;
				КодыУзлов.Колонки.Добавить("КодЭтогоУзла",             Новый ОписаниеТипов("Строка"));
				КодыУзлов.Колонки.Добавить("КодПредопределенногоУзла", Новый ОписаниеТипов("Строка"));
				КодыУзлов.Колонки.Добавить("ПараметрыОбработчика");
				КодыУзлов.Колонки.Добавить("ПродолжитьОжидание",       Новый ОписаниеТипов("Булево"));
				
				Запрос = Новый Запрос(
				"ВЫБРАТЬ
				|	Т.Ссылка КАК УзелОбмена
				|ИЗ
				|	#ТаблицаПланаОбмена КАК Т
				|ГДЕ
				|	НЕ Т.ЭтотУзел");
				
				Запрос.Текст = СтрЗаменить(Запрос.Текст,
					"#ТаблицаПланаОбмена", "ПланОбмена." + СтрокаНастройкиСинхронизацииXDTO.ПланОбмена);
				
				Выборка = Запрос.Выполнить().Выбрать();
				Пока Выборка.Следующий() Цикл
					КодЭтогоУзла = ОбменДаннымиСервер.ИдентификаторЭтогоУзлаДляОбмена(Выборка.УзелОбмена);
					
					ОбластьДанныхКорреспондента = РегистрыСведений.НастройкиОбменаДаннымиXDTO.ЗначениеНастройкиКорреспондента(Выборка.УзелОбмена,
						"ОбластьДанныхКорреспондента");
					
					Если СтрокаНастройкиСинхронизацииXDTO.ОбластьДанных = ОбластьДанныхКорреспондента Тогда
						СтрокаКодыУзлов = КодыУзлов.Добавить();
						СтрокаКодыУзлов.КодЭтогоУзла = КодЭтогоУзла;
						СтрокаКодыУзлов.КодПредопределенногоУзла = ОбменДаннымиСервер.ИдентификаторУзлаКорреспондентаДляОбмена(Выборка.УзелОбмена);
						СтрокаКодыУзлов.ПродолжитьОжидание = Ложь; 
						Прервать;
					КонецЕсли;
				КонецЦикла;
				
				Выборка.Сбросить();
				
				Пока Выборка.Следующий() Цикл
					КодЭтогоУзла = ОбменДаннымиСервер.ИдентификаторЭтогоУзлаДляОбмена(Выборка.УзелОбмена);
					
					Если Не КодыУзлов.Найти(КодЭтогоУзла, "КодЭтогоУзла") = Неопределено Тогда
						Продолжить;
					КонецЕсли;
					
					СтрокаКодыУзлов = КодыУзлов.Добавить();
					СтрокаКодыУзлов.КодЭтогоУзла = КодЭтогоУзла;
					СтрокаКодыУзлов.ПродолжитьОжидание = Истина;
					
				КонецЦикла;
				
				Область = ОбластиДляОпределенияКодовУзлов.Добавить();
				ЗаполнитьЗначенияСвойств(Область, СтрокаНастройкиСинхронизацииXDTO, "ОбластьДанных, ПланОбмена");
				Область.КодыУзлов = КодыУзлов;
				
			КонецЦикла;
				
			ПараметрыОбработчика.ДополнительныеПараметры.Вставить("НастройкиСинхронизацииИзМенеджераСервиса",
				Новый ХранилищеЗначения(НастройкиСинхронизацииИзМенеджераСервиса, Новый СжатиеДанных(9)));
			ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ОбластиДляОпределенияКодовУзлов",
					Новый ХранилищеЗначения(ОбластиДляОпределенияКодовУзлов, Новый СжатиеДанных(9)));
				
			Если ОбластиДляОпределенияКодовУзлов.Количество() > 0 Тогда
				
				ПриНачалеПолученияКодовУзловОбластейДанных(ПараметрыОбработчика);
				
				Если Не ПараметрыОбработчика.Отказ Тогда
					ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ОжиданиеСессииПолучениеПараметровКорреспондента");
					ПродолжитьОжидание = Истина;
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

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

#КонецОбласти

#Область СохранениеНастроекПодключения

// Параметры:
//   НастройкиПодключения - Структура - описание настроек выполнения операции.
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//   ПродолжитьОжидание - Булево - Истина, если запущена длительная операция.
//
Процедура ПриНачалеСохраненияНастроекПодключения(НастройкиПодключения, ПараметрыОбработчика, ПродолжитьОжидание = Истина) Экспорт
	
	КлючФоновогоЗадания = ОбменДаннымиСервер.КлючФоновогоЗадания(НастройкиПодключения.ИмяПланаОбмена,
		НСтр("ru = 'Настройка подключения к корреспонденту'"));

	Если ОбменДаннымиСервер.ЕстьАктивныеФоновыеЗадания(КлючФоновогоЗадания) Тогда
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Настройка подключения к корреспонденту для ""%1"" уже выполняется.'"), НастройкиПодключения.ИмяПланаОбмена);
	КонецЕсли;
		
	ПараметрыПроцедуры = Новый Структура;
	ПараметрыПроцедуры.Вставить("НастройкиПодключения", НастройкиПодключения);
	
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(Новый УникальныйИдентификатор);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Настройка подключения к корреспонденту: %1.'"), НастройкиПодключения.ИмяПланаОбмена);
	ПараметрыВыполнения.КлючФоновогоЗадания = КлючФоновогоЗадания;
	ПараметрыВыполнения.ЗапуститьНеВФоне    = Ложь;
	
	ФоновоеЗадание = ДлительныеОперации.ВыполнитьВФоне(
		"Обработки.ПомощникНастройкиСинхронизацииДанныхМеждуПриложениямиВИнтернете.НастроитьОбменШаг1_3_0_1_1",
		ПараметрыПроцедуры,
		ПараметрыВыполнения);
		
	ПриНачалеДлительнойОперации(ФоновоеЗадание, ПараметрыОбработчика, ПродолжитьОжидание);
	
	Если Не ПродолжитьОжидание
		И Не ПараметрыОбработчика.Отказ Тогда
		ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ФоновоеЗаданиеВыполнено");
		ПродолжитьОжидание = Истина;
	КонецЕсли;
	
	ПараметрыОбработчика.ДополнительныеПараметры.Вставить("НастройкиПодключения", НастройкиПодключения);
	
КонецПроцедуры

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

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

#КонецОбласти

#Область ПолучениеОбщихДанныхУзловКорреспондента

// Параметры:
//   НастройкиПодключения - Структура - описание настроек выполнения операции.
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//   ПродолжитьОжидание - Булево - Истина, если запущена длительная операция.
//
Процедура ПриНачалеПолученияОбщихДанныхУзловКорреспондента(НастройкиПодключения, ПараметрыОбработчика, ПродолжитьОжидание = Истина) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса") Тогда
		Возврат;
	КонецЕсли;
		
	МодульСообщенияВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("СообщенияВМоделиСервиса");
	
	ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации();
	ПараметрыОбработчика.ДополнительныеПараметры.Вставить("НастройкиПодключения", НастройкиПодключения);
	
	ИмяПланаОбмена              = НастройкиПодключения.ИмяПланаОбмена;
	ОбластьДанныхКорреспондента = НастройкиПодключения.ОбластьДанныхКорреспондента;
	
	УстановитьПривилегированныйРежим(Истина);
	
	НачатьТранзакцию();
	Попытка
		// Отправляем сообщение корреспонденту.
		Сообщение = МодульСообщенияВМоделиСервиса.НовоеСообщение(
			СообщенияОбменаДаннымиУправлениеИнтерфейс.СообщениеПолучитьОбщиеДанныеУзловКорреспондента());
		Сообщение.Body.CorrespondentZone = ОбластьДанныхКорреспондента;
		
		Сообщение.Body.ExchangePlan = ИмяПланаОбмена;
		
		ДополнительныеСвойства = Новый Структура;
		ДополнительныеСвойства.Вставить("Интерфейс", "3.0.1.1");
		
		Сообщение.AdditionalInfo = СериализаторXDTO.ЗаписатьXDTO(ДополнительныеСвойства);
		
		ПараметрыОбработчика.ИдентификаторОперации = ОбменДаннымиВМоделиСервиса.ОтправитьСообщение(Сообщение);
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		
		СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Ошибка, , , СообщениеОбОшибке);
			
		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = СообщениеОбОшибке;
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
		
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецПопытки;
	
	МодульСообщенияВМоделиСервиса.ДоставитьБыстрыеСообщения();
	
КонецПроцедуры

// Для внутреннего использования.
//
Процедура ПриОжиданииПолученияОбщихДанныхУзловКорреспондента(ПараметрыОбработчика, ПродолжитьОжидание = Истина) Экспорт
	
	ПриОжиданииСессииОбменаСообщениямиСистемы(ПараметрыОбработчика, ПродолжитьОжидание);
	
КонецПроцедуры

// Параметры:
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//   СтатусЗавершения - Структура - описание результата выполнения операции.
//
Процедура ПриЗавершенииПолученияОбщихДанныхУзловКорреспондента(ПараметрыОбработчика, СтатусЗавершения) Экспорт
	
	ИнициализироватьСтатусЗавершенияДлительнойОперации(СтатусЗавершения);
	
	НастройкиПодключения = ПараметрыОбработчика.ДополнительныеПараметры.НастройкиПодключения;
	
	Если ПараметрыОбработчика.Отказ Тогда
		ЗаполнитьЗначенияСвойств(СтатусЗавершения, ПараметрыОбработчика, "Отказ, СообщениеОбОшибке");
	Иначе
		Результат = Новый Структура;
		Результат.Вставить("ПараметрыКорреспондентаПолучены", Истина);
		Результат.Вставить("ПараметрыКорреспондента");
		Результат.Вставить("СообщениеОбОшибке", "");
		
		УстановитьПривилегированныйРежим(Истина);
		
		Попытка
			// Параметры корреспондента.
			ДанныеКорреспондента = РегистрыСведений.СессииОбменаСообщениямиСистемы.ПолучитьДанныеСессии(
				ПараметрыОбработчика.ИдентификаторОперации).Получить();
				
			Если Не ДанныеКорреспондента.Свойство("ПараметрыИнформационнойБазы", Результат.ПараметрыКорреспондента) Тогда
				Результат.СообщениеОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Не поддерживается версия 3.0.1.1 интерфейса ""ОбменДанными"".
					|Для настройки подключения обновите программу ""%1"", или начните настройку из нее.'"),
					НастройкиПодключения.НаименованиеКорреспондента);
				Результат.ПараметрыКорреспондентаПолучены = Ложь;
			КонецЕсли;
			
			СтатусЗавершения.Результат = Результат;
			
		Исключение
			СтатусЗавершения.Отказ = Истина;
			СтатусЗавершения.СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
			
			ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
				УровеньЖурналаРегистрации.Ошибка, , , СтатусЗавершения.СообщениеОбОшибке);
			
			Возврат;
		КонецПопытки;
	КонецЕсли;
	
	ПараметрыОбработчика = Неопределено;
	
КонецПроцедуры

#КонецОбласти

#Область УдалениеНастройкиСинхронизацииДанных

// Для внутреннего использования.
//
Процедура ПриНачалеУдаленияНастройкиСинхронизации(НастройкиУдаления, ПараметрыОбработчика, ПродолжитьОжидание) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса") Тогда
		Возврат;
	КонецЕсли;
		
	МодульСообщенияВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("СообщенияВМоделиСервиса");
	
	ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации();
	
	УстановитьПривилегированныйРежим(Истина);
	
	НачатьТранзакцию();
	Попытка
		// Отправляем сообщение Менеджеру сервиса.
		Сообщение = МодульСообщенияВМоделиСервиса.НовоеСообщение(
			СообщенияАдминистрированиеОбменаДаннымиУправлениеИнтерфейс.СообщениеОтключитьСинхронизацию());
			
		Сообщение.Body.CorrespondentZone = НастройкиУдаления.ОбластьДанныхКорреспондента;
		Сообщение.Body.ExchangePlan      = НастройкиУдаления.ИмяПланаОбмена;
		
		ПараметрыОбработчика.ИдентификаторОперации = ОбменДаннымиВМоделиСервиса.ОтправитьСообщение(Сообщение);
		
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Отключение синхронизации данных ""%1"" с приложением ""%2"".'"),
			НастройкиУдаления.ИмяПланаОбмена, XMLСтрока(НастройкиУдаления.ОбластьДанныхКорреспондента));
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Информация, , , ТекстСообщения);
		
		ЗафиксироватьТранзакцию();
	Исключение
		
		ОтменитьТранзакцию();
		
		СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Ошибка, , , СообщениеОбОшибке);
		
		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = СообщениеОбОшибке;
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
		
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецПопытки;
	
	МодульСообщенияВМоделиСервиса.ДоставитьБыстрыеСообщения();
	ПродолжитьОжидание = Истина;
	
КонецПроцедуры

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

// Для внутреннего использования.
//
Процедура ПриЗавершенииУдаленияНастройкиСинхронизации(ПараметрыОбработчика, СтатусЗавершения) Экспорт
	
	ИнициализироватьСтатусЗавершенияДлительнойОперации(СтатусЗавершения);
	
	Если ПараметрыОбработчика.Отказ Тогда
		ЗаполнитьЗначенияСвойств(СтатусЗавершения, ПараметрыОбработчика, "Отказ, СообщениеОбОшибке");
	Иначе
		
		Результат = Новый Структура;
		Результат.Вставить("НастройкаУдалена",                 Истина);
		Результат.Вставить("НастройкаУдаленаВКорреспонденте",  Истина);
		Результат.Вставить("СообщениеОбОшибке",                "");
		Результат.Вставить("СообщениеОбОшибкеВКорреспонденте", "");
		
		СтатусЗавершения.Результат = Результат;
		
	КонецЕсли;
	
	ПараметрыОбработчика = Неопределено;
	
КонецПроцедуры

#КонецОбласти

#Область ИзменениеТранспорта

// Для внутреннего использования.
//
Процедура ПриНачалеОтключенияОтМС(Настройки, ПараметрыОбработчика, ПродолжитьОжидание) Экспорт
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса") Тогда
		Возврат;
	КонецЕсли;
		
	МодульСообщенияВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("СообщенияВМоделиСервиса");
	
	ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации();
	
	УстановитьПривилегированныйРежим(Истина);
	
	НачатьТранзакцию();
	Попытка
		// Отправляем сообщение Менеджеру сервиса.
		Сообщение = МодульСообщенияВМоделиСервиса.НовоеСообщение(
			СообщенияАдминистрированиеОбменаДаннымиУправлениеИнтерфейс.СообщениеОтключитьСинхронизациюЧерезМС());
			
		Сообщение.Body.CorrespondentZone = Настройки.ОбластьДанныхКорреспондента;
		Сообщение.Body.ExchangePlan      = Настройки.ИмяПланаОбмена;
				
		ПараметрыОбработчика.ИдентификаторОперации = ОбменДаннымиВМоделиСервиса.ОтправитьСообщение(Сообщение);
		
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Отключение синхронизации данных через менеджер сервиса (переход на веб-сервис) ""%1"" с приложением ""%2"".'"),
			Настройки.ИмяПланаОбмена, XMLСтрока(Настройки.ОбластьДанныхКорреспондента));
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Информация, , , ТекстСообщения);
		
		ЗафиксироватьТранзакцию();
	Исключение
		
		ОтменитьТранзакцию();
		
		СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Ошибка, , , СообщениеОбОшибке);
		
		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = СообщениеОбОшибке;
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
		
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецПопытки;
	
	МодульСообщенияВМоделиСервиса.ДоставитьБыстрыеСообщения();
	ПродолжитьОжидание = Истина;
	
КонецПроцедуры

// Для внутреннего использования.
//
Процедура ПриОжиданииОтключенияОтМС(ПараметрыОбработчика, ПродолжитьОжидание) Экспорт
	
	ПриОжиданииСессииОбменаСообщениямиСистемы(ПараметрыОбработчика, ПродолжитьОжидание);
	
КонецПроцедуры

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

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

#Область СессииОбменаСообщениями

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

Функция СтатусСессии(Знач Сессия)
	
	УстановитьПривилегированныйРежим(Истина);
	
	Возврат РегистрыСведений.СессииОбменаСообщениямиСистемы.СтатусСессии(Сессия);
	
КонецФункции

Функция ОписаниеОшибкиСессии(Знач Сессия)
	
	УстановитьПривилегированныйРежим(Истина);
	
	Возврат РегистрыСведений.СессииОбменаСообщениямиСистемы.ОписаниеОшибкиСессии(Сессия);
	
КонецФункции 

#КонецОбласти

#Область РаботаСДлительнымиОперациями

// Для внутреннего использования.
//
Процедура ПриНачалеДлительнойОперации(ФоновоеЗадание, ПараметрыОбработчика, ПродолжитьОжидание = Истина)
	
	ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации(ФоновоеЗадание);
	
	Если ФоновоеЗадание.Статус = "Выполняется" Тогда
		ПараметрыОбработчика.АдресРезультата       = ФоновоеЗадание.АдресРезультата;
		ПараметрыОбработчика.ИдентификаторОперации = ФоновоеЗадание.ИдентификаторЗадания;
		ПараметрыОбработчика.ДлительнаяОперация    = Истина;
		
		ПродолжитьОжидание = Истина;
		Возврат;
	ИначеЕсли ФоновоеЗадание.Статус = "Выполнено" Тогда
		ПараметрыОбработчика.АдресРезультата    = ФоновоеЗадание.АдресРезультата;
		ПараметрыОбработчика.ДлительнаяОперация = Ложь;
		
		ПродолжитьОжидание = Ложь;
		Возврат;
	Иначе
		ПараметрыОбработчика.СообщениеОбОшибке = ФоновоеЗадание.КраткоеПредставлениеОшибки;
		Если ЗначениеЗаполнено(ФоновоеЗадание.ПодробноеПредставлениеОшибки) Тогда
			ПараметрыОбработчика.СообщениеОбОшибке = ФоновоеЗадание.ПодробноеПредставлениеОшибки;
		КонецЕсли;
		
		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.ДлительнаяОперация = Ложь;
		
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецЕсли;
	
КонецПроцедуры

// Для внутреннего использования.
//
Процедура ПриОжиданииДлительнойОперации(ПараметрыОбработчика, ПродолжитьОжидание = Истина)
	
	Если ПараметрыОбработчика.Отказ
		Или Не ПараметрыОбработчика.ДлительнаяОперация Тогда
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецЕсли;
	
	ЗаданиеВыполнено = Ложь;
	Попытка
		ЗаданиеВыполнено = ДлительныеОперации.ЗаданиеВыполнено(ПараметрыОбработчика.ИдентификаторОперации);
	Исключение
		ПараметрыОбработчика.Отказ             = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиСервер.СобытиеЖурналаРегистрацииСозданиеОбменаДанными(),
			УровеньЖурналаРегистрации.Ошибка, , , ПараметрыОбработчика.СообщениеОбОшибке);
	КонецПопытки;
		
	Если ПараметрыОбработчика.Отказ Тогда
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецЕсли;
	
	ПродолжитьОжидание = Не ЗаданиеВыполнено;
	
КонецПроцедуры

Функция ПараметрыОбработчикаДлительнойОперации(ФоновоеЗадание = Неопределено)
	
	ПараметрыОбработчика = Новый Структура;
	ПараметрыОбработчика.Вставить("ФоновоеЗадание",          ФоновоеЗадание);
	ПараметрыОбработчика.Вставить("Отказ",                   Ложь);
	ПараметрыОбработчика.Вставить("СообщениеОбОшибке",       "");
	ПараметрыОбработчика.Вставить("ДлительнаяОперация",      Ложь);
	ПараметрыОбработчика.Вставить("ИдентификаторОперации",   Неопределено);
	ПараметрыОбработчика.Вставить("АдресРезультата",         Неопределено);
	ПараметрыОбработчика.Вставить("ДополнительныеПараметры", Новый Структура);
	
	Возврат ПараметрыОбработчика;
	
КонецФункции

Процедура ИнициализироватьСтатусЗавершенияДлительнойОперации(СтатусЗавершения)
	
	СтатусЗавершения = Новый Структура;
	СтатусЗавершения.Вставить("Отказ",             Ложь);
	СтатусЗавершения.Вставить("СообщениеОбОшибке", "");
	СтатусЗавершения.Вставить("Результат",         Неопределено);

КонецПроцедуры

#КонецОбласти

// Параметры:
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//
Процедура ПриНачалеПолученияКодовУзловОбластейДанных(ПараметрыОбработчика)
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса") Тогда
		Возврат;
	КонецЕсли;
		
	МодульСообщенияВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("СообщенияВМоделиСервиса");
	
	ОбластиДляОпределенияКодовУзлов = ПараметрыОбработчика.ДополнительныеПараметры.ОбластиДляОпределенияКодовУзлов.Получить();
	
	УстановитьПривилегированныйРежим(Истина);
	
	Для Каждого Область Из ОбластиДляОпределенияКодовУзлов Цикл
		
		Для Каждого СтрокаКодыУзлов Из Область.КодыУзлов Цикл
			
			Если Не СтрокаКодыУзлов.ПродолжитьОжидание Тогда
				Продолжить;
			КонецЕсли;
			
			СтрокаКодыУзлов.ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации();
		
			НачатьТранзакцию();
			Попытка
				Сообщение = МодульСообщенияВМоделиСервиса.НовоеСообщение(
					СообщенияОбменаДаннымиУправлениеИнтерфейс.СообщениеПолучитьПараметрыУчетаКорреспондента());
					
				Сообщение.Body.ExchangePlan      = Область.ПланОбмена;
				Сообщение.Body.CorrespondentCode = СтрокаКодыУзлов.КодЭтогоУзла;
				
				Сообщение.Body.CorrespondentZone = Область.ОбластьДанных;
				
				ДополнительныеСвойства = Новый Структура;
				ДополнительныеСвойства.Вставить("Интерфейс", "3.0.1.1");
				
				Сообщение.AdditionalInfo = СериализаторXDTO.ЗаписатьXDTO(ДополнительныеСвойства);
			
				СтрокаКодыУзлов.ПараметрыОбработчика.ИдентификаторОперации = ОбменДаннымиВМоделиСервиса.ОтправитьСообщение(Сообщение);
					
				ЗафиксироватьТранзакцию();
			Исключение
				ОтменитьТранзакцию();
				
				СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
				
				ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииМониторСинхронизацииДанных(),
					УровеньЖурналаРегистрации.Ошибка, , , СообщениеОбОшибке);
					
				ПараметрыОбработчика.Отказ = Истина;
				ПараметрыОбработчика.СообщениеОбОшибке = СообщениеОбОшибке;
				ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
				
				Прервать;
			КонецПопытки;
			
		КонецЦикла;
		
		Если ПараметрыОбработчика.Отказ Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	Если Не ПараметрыОбработчика.Отказ Тогда
		МодульСообщенияВМоделиСервиса.ДоставитьБыстрыеСообщения();
	КонецЕсли;
	
	ПараметрыОбработчика.ДополнительныеПараметры.ОбластиДляОпределенияКодовУзлов =
		Новый ХранилищеЗначения(ОбластиДляОпределенияКодовУзлов, Новый СжатиеДанных(9));
	
КонецПроцедуры

Процедура ПриНачалеСохраненияНастройкиОбменаВМенеджереСервиса(НастройкиПодключения, ПараметрыОбработчика, ПродолжитьОжидание)
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса") Тогда
		Возврат;
	КонецЕсли;
		
	МодульСообщенияВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("СообщенияВМоделиСервиса");
	
	ПараметрыОбработчика = ПараметрыОбработчикаДлительнойОперации();
	
	ИмяПланаОбмена              = НастройкиПодключения.ИмяПланаОбмена;
	ОбластьДанныхКорреспондента = НастройкиПодключения.ОбластьДанныхКорреспондента;
	
	УстановитьПривилегированныйРежим(Истина);
	
	НачатьТранзакцию();
	Попытка
		// Отправляем сообщение менеджеру сервиса - включить синхронизацию.
		Сообщение = МодульСообщенияВМоделиСервиса.НовоеСообщение(
			СообщенияАдминистрированиеОбменаДаннымиУправлениеИнтерфейс.СообщениеВключитьСинхронизацию());
			
		Сообщение.Body.CorrespondentZone = ОбластьДанныхКорреспондента;
		Сообщение.Body.ExchangePlan = ИмяПланаОбмена;
		
		ПараметрыОбработчика.ИдентификаторОперации = ОбменДаннымиВМоделиСервиса.ОтправитьСообщение(Сообщение);
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		
		Информация = ИнформацияОбОшибке();
		
		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Ошибка, , , ОбработкаОшибок.ПодробноеПредставлениеОшибки(Информация));
			
		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = ОбработкаОшибок.КраткоеПредставлениеОшибки(Информация);
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
		
		ПродолжитьОжидание = Ложь;
		Возврат;
	КонецПопытки;
	
	МодульСообщенияВМоделиСервиса.ДоставитьБыстрыеСообщения();
	ПродолжитьОжидание = Истина;
	
КонецПроцедуры

Функция ТаблицаПриложенийСинхронизацииДанных(Параметры)
	
	НастройкиСинхронизацииИзМенеджераСервиса = Параметры.НастройкиСинхронизацииИзМенеджераСервиса.Получить();
	ОбластиДляОпределенияКодовУзлов          = Параметры.ОбластиДляОпределенияКодовУзлов.Получить();
	
	ДоступенExchangeAdministrationManage_3_0_1_1 = ОбменДаннымиВнутренняяПубликация.ВСервисеДоступенExchangeAdministrationManage_3_0_1_1();
		
	ТаблицаПриложений = Новый ТаблицаЗначений;
	ТаблицаПриложений.Колонки.Добавить("НаименованиеПриложения", Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("Префикс",                Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("ПрефиксКорреспондента",  Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("ВерсияКорреспондента",   Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("РольКорреспондента",     Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("ИмяПланаОбмена",         Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("ФорматОбмена",           Новый ОписаниеТипов("Строка"));
	ТаблицаПриложений.Колонки.Добавить("ОбластьДанных",          Новый ОписаниеТипов("Число"));
	
	ТаблицаПриложений.Колонки.Добавить("КонечнаяТочка", Новый ОписаниеТипов("ПланОбменаСсылка.ОбменСообщениями"));
	ТаблицаПриложений.Колонки.Добавить("КонечнаяТочкаКорреспондента", Новый ОписаниеТипов("ПланОбменаСсылка.ОбменСообщениями"));
	
	ТаблицаПриложений.Колонки.Добавить("Корреспондент");
	
	ТаблицаПриложений.Колонки.Добавить("НастройкаСинхронизацииНедоступна", Новый ОписаниеТипов("Булево"));
	ТаблицаПриложений.Колонки.Добавить("СообщениеОбОшибке",                Новый ОписаниеТипов("Строка"));
	
	ТаблицаПриложений.Колонки.Добавить("ДоступенExchangeAdministrationManage_3_0_1_1",	Новый ОписаниеТипов("Булево"));
	
	Если НастройкиСинхронизацииИзМенеджераСервиса.Количество() = 0 Тогда
		Возврат ТаблицаПриложений;
	КонецЕсли;
	
	СписокСвойств = "НаименованиеПриложения,
					|Префикс,
					|ПрефиксКорреспондента,
					|ВерсияКорреспондента,
					|РольКорреспондента,
					|ФорматОбмена,
					|ОбластьДанных";
	
	Если ДоступенExchangeAdministrationManage_3_0_1_1 Тогда
		СписокСвойств = СписокСвойств + ",ДоступенExchangeAdministrationManage_3_0_1_1";
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	Для Каждого НастройкаИзМенеджераСервиса Из НастройкиСинхронизацииИзМенеджераСервиса Цикл
		
		СтрокаПриложение = ТаблицаПриложений.Добавить();
		ЗаполнитьЗначенияСвойств(СтрокаПриложение, НастройкаИзМенеджераСервиса, СписокСвойств);
		СтрокаПриложение.ИмяПланаОбмена = НастройкаИзМенеджераСервиса.ПланОбмена;
		СтрокаПриложение.КонечнаяТочкаКорреспондента = ПланыОбмена["ОбменСообщениями"].НайтиПоКоду(
			НастройкаИзМенеджераСервиса.КонечнаяТочкаКорреспондента);
			
		Если ДоступенExchangeAdministrationManage_3_0_1_1 Тогда
			СтрокаПриложение.КонечнаяТочка = ПланыОбмена["ОбменСообщениями"].НайтиПоКоду(
				НастройкаИзМенеджераСервиса.КонечнаяТочка);	
		КонецЕсли;
			
		Если СтрокаПриложение.КонечнаяТочкаКорреспондента.Пустая() Тогда
			СтрокаПриложение.НастройкаСинхронизацииНедоступна = Истина;
			СтрокаПриложение.СообщениеОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для приложения ""%1"" не найдена конечная точка с идентификатором ""%2"".'"),
				НастройкаИзМенеджераСервиса.НаименованиеПриложения,
				НастройкаИзМенеджераСервиса.КонечнаяТочкаКорреспондента);
		ИначеЕсли НастройкаИзМенеджераСервиса.НастройкаСинхронизацииВМенеджереСервиса Тогда
			СтрокаПриложение.НастройкаСинхронизацииНедоступна = Истина;
			СтрокаПриложение.СообщениеОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Конечная точка ""%1"" временно недоступна.
				|Повторите попытку позднее.'"),
				СтрокаПриложение.КонечнаяТочкаКорреспондента);
		Иначе
			Попытка
				НастройкиТранспорта = РегистрыСведений.НастройкиТранспортаОбменаОбластейДанных.НастройкиТранспорта(
					СтрокаПриложение.КонечнаяТочкаКорреспондента);
			Исключение
				Информация = ИнформацияОбОшибке();
				
				ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииНастройкаСинхронизацииДанных(),
					УровеньЖурналаРегистрации.Ошибка, , , ОбработкаОшибок.ПодробноеПредставлениеОшибки(Информация));
				
				СтрокаПриложение.НастройкаСинхронизацииНедоступна = Истина;
				СтрокаПриложение.СообщениеОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Не удалось получить настройки подключения для приложения ""%1"" по причине:
					|%2
					|Повторите попытку позднее.'"),
					НастройкаИзМенеджераСервиса.НаименованиеПриложения,
					ОбработкаОшибок.КраткоеПредставлениеОшибки(Информация));
			КонецПопытки;
		КонецЕсли;
			
		Если Не ЗначениеЗаполнено(НастройкаИзМенеджераСервиса.КодПредопределенногоУзла)
			И НастройкаИзМенеджераСервиса.ЭтоПланОбменаXDTO
			И НастройкаИзМенеджераСервиса.СинхронизацияНастроена Тогда
			
			Отбор = Новый Структура("ОбластьДанных, ПланОбмена");
			ЗаполнитьЗначенияСвойств(Отбор, НастройкаИзМенеджераСервиса);
			
			Области = ОбластиДляОпределенияКодовУзлов.НайтиСтроки(Отбор);
			Если Области.Количество() > 0 Тогда
				Область = Области[0];
				
				Для Каждого СтрокаКодыУзлов Из Область.КодыУзлов Цикл
					Если Не ЗначениеЗаполнено(СтрокаКодыУзлов.КодПредопределенногоУзла) Тогда
						Продолжить;
					КонецЕсли;
					
					НастройкаИзМенеджераСервиса.КодПредопределенногоУзла = СтрокаКодыУзлов.КодПредопределенногоУзла;
					Прервать;
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
			
		Если ЗначениеЗаполнено(НастройкаИзМенеджераСервиса.КодПредопределенногоУзла) Тогда
			СтрокаПриложение.Корреспондент = ОбменДаннымиСервер.УзелПланаОбменаПоКоду(СтрокаПриложение.ИмяПланаОбмена,
				НастройкаИзМенеджераСервиса.КодПредопределенногоУзла);
		КонецЕсли;
			
		Если Не ЗначениеЗаполнено(СтрокаПриложение.Корреспондент) Тогда
			КодУзлаМС = ОбменДаннымиВМоделиСервиса.КодУзлаПланаОбменаВСервисе(СтрокаПриложение.ОбластьДанных);	
			СтрокаПриложение.Корреспондент = ОбменДаннымиСервер.УзелПланаОбменаПоКоду(СтрокаПриложение.ИмяПланаОбмена, КодУзлаМС);
		Иначе
			
			ОбластьДанныхКорреспондента = РегистрыСведений.НастройкиОбменаДаннымиXDTO.ЗначениеНастройкиКорреспондента(СтрокаПриложение.Корреспондент,
				"ОбластьДанныхКорреспондента");
			
			Если ОбластьДанныхКорреспондента = Неопределено Тогда
				РегистрыСведений.НастройкиОбменаДаннымиXDTO.ОбновитьНастройкиКорреспондента(СтрокаПриложение.Корреспондент,
					"ОбластьДанныхКорреспондента", НастройкаИзМенеджераСервиса.ОбластьДанных);
			КонецЕсли;
			
			Если ДоступенExchangeAdministrationManage_3_0_1_1 Тогда
				РегистрыСведений.НастройкиОбменаДаннымиXDTO.ОбновитьНастройкиКорреспондента(СтрокаПриложение.Корреспондент,
					"ДоступенExchangeAdministrationManage_3_0_1_1", СтрокаПриложение.ДоступенExchangeAdministrationManage_3_0_1_1);	
			КонецЕсли;			
			
		КонецЕсли;
		
		Если Параметры.Режим = "НеНастроенныеОбмены"
			И ЗначениеЗаполнено(СтрокаПриложение.Корреспондент) Тогда
			ТаблицаПриложений.Удалить(СтрокаПриложение);
		ИначеЕсли Параметры.Режим = "НастроенныеОбмены"
			И Не ЗначениеЗаполнено(СтрокаПриложение.Корреспондент) Тогда
			ТаблицаПриложений.Удалить(СтрокаПриложение);
		КонецЕсли;
				
	КонецЦикла;
	
	Возврат ТаблицаПриложений;
	
КонецФункции

Процедура УдалитьЛишниеСтрокиНастроекСинхронизации(НастройкиСинхронизацииИзМенеджераСервиса, ДополнительныеПараметры)
	
	НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Добавить("ЭтоПланОбменаXDTO", Новый ОписаниеТипов("Булево"));
	НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Добавить("УдалитьНастройку",  Новый ОписаниеТипов("Булево"));
	
	НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Добавить("ИмяПланаОбменаДляПереходаНаНовыйОбмен",
		Новый ОписаниеТипов("Строка"));
	
	Если НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Найти("РольКорреспондента") = Неопределено Тогда	
		НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Добавить("РольКорреспондента", Новый ОписаниеТипов("Строка"));
	КонецЕсли;
	
	ЕстьВерсияКорреспондента = НастройкиСинхронизацииИзМенеджераСервиса.Колонки.Найти("ВерсияКорреспондента") <> Неопределено;
	
	Для Каждого НастройкаИзМенеджераСервиса Из НастройкиСинхронизацииИзМенеджераСервиса Цикл
		
		Если Метаданные.ПланыОбмена.Найти(НастройкаИзМенеджераСервиса.ПланОбмена) = Неопределено Тогда
			НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
			Продолжить;
		КонецЕсли;
		
		НастройкиПланаОбмена = ОбменДаннымиСервер.ЗначениеНастройкиПланаОбмена(НастройкаИзМенеджераСервиса.ПланОбмена,
			"ИмяПланаОбменаДляПереходаНаНовыйОбмен, ЭтоПланОбменаXDTO");
		ЗаполнитьЗначенияСвойств(НастройкаИзМенеджераСервиса, НастройкиПланаОбмена);
		
		Если Не ЗначениеЗаполнено(НастройкаИзМенеджераСервиса.СинхронизацияНастроена) Тогда
			НастройкаИзМенеджераСервиса.СинхронизацияНастроена = Ложь;
		КонецЕсли;
		
	КонецЦикла;
	
	Если ДополнительныеПараметры.Режим = "НеНастроенныеОбмены" Тогда
		
		НастроенныеОбмены = НастройкиСинхронизацииИзМенеджераСервиса.Скопировать(Новый Структура("СинхронизацияНастроена", Истина));
		
		// Области с настроенной синхронизацией через внутр публикацию
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	ТаблицаНастроек.Значение КАК Значение
			|ИЗ
			|	Справочник.НастройкиТранспортаСообщенийОбмена.Настройки КАК ТаблицаНастроек
			|ГДЕ
			|	ТаблицаНастроек.Настройка = ""ОбластьДанныхКорреспондента""";
		
		ОбластьДанныхВнутренняяПубликация = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Значение");
		
		Для Каждого НастройкаИзМенеджераСервиса Из НастройкиСинхронизацииИзМенеджераСервиса Цикл
			
			Если НастройкаИзМенеджераСервиса.УдалитьНастройку Тогда
				Продолжить;
			КонецЕсли;
			
			Если Не НастройкаИзМенеджераСервиса.СинхронизацияНастроена
				И НастроенныеОбмены.НайтиСтроки(Новый Структура("ОбластьДанных", НастройкаИзМенеджераСервиса.ОбластьДанных)).Количество() > 0 Тогда
				НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
				Продолжить;
			КонецЕсли;
			
			ВариантыНастроек = ОбменДаннымиСервер.ВариантыНастроекОбменаДляКорреспондента(
				НастройкаИзМенеджераСервиса.ПланОбмена,
				?(ЕстьВерсияКорреспондента, НастройкаИзМенеджераСервиса.ВерсияКорреспондента, ""),
				НастройкаИзМенеджераСервиса.РольКорреспондента);
				
			Если ВариантыНастроек.Найти(ДополнительныеПараметры.ИдентификаторНастройки) = Неопределено Тогда
				НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
				Продолжить;
			КонецЕсли;
			
			Если ОбластьДанныхВнутренняяПубликация.Найти(НастройкаИзМенеджераСервиса.ОбластьДанных) <> Неопределено Тогда
				НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
				Продолжить;
			КонецЕсли;
			
			// Исключение возможности создания новой синхронизации данных на устаревшем плане обмена.
			НастройкаИзМенеджераСервиса.УдалитьНастройку = Не НастройкаИзМенеджераСервиса.СинхронизацияНастроена
				И ЗначениеЗаполнено(НастройкаИзМенеджераСервиса.ИмяПланаОбменаДляПереходаНаНовыйОбмен);
			
		КонецЦикла;
				
	КонецЕсли;
	
	Для Каждого НастройкаИзМенеджераСервиса Из НастройкиСинхронизацииИзМенеджераСервиса.НайтиСтроки(Новый Структура("УдалитьНастройку", Ложь)) Цикл
		
		Если ДополнительныеПараметры.Режим = "НеНастроенныеОбмены" Тогда
			Если НастройкаИзМенеджераСервиса.ПланОбмена <> ДополнительныеПараметры.ИмяПланаОбмена Тогда
				НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		
		Если ДополнительныеПараметры.Режим = "НеНастроенныеОбмены"
			И НастройкаИзМенеджераСервиса.СинхронизацияНастроена Тогда
			НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
		ИначеЕсли ДополнительныеПараметры.Режим = "НастроенныеОбмены"
			И Не НастройкаИзМенеджераСервиса.СинхронизацияНастроена Тогда
			НастройкаИзМенеджераСервиса.УдалитьНастройку = Истина;
		КонецЕсли;
		
	КонецЦикла;
	
	Если НастройкиСинхронизацииИзМенеджераСервиса.Найти(Истина, "УдалитьНастройку") <> Неопределено Тогда
		НастройкиСинхронизацииИзМенеджераСервиса = НастройкиСинхронизацииИзМенеджераСервиса.Скопировать(
			Новый Структура("УдалитьНастройку", Ложь));
	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#КонецЕсли
