Процедура ВыполнитьСопоставлениеПоВыбранномуРеквизиту(КоличествоСопоставленных = 0, СписокКолонокСопоставления = "")

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

	Если Не ЗначениеЗаполнено(Условия.УсловиеОбъединения) Тогда
		Возврат;
	КонецЕсли;

	Если ЗначениеЗаполнено(Условия.ТабличнаяЧасть) Тогда
		ИмяСправочника = ИмяСправочника + "." + Условия.ТабличнаяЧасть;
	КонецЕсли;

	ТаблицаСопоставления = РеквизитФормыВЗначение("ТаблицаСопоставленияДанных");

	СписокКолонок = "";
	Разделитель   = "";

	Для каждого Колонка Из ТаблицаСопоставления.Колонки Цикл
		Если Колонка.Имя <> "СписокНеоднозначностей" И Колонка.Имя <> "РезультатСопоставленияСтроки" И Колонка.Имя <> "ОписаниеОшибки" Тогда
			СписокКолонок = СписокКолонок + Разделитель + Колонка.Имя;
			Разделитель   = ", ";
		КонецЕсли;
	КонецЦикла;

	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	|	&СписокКолонок
	|ПОМЕСТИТЬ ТаблицаСопоставления
	|ИЗ
	|	&ТаблицаСопоставления КАК ТаблицаСопоставления
	|;
	|
	|ВЫБРАТЬ
	|	СправочникСопоставления.Ссылка,
	|	ТаблицаСопоставления.Идентификатор
	|ИЗ
	|	ТаблицаСопоставления КАК ТаблицаСопоставления
	|		ЛЕВОЕ СОЕДИНЕНИЕ &СправочникСопоставления КАК СправочникСопоставления
	|		ПО &УсловиеОбъединения
	|ГДЕ
	|	СправочникСопоставления.Ссылка.ПометкаУдаления = ЛОЖЬ
	|	И &Условия
	|УПОРЯДОЧИТЬ ПО
	|	ТаблицаСопоставления.Идентификатор
	|ИТОГИ
	|ПО
	|	ТаблицаСопоставления.Идентификатор";

	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&СписокКолонок", СписокКолонок);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&СправочникСопоставления", "Справочник." + ИмяСправочника);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеОбъединения", Условия.УсловиеОбъединения);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Условия", ?(ПустаяСтрока(Условия.Где), "ИСТИНА", Условия.Где));
	Запрос.УстановитьПараметр("ТаблицаСопоставления", ТаблицаСопоставления);

	РезультатЗапроса = Запрос.Выполнить();
	ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

	Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
		Строка = ТаблицаСопоставления.Найти(ВыборкаДетальныеЗаписи.Идентификатор, "Идентификатор");

		Если ЗначениеЗаполнено(Строка.ОбъектСопоставления) Тогда
			Продолжить;
		КонецЕсли;

		ВыборкаДетальныеЗаписиГруппа = ВыборкаДетальныеЗаписи.Выбрать();

		Если ВыборкаДетальныеЗаписиГруппа.Количество() > 1 Тогда
			СписокНеоднозначностей = Новый СписокЗначений;
			Пока ВыборкаДетальныеЗаписиГруппа.Следующий() Цикл
				СписокНеоднозначностей.Добавить(ВыборкаДетальныеЗаписиГруппа.Ссылка);
			КонецЦикла;
			Строка.РезультатСопоставленияСтроки = ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусНеоднозначность();
			Строка.ОписаниеОшибки = СписокКолонокСопоставления;
			Строка.СписокНеоднозначностей = СписокНеоднозначностей;
		Иначе
			ВыборкаДетальныеЗаписиГруппа.Следующий();
			КоличествоСопоставленных = КоличествоСопоставленных + 1;
			Строка.РезультатСопоставленияСтроки = ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусСопоставлен();
			Строка.ОписаниеОшибки = "";
			Строка.ОбъектСопоставления = ВыборкаДетальныеЗаписиГруппа.Ссылка;
		КонецЕсли;
	КонецЦикла;

	СписокКолонокСопоставления = "";
	Разделитель = "";
	Для каждого Колонка Из СопоставитьПоКолонке Цикл
		Если Колонка.Пометка Тогда
			СписокКолонокСопоставления = СписокКолонокСопоставления + Разделитель + Колонка.Представление;
			Разделитель = ", ";
		КонецЕсли;
	КонецЦикла;
	ЗагрузкаДанныхИзФайла.ДобавитьСтатистическуюИнформацию("СопоставлениеКолонок", КоличествоСопоставленных, СписокКолонокСопоставления);

	ЗначениеВРеквизитФормы(ТаблицаСопоставления, "ТаблицаСопоставленияДанных");

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

&НаСервере


Процедура ИнициализироватьЗаменяемыеСсылки(Знач МассивСсылок)

	КоличествоСсылок = МассивСсылок.Количество();
	Если КоличествоСсылок = 0 Тогда
		ВызватьИсключение НСтр("ru = 'Выберите хотя бы один элемент для замены.'");
	КонецЕсли;

	ЦелевойЭлемент = МассивСсылок[0];
	ОсновныеМетаданные = ЦелевойЭлемент.Метаданные();
	ВыполнитьПроверкуПравДоступа("Изменение", ОсновныеМетаданные);

	Характеристики = Новый Структура("Владельцы, Иерархический, ВидИерархии", Новый Массив, Ложь);
	ЗаполнитьЗначенияСвойств(Характеристики, ОсновныеМетаданные);

	ЕстьВладельцы = Характеристики.Владельцы.Количество() > 0;
	ЕстьГруппы    = Характеристики.Иерархический И Характеристики.ВидИерархии = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов;

	ТекстЗапроса =
		"ВЫБРАТЬ
		|Ссылка КАК Ссылка,
		|&ПолеВладелец КАК Владелец,
		|&ЭтоГруппа КАК ЭтоГруппа
		|ПОМЕСТИТЬ ЗаменяемыеСсылки
		|ИЗ
		|	#ИмяТаблицы
		|ГДЕ
		|	Ссылка В (&НаборСсылок)
		|ИНДЕКСИРОВАТЬ ПО
		|	Владелец,
		|	ЭтоГруппа
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Владелец) КАК КоличествоВладельцев,
		|	МИНИМУМ(Владелец)              КАК ОбщийВладелец,
		|	МАКСИМУМ(ЭтоГруппа)            КАК ЕстьГруппы,
		|	КОЛИЧЕСТВО(Ссылка)             КАК КоличествоСсылок
		|ИЗ
		|	ЗаменяемыеСсылки
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
		|	ЦелеваяТаблица.Ссылка
		|ИЗ
		|	#ИмяТаблицы КАК ЦелеваяТаблица
		|		ЛЕВОЕ СОЕДИНЕНИЕ ЗаменяемыеСсылки КАК ЗаменяемыеСсылки
		|		ПО ЦелеваяТаблица.Ссылка = ЗаменяемыеСсылки.Ссылка
		|ГДЕ
		|	ЗаменяемыеСсылки.Ссылка ЕСТЬ NULL
		|	И &УсловиеГруппа
		|	И &УсловиеВладелец";
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяТаблицы", ОсновныеМетаданные.ПолноеИмя());
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПолеВладелец", ?(ЕстьВладельцы, "Владелец", "НЕОПРЕДЕЛЕНО"));
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ЭтоГруппа", ?(ЕстьГруппы, "ЭтоГруппа", "ЛОЖЬ"));
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеВладелец",
		?(ЕстьВладельцы, "ЦелеваяТаблица.Владелец = &Владелец", "ИСТИНА")); // @query-part
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&УсловиеГруппа",
		?(ЕстьГруппы, "НЕ ЦелеваяТаблица.ЭтоГруппа", "ИСТИНА")); // @query-part

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

	Результат = Запрос.ВыполнитьПакет();
	Условия = Результат[1].Выгрузить()[0];
	Если Условия.ЕстьГруппы Тогда
		ВызватьИсключение НСтр("ru = 'Один из заменяемых элементов является группой.
			|Группы не могут быть заменены.'");
	ИначеЕсли Условия.КоличествоВладельцев > 1 Тогда
		ВызватьИсключение НСтр("ru = 'У заменяемых элементов разные владельцы.
			|Такие элементы не могут быть заменены.'");
	ИначеЕсли Условия.КоличествоСсылок <> КоличествоСсылок Тогда
		ВызватьИсключение НСтр("ru = 'Все заменяемые элементы должны быть одного типа.'");
	КонецЕсли;

	Если Результат[2].Выгрузить().Количество() = 0 Тогда
		Если КоличествоСсылок > 1 Тогда
			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Выбранные элементы (%1) не на что заменить, т.к. нет других подходящих элементов для замены.'"),
				КоличествоСсылок);
		Иначе
			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Выбранный элемент ""%1"" не на что заменить, т.к. нет других подходящих элементов для замены.'"),
				ОбщегоНазначения.ПредметСтрокой(ЦелевойЭлемент));
		КонецЕсли;
	КонецЕсли;

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

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

////////////////////////////////////////////////////////////////////////////////
// Работа с длительными операциями

&НаКлиенте

Процедура ЗапуститьФоновоеЗаданиеКлиент()

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

	Задание = ЗапуститьФоновоеЗадание(ПараметрыМетода, УникальныйИдентификатор);

	НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
	НастройкиОжидания.ВыводитьОкноОжидания = Ложь;

	Обработчик = Новый ОписаниеОповещения("ПослеЗавершенияФоновогоЗадания", ЭтотОбъект);
	ДлительныеОперацииКлиент.ОжидатьЗавершение(Задание, Обработчик, НастройкиОжидания);

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

&НаСервереБезКонтекста

Функция ЗапуститьФоновоеЗадание(Знач ПараметрыМетода, Знач УникальныйИдентификатор)

	ИмяМетода = "ПоискИУдалениеДублей.ЗаменитьСсылки";
	НаименованиеМетода = НСтр("ru = 'Поиск и удаление дублей: Замена ссылок'");

	НастройкиЗапуска = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
	НастройкиЗапуска.НаименованиеФоновогоЗадания = НаименованиеМетода;

	Возврат ДлительныеОперации.ВыполнитьВФоне(ИмяМетода, ПараметрыМетода, НастройкиЗапуска);

КонецФункции

&НаКлиенте

Процедура ПослеЗавершенияФоновогоЗадания(Задание, ДополнительныеПараметры) Экспорт

	НастройкиМастера.ПоказатьДиалогПередЗакрытием = Ложь;
	Если Задание = Неопределено
		ИЛИ Элементы.ШагиМастера.ТекущаяСтраница = Элементы.ШагВыборЦелевогоЭлемента Тогда
		Возврат;
	КонецЕсли;

	Если Задание.Статус <> "Выполнено" Тогда
		// Фоновое задание завершено с ошибкой.
		Кратко = НСтр("ru = 'Не выполнена замена элементов по причине:'") + Символы.ПС + Задание.КраткоеПредставлениеОшибки;
		Подробно = Кратко + Символы.ПС + Символы.ПС + Задание.ПодробноеПредставлениеОшибки;
		Элементы.НадписьТекстОшибки.Заголовок = Кратко;
		Элементы.СсылкаПодробнее.Подсказка    = Подробно;
		ПерейтиНаШагМастера(Элементы.ШагВозниклаОшибка);
		Активизировать();
		Возврат;
	КонецЕсли;

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

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

&НаСервере


Процедура ПриЗакрытии(ЗавершениеРаботы)

	Если ЗавершениеРаботы Тогда
		Возврат;
	КонецЕсли;

	Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
		РазблокироватьОбъект(Объект.Ссылка, УникальныйИдентификатор);
	КонецЕсли;

	Если ОписаниеОповещенияОЗакрытии = Неопределено Тогда
		Возврат;
	КонецЕсли;

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

	Оповещение = ОписаниеОповещенияОЗакрытии;
	ОписаниеОповещенияОЗакрытии = Неопределено;

	ВыполнитьОбработкуОповещения(Оповещение, ВозвращаемоеЗначение);

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

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

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте

Процедура РеквизитПриИзменении(Элемент)

	ПриПотереГотовности(ЭтотОбъект);

	ЭтотОбъект[Элемент.Имя] = СокрЛП(ЭтотОбъект[Элемент.Имя]);

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

&НаКлиенте

Процедура ЭлектронноеПродлениеПриИзменении(Элемент)

	ОчиститьСообщения();
	ПриПотереГотовности(ЭтотОбъект);
	ПодключитьОбработчикОжидания(
			"ЭлектронноеПродлениеПриИзмененииОбработчикОжидания", 0.1, Истина);

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

&НаКлиенте

Процедура СертификатОснованиеПриИзменении(Элемент)

	ПриПотереГотовности(ЭтотОбъект);

	Если ЗначениеЗаполнено(ДанныеЗаявления.СертификатОснование) Тогда
		СкопироватьЗаявление(ДанныеЗаявления.СертификатОснование);
	КонецЕсли;

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

&НаКлиенте

Процедура СертификатОснованиеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

	ЭлектроннаяПодписьКлиент.СертификатНачалоВыбораСПодтверждением(
		Элемент, ДанныеЗаявления.СертификатОснование, СтандартнаяОбработка);

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

&НаКлиенте

Процедура ОчиститьДокумент(Элемент)

	ВидДокумента = Сред(Элемент.Имя, СтрДлина("Очистить") + 1);

	Элементы["Выбрать" + ВидДокумента].Заголовок = Новый ФорматированнаяСтрока(
		НСтр("ru = 'выбрать файл'"), , , , "ВыбратьДокумент");
	ЭтотОбъект["АдресФайла" + ВидДокумента] = "";
	Элементы["Очистить" + ВидДокумента].Видимость = Ложь;

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

&НаКлиенте

Процедура ВыбратьДокументОбработкаНавигационнойСсылки(Элемент, НавигационнаяСсылкаФорматированнойСтроки, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	Если НавигационнаяСсылкаФорматированнойСтроки = "ВыбратьДокумент" Тогда

		ОписаниеОповещения = Новый ОписаниеОповещения("ПослеДобавленияДокумента", ЭтотОбъект, Элемент.Имя);

		ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
		ПараметрыЗагрузки.ДействиеПередНачаломПомещенияФайлов = Новый ОписаниеОповещения("ПроверитьФайл", ЭтотОбъект);
		ПараметрыЗагрузки.Диалог.Фильтр = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Сканированные документы (%1)'"), "*.pdf;*.png;*.jpg;*.zip")
			+ "|*.pdf;*.png;*.jpg;*.jpeg;*.zip";

		ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;

		ФайловаяСистемаКлиент.ЗагрузитьФайл(ОписаниеОповещения, ПараметрыЗагрузки);

	ИначеЕсли НавигационнаяСсылкаФорматированнойСтроки = "ОткрытьФайл" Тогда

		ВидДокумента = Сред(Элемент.Имя, СтрДлина("Выбрать") + 1);

		#Если ВебКлиент Тогда
		ФайловаяСистемаКлиент.ОткрытьФайл(ЭтотОбъект["АдресФайла" + ВидДокумента],, Строка(Элемент.Заголовок));
		#Иначе
		ФайловаяСистемаКлиент.ОткрытьФайл(Строка(Элемент.Заголовок));
		#КонецЕсли

	КонецЕсли;

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

&НаКлиенте

Процедура НапомнитьОГотовностиПриИзменении(Элемент)

	ПодключитьОбработчикОжидания("ОбработчикОжиданияНапомнитьОГотовности", 0.1, Истина);

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

#Область Организация

&НаКлиенте

Процедура ОрганизацияПриИзменении(Элемент)

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

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

&НаКлиенте

Процедура ОрганизацияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

	ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка);

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

&НаКлиенте

Процедура ОрганизацияОчистка(Элемент, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;
	ПриПотереГотовности(ЭтотОбъект);

	ОчиститьСообщения();
	ОчиститьРеквизитыОрганизации(Истина);

	Организация = Неопределено;
	УточнитьПустоеЗначение(Организация, ОрганизацияТип);
	УстановитьОтображениеРеквизитовЗависимыхОтОрганизации();

	СотрудникОчистка(Элемент, СтандартнаяОбработка);

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

&НаКлиенте

Процедура НаименованиеСокращенноеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

	ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка, "ОрганизацияТип");

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

&НаКлиенте

Процедура НаименованиеСокращенноеОчистка(Элемент, СтандартнаяОбработка)

	ОрганизацияОчистка(Элемент, СтандартнаяОбработка);

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

&НаКлиенте

Процедура НаименованиеСокращенноеОткрытие(Элемент, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	Если ЗначениеЗаполнено(Организация) Тогда
		ПоказатьЗначение(, Организация);
	КонецЕсли;

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

&НаКлиенте

Процедура НаименованиеСокращенноеОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;
	ОчиститьСообщения();

	Если ВыбранноеЗначение <> Неопределено Тогда
		Организация = ВыбранноеЗначение;
		ПодключитьОбработчикОжидания("ОбработчикОжиданияРеквизитыОрганизацииПриИзменении", 0.1, Истина);
	КонецЕсли;

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

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

#Область ВладелецСертификата

&НаКлиенте

Процедура СотрудникПриИзменении(Элемент)

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

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

&НаКлиенте

Процедура СотрудникНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

	ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка);

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

&НаКлиенте

Процедура СотрудникОчистка(Элемент, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;
	ПриПотереГотовности(ЭтотОбъект);

	ОчиститьСообщения();
	ОчиститьРеквизитыВладельца();

	Сотрудник = Неопределено;
	УточнитьПустоеЗначение(Сотрудник, СотрудникТип);
	УстановитьОтображениеРеквизитовЗависимыхОтВладельца();

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

&НаКлиенте

Процедура ВладелецСертификатаСтрокойНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

	ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка, "СотрудникТип");

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

&НаКлиенте

Процедура ВладелецСертификатаСтрокойОчистка(Элемент, СтандартнаяОбработка)

	СотрудникОчистка(Элемент, СтандартнаяОбработка);

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

&НаКлиенте

Процедура ВладелецСертификатаСтрокойОткрытие(Элемент, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	Если ЗначениеЗаполнено(Сотрудник) Тогда
		ПоказатьЗначение(, Сотрудник);
	КонецЕсли;

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

&НаКлиенте

Процедура ВладелецСертификатаСтрокойОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;
	ОчиститьСообщения();

	Если ВыбранноеЗначение <> Неопределено Тогда
		Сотрудник = ВыбранноеЗначение;
		ПодключитьОбработчикОжидания("ОбработчикОжиданияРеквизитыВладельцаПриИзменении", 0.1, Истина);
	КонецЕсли;

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

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

#Область ПодписантЗаявления

&НаКлиенте

Процедура ДокументыРуководительПриИзменении(Элемент)

	ПриПотереГотовности(ЭтотОбъект);

	ДокументыРуководительСсылка = Неопределено;
	Элементы.ДокументыРуководитель.КнопкаОткрытия = Неопределено;

	ДокументыРуководитель = СокрЛП(ДокументыРуководитель);

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

&НаКлиенте

Процедура ДокументыРуководительНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

	ЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка);

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

&НаКлиенте


Процедура ДекорацияТекстЗаявленияОбработкаНавигационнойСсылки(Элемент, НавигационнаяСсылка, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	Если Не Доступность Тогда
		Возврат;
	КонецЕсли;

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

	ОчиститьСообщения();
	Если Не ЗаявлениеПроверено() Тогда
		Возврат;
	КонецЕсли;

	Если Не ВариантУдостоверяющегоЦентраУстановлен() Тогда
		Возврат;
	КонецЕсли;

	Доступность = Ложь;

	СозданиеКлючаИЗапросаНаСертификатНачало();

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

&НаКлиенте

Процедура ДекорацияОписаниеНажатие(Элемент)

	ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку("https://portal.1c.ru/applications/31");

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

&НаКлиенте

Процедура ДекорацияПроверкаУстановкиКриптопровайдераОбработкаНавигационнойСсылки(
	Элемент, НавигационнаяСсылкаФорматированнойСтроки, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	ПараметрыПроверки = Новый Структура;
	ПараметрыПроверки.Вставить("УстанавливатьРасширение", Истина);
	ПараметрыПроверки.Вставить("УстанавливатьКомпоненту", Истина);
	ПараметрыПроверки.Вставить("ПроверятьНаСервере", Ложь);

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

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

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

#Область ОбработчикиКомандФормы

&НаКлиенте

Процедура ВыбратьВидОрганизации(Команда)

	ЭлементКнопки = ?(ЭтоФизическоеЛицо,
		Элементы.ВидОрганизации2, Элементы.ВидОрганизации1);

	СписокВыбора = Новый СписокЗначений;
	СписокВыбора.Добавить("Организация",    НСтр("ru = 'Организация'"));
	СписокВыбора.Добавить("ФизическоеЛицо", НСтр("ru = 'Физическое лицо'"));

	Оповещение = Новый ОписаниеОповещения("ВыбратьВидОрганизацииПослеВыбора", ЭтотОбъект);

	ПоказатьВыборИзМеню(Оповещение, СписокВыбора, ЭлементКнопки);

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

&НаКлиенте

Процедура УказатьСведенияОбОрганизации(Команда)

	ПараметрыВвода = Новый Структура("СведенияОбОрганизации, ТолькоПросмотр",
		СведенияОбОрганизации(), ЗаявлениеОтправлено(ЭтотОбъект));

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

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

&НаКлиенте

Процедура УказатьСведенияОВладельце(Команда)

	ПараметрыВвода = Новый Структура("СведенияОВладельце, ТолькоПросмотр",
		СведенияОВладельцеСертификата(), ЗаявлениеОтправлено(ЭтотОбъект));

	ЗавершениеВводаСведений = Новый ОписаниеОповещения("ВводСведенийОВладельце", ЭтотОбъект);
	ОткрытьФорму("Обработка.ЗаявлениеНаВыпускНовогоКвалифицированногоСертификата.Форма.СведенияОВладельцеСертификата",
		ПараметрыВвода, ЭтотОбъект, , , , ЗавершениеВводаСведений);

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

&НаКлиенте

Процедура ОтправитьЗаявление(Команда)

	ОчиститьСообщения();
	Если Не ЗначениеЗаполнено(ПрограммаИмя) Тогда
		ПриПотереГотовности(ЭтотОбъект, Ложь);
	КонецЕсли;

	ПроверитьДоступностьОтправки(Истина);

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

&НаКлиенте

Процедура ОбновитьСостояниеОбработкиЗаявления(Команда)

	РезультатОбновления = ОбновитьСостояниеОбработкиЗаявленияНаСервере();
	СостояниеОбработкиЗаявленияАктуально = Истина;
	Если РезультатОбновления = Истина Тогда

		УстановитьПолученныйСертификат();

	ИначеЕсли ЗначениеЗаполнено(ДанныеЗаявления.СостояниеОбработкиЗаявления) Тогда
		ПоказатьПредупреждение(Неопределено,
			ДанныеЗаявления.СостояниеОбработкиЗаявления);
	КонецЕсли;

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

&НаКлиенте

Процедура ТехническаяИнформация(Команда)

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

	ОткрытьФорму(
		"Обработка.ЗаявлениеНаВыпускНовогоКвалифицированногоСертификата.Форма.ТехническаяИнформация",
		ПараметрыВывода, ЭтотОбъект);

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

&НаКлиенте

Процедура СведенияОЗаявленииИВладельцеСертификата(Команда)

	Документ = ПечатьИнформацииЗаявления();
	Если Документ = Неопределено Тогда
		Возврат;
	КонецЕсли;

	ИдентификаторПечатнойФормы = "ИнформацияЗаявления";
	НазваниеПечатнойФормы = НСтр("ru = 'Сведения о заявлении и владельце сертификата'");

	ОткрытьПечатнуюФорму(Документ, ИдентификаторПечатнойФормы, НазваниеПечатнойФормы);

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

&НаКлиенте

Процедура СодержаниеСертификата(Команда)

	Документ = ПечатьИнформацииСертификата();
	Если Документ = Неопределено Тогда
		Возврат;
	КонецЕсли;

	ИдентификаторПечатнойФормы = "СодержаниеСертификата";
	НазваниеПечатнойФормы = НСтр("ru = 'Содержание сертификата'");

	ОткрытьПечатнуюФорму(Документ, ИдентификаторПечатнойФормы, НазваниеПечатнойФормы);

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

&НаКлиенте

Процедура ПодписатьИОтправитьСертификат(Команда)

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

	Если ПодтвержденоОзнакомлениеСИнформацией Тогда
		СформироватьИОтправитьФайлРасписки();
	Иначе
		ОткрытьФормуИнформацииСертификата(, Истина);
	КонецЕсли;

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

&НаКлиенте

Процедура УстановитьСертификат(Команда)

	Если Не ЗначениеЗаполнено(Объект.Программа) Тогда
		ТекстОшибки = НСтр("ru = 'Программа: Поле не заполнено.'");
		ОбщегоНазначенияКлиент.СообщитьПользователю(ТекстОшибки,, "Объект.Программа");
		Возврат;
	КонецЕсли;

	УстановитьПолученныйСертификат();

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

&НаКлиенте

Процедура Готово(Команда)

	Закрыть();

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

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

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

#Область ДействияСЗаявлением

&НаКлиенте

Процедура ЗакрытиеПослеОтветаНаВопрос(Ответ, ДополнительныеПараметры) Экспорт

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

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

&НаКлиенте

Процедура ПослеЗаписи()

	Если Не ОповеститьОбИзмененииЗаявления Тогда
		Возврат;
	КонецЕсли;

	ОповеститьОбИзменении(Объект.Ссылка);

	Контекст = ЭлектроннаяПодписьСлужебныйКлиент.ПараметрыОповещенияПриЗаписиСертификата();

	Если ЭтоНовый Тогда
		Контекст.ЭтоНовый = Истина;
	ИначеЕсли Элементы.Готово.Видимость Тогда
		Контекст.Установлен = Истина;
	КонецЕсли;

	ОповеститьОбИзмененииЗаявления = Ложь;
	Оповестить("Запись_СертификатыКлючейЭлектроннойПодписиИШифрования", Контекст, Объект.Ссылка);

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

&НаКлиенте

Функция ЗаявлениеИсполнено()

	Возврат ДанныеЗаявления.СостояниеЗаявления = ПредопределенноеЗначение("Перечисление.СостоянияЗаявленияНаВыпускСертификата.Исполнено");

КонецФункции

&НаСервере


Функция ПодготовитьСтрокуДляИмениКонтейнера(Строка, ЗаменаПробела = Неопределено)

	ЗаменаСимволов = Новый Соответствие;
	ЗаменаСимволов.Вставить("\", " ");
	ЗаменаСимволов.Вставить("/", " ");
	ЗаменаСимволов.Вставить("*", " ");
	ЗаменаСимволов.Вставить("<", " ");
	ЗаменаСимволов.Вставить(">", " ");
	ЗаменаСимволов.Вставить("|", " ");
	ЗаменаСимволов.Вставить(":", "");
	ЗаменаСимволов.Вставить("""", "");
	ЗаменаСимволов.Вставить("?", "");
	ЗаменаСимволов.Вставить(Символы.ВК, "");
	ЗаменаСимволов.Вставить(Символы.ПС, " ");
	ЗаменаСимволов.Вставить(Символы.Таб, " ");
	ЗаменаСимволов.Вставить(Символы.НПП, " ");
	// Замена символов кавычек.
	ЗаменаСимволов.Вставить(Символ(171), "");
	ЗаменаСимволов.Вставить(Символ(187), "");
	ЗаменаСимволов.Вставить(Символ(8195), "");
	ЗаменаСимволов.Вставить(Символ(8194), "");
	ЗаменаСимволов.Вставить(Символ(8216), "");
	ЗаменаСимволов.Вставить(Символ(8218), "");
	ЗаменаСимволов.Вставить(Символ(8217), "");
	ЗаменаСимволов.Вставить(Символ(8220), "");
	ЗаменаСимволов.Вставить(Символ(8222), "");
	ЗаменаСимволов.Вставить(Символ(8221), "");

	СтрокаПодготовленная = "";

	СтрокаЛатиницей = СтроковыеФункцииКлиент.СтрокаЛатиницей(Строка);
	КоличествоСимволов = СтрДлина(СтрокаЛатиницей);

	Для НомерСимвола = 1 По КоличествоСимволов Цикл
		Символ = Сред(СтрокаЛатиницей, НомерСимвола, 1);
		Если ЗаменаСимволов[Символ] <> Неопределено Тогда
			Символ = ЗаменаСимволов[Символ];
		КонецЕсли;
		СтрокаПодготовленная = СтрокаПодготовленная + Символ;
	КонецЦикла;

	Если ЗаменаПробела <> Неопределено Тогда
		СтрокаПодготовленная = СтрЗаменить(ЗаменаПробела, " ", ЗаменаПробела);
	КонецЕсли;

	Возврат СокрЛП(СтрокаПодготовленная);

КонецФункции

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

#Область ОбъектКриптографии

&НаКлиенте

Процедура СоздатьОбъектКриптографии(ОбработкаПродолжения, НазначениеРасширенияДляРаботыСФайлами, НазначениеВнешнейКомпонентыКриптографии)

	Контекст = Новый Структура;
	Контекст.Вставить("ОбработкаПродолжения", ОбработкаПродолжения);
	Контекст.Вставить("НазначениеВнешнейКомпонентыКриптографии", НазначениеВнешнейКомпонентыКриптографии);

	ФайловаяСистемаКлиент.ПодключитьРасширениеДляРаботыСФайлами(
		Новый ОписаниеОповещения("СоздатьОбъектКриптографииПослеПодключенияРасширенияРаботыСФайлами", ЭтотОбъект, Контекст),
		НазначениеРасширенияДляРаботыСФайлами, Ложь);

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

&НаКлиенте

Процедура СоздатьОбъектКриптографииПослеПодключенияРасширенияРаботыСФайлами(Результат, Контекст) Экспорт

	Если Результат <> Истина Тогда
		ВыполнитьОбработкуОповещения(Контекст.ОбработкаПродолжения, Ложь);
		Возврат;
	КонецЕсли;

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

	ПолноеИмяМакета = "";
	УстановитьПараметрыКомпоненты(ПолноеИмяМакета, ПараметрыПодключения);

	ОбщегоНазначенияКлиент.ПодключитьКомпонентуИзМакета(
		Новый ОписаниеОповещения("СоздатьОбъектКриптографииПослеПодключенияКомпоненты", ЭтотОбъект, Контекст),
		Неопределено, ПолноеИмяМакета, ПараметрыПодключения);

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

&НаКлиенте

Процедура УстановитьПараметрыКомпоненты(ПолноеИмяМакета, ПараметрыПодключения)

	ОписаниеКомпоненты = ЭлектроннаяПодписьСлужебныйКлиентСервер.ОписаниеКомпоненты();
	ПолноеИмяМакета = ОписаниеКомпоненты.ПолноеИмяМакета;
	ПараметрыПодключения.ИдентификаторыСозданияОбъектов.Добавить(ОписаниеКомпоненты.ИмяОбъекта);

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

&НаКлиенте

Процедура СоздатьОбъектКриптографииПослеПодключенияКомпоненты(Результат, Контекст) Экспорт

	Если Не Результат.Подключено Тогда
		Криптография = Неопределено;
		РаботаСДвоичнымиДанными = Неопределено;

		Если ПустаяСтрока(Результат.ОписаниеОшибки) Тогда
			// Пользователь отказался от установки внешней компоненты.
			ВыполнитьОбработкуОповещения(Контекст.ОбработкаПродолжения, Ложь);
		Иначе
			ТекстСообщения = Результат.ОписаниеОшибки;
			Если ОбщегоНазначенияКлиент.ЭтоMacOSКлиент() Тогда
				ТекстСообщения = ТекстСообщения + Символы.ПС + Символы.ПС
					+ НСтр("ru = 'Рекомендуется оформить заявление на компьютере с ОС Windows, сохранив закрытую часть ключа на внешний носитель (для возможности дальнейшего переноса).'");
			КонецЕсли;
			ПоказатьПредупреждение(Новый ОписаниеОповещения("СоздатьОбъектКриптографииПослеПредупрежденияОбОшибке",
				ЭтотОбъект, Контекст), ТекстСообщения);
		КонецЕсли;

		Возврат;
	КонецЕсли;

	УстановитьПодключенныеМодули(РаботаСДвоичнымиДанными, Криптография, Результат);

	Криптография.НачатьУстановкуНеВыводитьСообщенияОбОшибках(
		Новый ОписаниеОповещения("СоздатьОбъектКриптографииПослеУстановкиНеВыводитьСообщенияОбОшибках",
		ЭтотОбъект, Контекст), Истина);

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

&НаКлиенте

Процедура УстановитьПодключенныеМодули(РаботаСДвоичнымиДанными, Криптография, РезультатПодключения)

	ОписаниеКомпоненты = ЭлектроннаяПодписьСлужебныйКлиентСервер.ОписаниеКомпоненты();
	ОбъектКомпоненты = РезультатПодключения.ПодключаемыйМодуль.Получить(ОписаниеКомпоненты.ИмяОбъекта);
	РаботаСДвоичнымиДанными = ОбъектКомпоненты;
	Криптография            = ОбъектКомпоненты;

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

&НаКлиенте

Процедура СоздатьОбъектКриптографииПослеУстановкиНеВыводитьСообщенияОбОшибках(Контекст) Экспорт

	Если Не ВозможноПродолжениеПослеОперацииКомпоненты() Тогда
		Возврат;
	КонецЕсли;

	Если ЗначениеЗаполнено(Объект.Программа) Тогда
		ЭлектроннаяПодписьСлужебныйКлиент.ПолучитьПутьКПрограмме(
			Новый ОписаниеОповещения("СоздатьОбъектКриптографииПослеПолученияПутиКПрограмме",
				ЭтотОбъект, Контекст), Объект.Программа);
	Иначе
		СоздатьОбъектКриптографииПослеПолученияПутиКПрограмме("", Контекст);
	КонецЕсли;

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

// Продолжение процедуры ЗаполнитьАлгоритмыВыбраннойПрограммы.
&НаКлиенте
Асинх Процедура СоздатьОбъектКриптографииПослеПолученияПутиКПрограмме(ОписаниеПути, Контекст) Экспорт

	ДанныеПрограммы = ДанныеПрограммы();

	Если Не ЗначениеЗаполнено(Объект.Программа) Тогда

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

		ПрограммаАвто = ПрограммыАвто.Получить(ПрограммаИдентификатор);
		Если ПрограммаАвто = Неопределено Тогда
			ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Не установлена программа %1.'"), ПредставлениеПрограммы);
		КонецЕсли;

		ПутьКПрограмме = ПрограммаАвто.ПутьКПрограммеАвто;

	Иначе
		ПутьКПрограмме = ОписаниеПути.ПутьКПрограмме;
	КонецЕсли;

	ОповещениеПослеВызоваСоздать = Новый ОписаниеОповещения("СоздатьОбъектКриптографииПослеВызоваСоздатьМенеджераКриптографии",
		ЭтотОбъект, Контекст, "СоздатьОбъектКриптографииПослеОшибкиВызоваСоздатьМенеджераКриптографии", ЭтотОбъект);

	Криптография.НачатьВызовСоздатьМенеджераКриптографии(
		ОповещениеПослеВызоваСоздать, ДанныеПрограммы.ИмяПрограммы, ПутьКПрограмме, ДанныеПрограммы.ТипПрограммы);

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

&НаКлиенте

Функция ДанныеПрограммы()

	Если ЗначениеЗаполнено(Объект.Программа) Тогда
		Строки = СписокПрограмм.НайтиСтроки(Новый Структура("Ссылка", Объект.Программа));
	Иначе
		Строки = СписокПрограмм.НайтиСтроки(Новый Структура("Идентификатор", ПрограммаИдентификатор));
	КонецЕсли;

	Возврат Строки[0];

КонецФункции

&НаКлиенте


Функция ИмяРегионаРФПоРекомендациямДляСКПЭП(КодРегиона, ТекстОшибки)

	// Методические рекомендации по составу квалифицированного сертификата ключа
	// проверки электронной подписи (Версия 1.9).
	//
	// 3.2 Цели и требования
	//     Данный документ разработан в целях реализации и во исполнение:
	//     федерального закона от 6 апреля 2011 г. № 63-ФЗ "Об электронной подписи";
	//     приказа ФСБ от 27 декабря 2011 г. N 795 "ОБ УТВЕРЖДЕНИИ ТРЕБОВАНИЙ К ФОРМЕ
	//     КВАЛИФИЦИРОВАННОГО СЕРТИФИКАТА КЛЮЧА ПРОВЕРКИ ЭЛЕКТРОННОЙ ПОДПИСИ".
	//
	// Приложение 2. Формат названия субъекта федерации.
	//     2. Код и название субъекта федерации должно соответствовать КЛАДР.

	// Справочник "Субъекты Российской федерации" (ССРФ) в формате КЛАДР опубликован тут:
	// "https://www.gnivc.ru/technical_support/classifiers_reference/ssrf/".
	// Последнее обновление в конфигурации на дату актуальности: 04.04.2019.

	Если ПустаяСтрока(КодРегиона) Тогда
		ТекстОшибки = ТекстОшибки + НСтр("ru = 'Не указан регион РФ.'");
		Возврат "";
	КонецЕсли;

	ИменаВсехРегионовРФ = Обработки.ЗаявлениеНаВыпускНовогоКвалифицированногоСертификата.ПолучитьМакет(
		"ИменаРегионовРФ");

	Строка = ИменаВсехРегионовРФ.ПолучитьСтроку(Число(КодРегиона));
	Если Не СтрНачинаетсяС(Строка, КодРегиона + " ") Тогда
		ТекстОшибки = ТекстОшибки + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Регион РФ с кодом ""%1"" не существует.'"), КодРегиона);
		Возврат "";
	КонецЕсли;

	Строка = СокрЛП(Сред(Строка, 4));
	Если Не ЗначениеЗаполнено(Строка) Тогда
		ТекстОшибки = ТекстОшибки + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Для региона РФ с кодом ""%1"" имя, рекомендованное для СКПЭП, еще не назначено.'"), КодРегиона);
		Возврат "";
	КонецЕсли;

	ТекстОшибки = "";
	Возврат Строка;

КонецФункции

&НаСервереБезКонтекста

Функция ПредставлениеЧастиАдреса(АдресСтруктура, СписокПолей)

	Представление = "";
	СтруктураПолей = Новый Структура(СписокПолей);
	ЗаполнитьЗначенияСвойств(СтруктураПолей, АдресСтруктура);

	МодульУправлениеКонтактнойИнформацией = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформацией");
	Представление = МодульУправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформации(СтруктураПолей);

	Возврат Представление;

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ТолькоЦифры(Строка)

	ДлинаСтроки = СтрДлина(Строка);

	ОбработаннаяСтрока = "";
	Для НомерСимвола = 1 По ДлинаСтроки Цикл

		Символ = Сред(Строка, НомерСимвола, 1);
		Если Символ >= "0" И Символ <= "9" Тогда
			ОбработаннаяСтрока = ОбработаннаяСтрока + Символ;
		КонецЕсли;

	КонецЦикла;

	Возврат ОбработаннаяСтрока;

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция НаселенныйПунктПолностью(АдресСтруктура)

	// Округ ОкругСокращение, Район РайонСокращение, Город ГородСокращение,
	// ВнутригородскойРайон ВнутригородскойРайонСокращение, НаселенныйПункт НаселенныйПунктСокращение.

	СписокПолей = "";
	Если АдресСтруктура.Свойство("Регион")
		И АдресСтруктура.Свойство("КодРегиона")
		И (АдресСтруктура.КодРегиона = "77"
		Или АдресСтруктура.КодРегиона = "78"
		Или АдресСтруктура.КодРегиона = "92"
		Или АдресСтруктура.КодРегиона = "99") Тогда

		СписокПолей = "Регион, КодРегиона, ";
	КонецЕсли;

	Возврат ПредставлениеЧастиАдреса(АдресСтруктура, СписокПолей +
		"Округ,
		|Район,
		|Город,
		|ВнутригородскойРайон,
		|НаселенныйПункт,
		|Территория");

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеДвоичныхДанных(Знач Строка, БайтВСтроке = 20)

	ОстатокСтроки = НРег(СтрЗаменить(Строка, " ", ""));
	Представление = "";
	БайтВТекущейСтроке = 0;

	Пока ЗначениеЗаполнено(ОстатокСтроки) Цикл
		Представление = Представление + Лев(ОстатокСтроки, 2) + " ";
		ОстатокСтроки = Сред(ОстатокСтроки, 3);
		БайтВТекущейСтроке = БайтВТекущейСтроке + 1;
		Если БайтВТекущейСтроке = БайтВСтроке Тогда
			Представление = СокрЛП(Представление) + Символы.ПС;
			БайтВТекущейСтроке = 0;
		КонецЕсли;
	КонецЦикла;

	Возврат СокрЛП(Представление);

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеРеквизитаНомерПаспортаРФ(НомерПаспортаРФ)

	Возврат Лев(НомерПаспортаРФ, 2) + " " + Сред(НомерПаспортаРФ, 3, 2) + " " + Прав(НомерПаспортаРФ, 6);

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеРеквизитаДокументКодПодразделения(КодПодразделения)

	Если Не ЗначениеЗаполнено(КодПодразделения) Тогда
		Возврат "";
	КонецЕсли;

	Возврат Лев(КодПодразделения, 3) + "-" + Сред(КодПодразделения, 4);

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеРеквизитаДокументДатаВыдачи(ДокументДатаВыдачи)

	Возврат Формат(ДокументДатаВыдачи, "ДФ=dd.MM.yyyy"); // АПК:335 Не локализуется (формат веб-сервиса).

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеВидаДокумента(ВидДокумента)

	Возврат ?(ВидДокумента = "21",
		НСтр("ru = 'паспорт гражданина Российской Федерации'"),
		НСтр("ru = 'иной документ, предусмотренный законодательством Российской Федерации'"));

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеРеквизитаСтраховойНомерПФР(СтраховойНомерПФР)

	Возврат Сред(СтраховойНомерПФР, 1, 3) + "-" + Сред(СтраховойНомерПФР,  4, 3)
	+ "-" + Сред(СтраховойНомерПФР, 7, 3) + " " + Сред(СтраховойНомерПФР, 10, 2);

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ПредставлениеРеквизитаДатаРождения(ДатаРождения)

	Возврат Формат(ДатаРождения, "ДФ=dd.MM.yyyy"); // АПК:335 Не локализуется (формат веб-сервиса).

КонецФункции

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

#Область ОблачныйСервисПодписи

&НаКлиенте

Процедура СоздатьЗапросВОблачныйСервис(ОбработкаЗавершения)

	ИдентификаторЗаявленияВОблачныйСервис = Новый УникальныйИдентификатор;

	Контекст = Новый Структура;
	Контекст.Вставить("ОбработкаЗавершения", ОбработкаЗавершения);
	Контекст.Вставить("ЗапросНаСертификат", Неопределено);

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

	МодульМенеджерСервисаКриптографииКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("МенеджерСервисаКриптографииКлиент");
	МодульМенеджерСервисаКриптографииКлиент.СоздатьКонтейнерИЗапросНаСертификат(
		Новый ОписаниеОповещения("СоздатьЗапросВОблачныйСервисПослеОтправкиЗапроса", ЭтотОбъект, Контекст),
		ИдентификаторЗаявленияВОблачныйСервис, ТекстЗапросаНаСертификат);

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

&НаКлиенте


Функция ЗаписатьВПротоколВыполнения(Код = "",
									СтруктураЗаписи=Неопределено,
									ВзвестиФлагОшибок=Истина,
									Уровень=0,
									Выравнивание=22,
									БезусловнаяЗаписьВПротоколОбмена = Ложь,
									Знач РезультатВыполненияОбмена = Неопределено) Экспорт
	//
	Отступ = "";
	Для Сч = 0 По Уровень-1 Цикл
		Отступ = Отступ + Символы.Таб;
	КонецЦикла;

	Если ТипЗнч(Код) = ТипЧисло Тогда

		Если СообщенияОбОшибках = Неопределено Тогда
			ИнициализацияСообщений();
		КонецЕсли;

		Стр = СообщенияОбОшибках[Код];

	Иначе

		Стр = Строка(Код);

	КонецЕсли;

	Стр = Отступ + Стр;

	Если СтруктураЗаписи <> Неопределено Тогда

		Для каждого Поле Из СтруктураЗаписи Цикл

			Значение = Поле.Значение;
			Если Значение = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			Ключ = Поле.Ключ;
			Стр  = Стр + Символы.ПС + Отступ + Символы.Таб + одДополнитьСтроку(Ключ, Выравнивание) + " =  " + Строка(Значение);

		КонецЦикла;

	КонецЕсли;

	ПолеСтрокаСообщенияОбОшибке = Стр;

	Если ВзвестиФлагОшибок Тогда

		УстановитьФлагОшибки();

		РезультатВыполненияОбмена = ?(РезультатВыполненияОбмена = Неопределено,
										Перечисления.РезультатыВыполненияОбмена.Ошибка,
										РезультатВыполненияОбмена);
		//
	КонецЕсли;

	УстановитьРезультатВыполненияОбмена(РезультатВыполненияОбмена);

	Если ФайлПротоколаДанных <> Неопределено Тогда

		Если ВзвестиФлагОшибок Тогда

			ФайлПротоколаДанных.ЗаписатьСтроку(Символы.ПС + "Ошибка.");

		КонецЕсли;

		Если ВзвестиФлагОшибок ИЛИ БезусловнаяЗаписьВПротоколОбмена ИЛИ ВыводВПротоколИнформационныхСообщений Тогда

			ФайлПротоколаДанных.ЗаписатьСтроку(Символы.ПС + СтрокаСообщенияОбОшибке());

		КонецЕсли;

	КонецЕсли;

	Если РезультатВыполненияОбменаОшибка(РезультатВыполненияОбмена) Тогда

		УровеньЖР = УровеньЖурналаРегистрации.Ошибка;

	ИначеЕсли РезультатВыполненияОбменаПредупреждение(РезультатВыполненияОбмена) Тогда

		УровеньЖР = УровеньЖурналаРегистрации.Предупреждение;

	Иначе

		УровеньЖР = УровеньЖурналаРегистрации.Информация;

	КонецЕсли;

	// Фиксируем событие в журнале регистрации.
	СтрокаСообщенияОбОшибке = СтрокаСообщенияОбОшибке();
	ЗаписьЖурналаРегистрацииОбменДанными(СтрокаСообщенияОбОшибке, УровеньЖР);

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

		МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
		ЗаписатьВРезультатыОбменаДанными = МодульРаботаВМоделиСервиса.ИспользованиеРазделителяСеанса();

	КонецЕсли;

	Если ЗаписатьВРезультатыОбменаДанными Тогда

		ПараметрыЗаписи = Новый Структура("ПроблемныйОбъект, ТипПроблемы");
		ПараметрыЗаписи.Вставить("УзелИнформационнойБазы", УзелДляОбмена);
		ПараметрыЗаписи.Вставить("Причина", СтрокаСообщенияОбОшибке);

		Если ЗначениеЗаполнено(СсылкаДляПереходаПриВозникновенииОшибки) Тогда

			ПараметрыЗаписи.ПроблемныйОбъект = СсылкаДляПереходаПриВозникновенииОшибки;

		КонецЕсли;

		Если РежимОбмена = "Выгрузка" Тогда

			ПараметрыЗаписи.ТипПроблемы = Перечисления.ТипыПроблемОбменаДанными.ОшибкаВыполненияКодаОбработчиковПриОтправкеДанных;

		ИначеЕсли РежимОбмена = "Загрузка" Тогда

			ПараметрыЗаписи.ТипПроблемы = Перечисления.ТипыПроблемОбменаДанными.ОшибкаВыполненияКодаОбработчиковПриПолученииДанных;

		КонецЕсли;

		РегистрыСведений.РезультатыОбменаДанными.ДобавитьЗаписьОРезультатахОбмена(ПараметрыЗаписи);

	КонецЕсли;

	Возврат СтрокаСообщенияОбОшибке();

КонецФункции

Функция ЗаписатьИнформациюОбОшибкеВПротокол(КСообщенияОбОшибках, СтрокаОшибки, Объект, ТипОбъекта = Неопределено)

	ЗП         = ЗаписьПротоколаОбмена(КСообщенияОбОшибках, СтрокаОшибки);
	ЗП.Объект  = Объект;

	Если ТипОбъекта <> Неопределено Тогда
		ЗП.ТипОбъекта     = ТипОбъекта;
	КонецЕсли;

	СтрокаОшибки = ЗаписатьВПротоколВыполнения(КСообщенияОбОшибках, ЗП);

	Возврат СтрокаОшибки;

КонецФункции

Процедура ЗаписатьИнформациюОбОшибкеОбработчикаОчисткиДанных(КСообщенияОбОшибках, СтрокаОшибки, ИмяПравилаОчисткиДанных, Объект = "", ИмяОбработчика = "")

	ЗП                        = ЗаписьПротоколаОбмена(КСообщенияОбОшибках, СтрокаОшибки);
	ЗП.ПОД                    = ИмяПравилаОчисткиДанных;

	Если Объект <> "" Тогда
		ЗП.Объект                 = Строка(Объект) + "  (" + ТипЗнч(Объект) + ")";
	КонецЕсли;

	Если ИмяОбработчика <> "" Тогда
		ЗП.Обработчик             = ИмяОбработчика;
	КонецЕсли;

	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КСообщенияОбОшибках, ЗП);

	Если Не ПродолжитьПриОшибке Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;

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

Процедура ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(КСообщенияОбОшибках, СтрокаОшибки, ИмяПравила, Источник = "",
	ТипОбъекта, Объект = Неопределено, ИмяОбработчика)

	ЗП                        = ЗаписьПротоколаОбмена(КСообщенияОбОшибках, СтрокаОшибки);
	ЗП.ИмяПКО                 = ИмяПравила;
	ЗП.ТипОбъекта             = ТипОбъекта;
	ЗП.Обработчик             = ИмяОбработчика;

	Если Не ПустаяСтрока(Источник) Тогда

		ЗП.Источник           = Источник;

	КонецЕсли;

	Если Объект <> Неопределено Тогда

		ЗП.Объект                 = Строка(Объект);

	КонецЕсли;

	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КСообщенияОбОшибках, ЗП);

	Если Не ПродолжитьПриОшибке Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;

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

Процедура ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(КСообщенияОбОшибках, СтрокаОшибки, ПКО, Источник, ИмяОбработчика)

	ЗП                        = ЗаписьПротоколаОбмена(КСообщенияОбОшибках, СтрокаОшибки);
	ЗП.ПКО                    = ПКО.Имя + "  (" + ПКО.Наименование + ")";

	Попытка
		ЗП.Объект                 = Строка(Источник) + "  (" + ТипЗнч(Источник) + ")";
	Исключение
		ЗП.Объект                 = "(" + ТипЗнч(Источник) + ")";
	КонецПопытки;

	ЗП.Обработчик             = ИмяОбработчика;

	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КСообщенияОбОшибках, ЗП);

	Если Не ПродолжитьПриОшибке Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;

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

Процедура ЗаписатьИнформациюОбОшибкеОбработчикиПКС(КСообщенияОбОшибках, СтрокаОшибки, ПКО, ПКС, Источник = "",
	ИмяОбработчика = "", Значение = Неопределено)

	ЗП                        = ЗаписьПротоколаОбмена(КСообщенияОбОшибках, СтрокаОшибки);
	ЗП.ПКО                    = ПКО.Имя + "  (" + ПКО.Наименование + ")";
	ЗП.ПКС                    = ПКС.Имя + "  (" + ПКС.Наименование + ")";

	Попытка
		ЗП.Объект                 = Строка(Источник) + "  (" + ТипЗнч(Источник) + ")";
	Исключение
		ЗП.Объект                 = "(" + ТипЗнч(Источник) + ")";
	КонецПопытки;

	ЗП.СвойствоПриемника      = ПКС.Приемник + "  (" + ПКС.ТипПриемника + ")";

	Если ИмяОбработчика <> "" Тогда
		ЗП.Обработчик         = ИмяОбработчика;
	КонецЕсли;

	Если Значение <> Неопределено Тогда
		ЗП.КонвертируемоеЗначение = Строка(Значение) + "  (" + ТипЗнч(Значение) + ")";
	КонецЕсли;

	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КСообщенияОбОшибках, ЗП);

	Если Не ПродолжитьПриОшибке Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;

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

Процедура ЗаписатьИнформациюОбОшибкеОбработчикиПВД(КСообщенияОбОшибках, СтрокаОшибки, ИмяПравила, ИмяОбработчика, Объект = Неопределено)

	ЗП                        = ЗаписьПротоколаОбмена(КСообщенияОбОшибках, СтрокаОшибки);
	ЗП.ПВД                    = ИмяПравила;

	Если Объект <> Неопределено Тогда
		ЗП.Объект                 = Строка(Объект) + "  (" + ТипЗнч(Объект) + ")";
	КонецЕсли;

	ЗП.Обработчик             = ИмяОбработчика;

	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КСообщенияОбОшибках, ЗП);

	Если Не ПродолжитьПриОшибке Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;

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


Функция КлючевыеПоляПоискаПоТабличнойЧасти(ПКО, ИмяТабличнойЧасти, МассивКлючевыхПолейПоиска, КлючевыеПоляПоиска)

	Если ПКО = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	ДанныеПоискаПоТЧ = ПКО.ПоискПоТабличнымЧастям.Найти("ТабличнаяЧасть." + ИмяТабличнойЧасти, "ИмяЭлемента");

	Если ДанныеПоискаПоТЧ = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Если Не ДанныеПоискаПоТЧ.Валидное Тогда
		Возврат Ложь;
	КонецЕсли;

	МассивКлючевыхПолейПоиска = ДанныеПоискаПоТЧ.МассивКлючевыхПолейПоиска;
	КлючевыеПоляПоиска        = ДанныеПоискаПоТЧ.КлючевыеПоляПоиска;

	Возврат Истина;

КонецФункции

// Загружает движения объекта
//
// Параметры:
//  Объект         - объект, движения которого загружаем.
//  Имя            - имя регистра.
//  Очистить       - если Истина, то движения предварительно очищается.
//

Процедура ЗагрузитьДвижения(Объект, Имя, Очистить, ОбщаяИнформацияОТипеДокумента,
	ПараметрыОбъекта, Правило)

	ИмяДвижений = Имя + "НаборЗаписей";
	Если ОбщаяИнформацияОТипеДокумента <> Неопределено Тогда
		ИнформацияОТипах = ОбщаяИнформацияОТипеДокумента[ИмяДвижений];
	Иначе
	    ИнформацияОТипах = Неопределено;
	КонецЕсли;

	ДанныеПоискаПоТЧ = Неопределено;

	КопияТЧДляПоиска = Неопределено;

	Движения = Объект.Движения[Имя];

	Движения.Прочитать();
	Движения.Записывать = Истина;

	Если Очистить
		И Движения.Количество() <> 0 Тогда

		Если ДанныеПоискаПоТЧ <> Неопределено Тогда
			КопияТЧДляПоиска = Движения.Выгрузить();
		КонецЕсли;

        Движения.Очистить();

	ИначеЕсли ДанныеПоискаПоТЧ <> Неопределено Тогда

		КопияТЧДляПоиска = Движения.Выгрузить();

	КонецЕсли;

	НомерЗаписи = 0;
	Пока ФайлОбмена.Прочитать() Цикл

		ИмяУзла = ФайлОбмена.ЛокальноеИмя;

		Если      ИмяУзла = "Запись" Тогда

			Запись = Движения.Добавить();
			УстановитьСвойстваЗаписи(Запись, ИнформацияОТипах, ПараметрыОбъекта, ИмяДвижений, НомерЗаписи, ДанныеПоискаПоТЧ, КопияТЧДляПоиска);

			НомерЗаписи = НомерЗаписи + 1;

		ИначеЕсли (ИмяУзла = "НаборЗаписей") И (ФайлОбмена.ТипУзла = ТипУзлаXMLКонецЭлемента) Тогда

			Прервать;

		Иначе

			ЗаписатьВПротоколВыполнения(9);
			Прервать;

		КонецЕсли;

	КонецЦикла;

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

// Устанавливает свойства объекта (записи).
//
// Параметры:
//  Запись         - объект, свойства которого устанавливаем.
//                   Например, строка табличной части или запись регистра.
//

Процедура УстановитьСвойстваЗаписи(Запись, ИнформацияОТипах,
	ПараметрыОбъекта, ИмяВетки, НомерЗаписи,
	ДанныеПоискаПоТЧ = Неопределено, КопияТЧДляПоиска = Неопределено)

	НужноОрганизоватьПоискПоТЧ = (ДанныеПоискаПоТЧ <> Неопределено)
								И (КопияТЧДляПоиска <> Неопределено)
								И КопияТЧДляПоиска.Количество() <> 0;

	Если НужноОрганизоватьПоискПоТЧ Тогда

		СтруктураЧтенияСвойств = Новый Структура();
		СтруктураЧтенияСубконто = Новый Структура();

	КонецЕсли;

	Пока ФайлОбмена.Прочитать() Цикл

		ИмяУзла = ФайлОбмена.ЛокальноеИмя;

		Если ИмяУзла = "Свойство"
			ИЛИ ИмяУзла = "ЗначениеПараметра" Тогда

			ЭтоПараметр = (ИмяУзла = "ЗначениеПараметра");

			Имя    = одАтрибут(ФайлОбмена, ТипСтрока, "Имя");
			ИмяПКО = одАтрибут(ФайлОбмена, ТипСтрока, "ИмяПКО");

			Если Имя = "ВидДвижения" И СтрНайти(Метаданные.НайтиПоТипу(ТипЗнч(Запись)).ПолноеИмя(), "РегистрНакопления") Тогда

				ТипСвойства = ТипВидДвиженияНакопления;

			Иначе

				ТипСвойства = ТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);

			КонецЕсли;

			ЗначениеСвойства = ПрочитатьСвойство(ТипСвойства,,, ИмяПКО);

			Если ЭтоПараметр Тогда
				ДобавитьСложныйПараметрПриНеобходимости(ПараметрыОбъекта, ИмяВетки, НомерЗаписи, Имя, ЗначениеСвойства);
			ИначеЕсли НужноОрганизоватьПоискПоТЧ Тогда
				СтруктураЧтенияСвойств.Вставить(Имя, ЗначениеСвойства);
			Иначе

				Попытка

					Запись[Имя] = ЗначениеСвойства;

				Исключение

					ЗП = ЗаписьПротоколаОбмена(26, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
					ЗП.ИмяПКО           = ИмяПКО;
					ЗП.Объект           = Запись;
					ЗП.ТипОбъекта       = ТипЗнч(Запись);
					ЗП.Свойство         = Имя;
					ЗП.Значение         = ЗначениеСвойства;
					ЗП.ТипЗначения      = ТипЗнч(ЗначениеСвойства);
					СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(26, ЗП, Истина);

					Если Не ПродолжитьПриОшибке Тогда
						ВызватьИсключение СтрокаСообщенияОбОшибке;
					КонецЕсли;

				КонецПопытки;

			КонецЕсли;

		ИначеЕсли ИмяУзла = "СубконтоДт" ИЛИ ИмяУзла = "СубконтоКт" Тогда

			// Поиск по субконто не реализован.

			Ключ = Неопределено;
			Значение = Неопределено;

			Пока ФайлОбмена.Прочитать() Цикл

				ИмяУзла = ФайлОбмена.ЛокальноеИмя;

				Если ИмяУзла = "Свойство" Тогда

					Имя    = одАтрибут(ФайлОбмена, ТипСтрока, "Имя");
					ИмяПКО = одАтрибут(ФайлОбмена, ТипСтрока, "ИмяПКО");

					ТипСвойства = ТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);

					Если Имя = "Ключ" Тогда

						Ключ = ПрочитатьСвойство(ТипСвойства);

					ИначеЕсли Имя = "Значение" Тогда

						Значение = ПрочитатьСвойство(ТипСвойства,,, ИмяПКО);

					КонецЕсли;

				ИначеЕсли (ИмяУзла = "СубконтоДт" ИЛИ ИмяУзла = "СубконтоКт") И (ФайлОбмена.ТипУзла = ТипУзлаXMLКонецЭлемента) Тогда

					Прервать;

				Иначе

					ЗаписатьВПротоколВыполнения(9);
					Прервать;

				КонецЕсли;

			КонецЦикла;

			Если Ключ <> Неопределено
				И Значение <> Неопределено Тогда

				Если НЕ НужноОрганизоватьПоискПоТЧ Тогда

					Запись[ИмяУзла][Ключ] = Значение;

				Иначе

					СоответствиеЗаписи = Неопределено;
					Если НЕ СтруктураЧтенияСубконто.Свойство(ИмяУзла, СоответствиеЗаписи) Тогда
						СоответствиеЗаписи = Новый Соответствие;
						СтруктураЧтенияСубконто.Вставить(ИмяУзла, СоответствиеЗаписи);
					КонецЕсли;

					СоответствиеЗаписи.Вставить(Ключ, Значение);

				КонецЕсли;

			КонецЕсли;

		ИначеЕсли (ИмяУзла = "Запись") И (ФайлОбмена.ТипУзла = ТипУзлаXMLКонецЭлемента) Тогда

			Прервать;

		Иначе

			ЗаписатьВПротоколВыполнения(9);
			Прервать;

		КонецЕсли;

	КонецЦикла;

	Если НужноОрганизоватьПоискПоТЧ Тогда

		СтруктураПоиска = Новый Структура();

		Для Каждого ЭлементПоиска Из  ДанныеПоискаПоТЧ.ПоляПоискаТЧ Цикл

			ЗначениеЭлемента = Неопределено;
			СтруктураЧтенияСвойств.Свойство(ЭлементПоиска, ЗначениеЭлемента);

			СтруктураПоиска.Вставить(ЭлементПоиска, ЗначениеЭлемента);

		КонецЦикла;

		МассивРезультатовПоиска = КопияТЧДляПоиска.НайтиСтроки(СтруктураПоиска);

		НайденаЗапись = МассивРезультатовПоиска.Количество() > 0;
		Если НайденаЗапись Тогда
			ЗаполнитьЗначенияСвойств(Запись, МассивРезультатовПоиска[0]);
		КонецЕсли;

		// Поверх заполнение свойствами и значением субконто.
		Для Каждого КлючИЗначение Из СтруктураЧтенияСвойств Цикл

			Запись[КлючИЗначение.Ключ] = КлючИЗначение.Значение;

		КонецЦикла;

		Для Каждого ЭлементИмя Из СтруктураЧтенияСубконто Цикл

			Для Каждого ЭлементКлюч Из ЭлементИмя.Значение Цикл

				Запись[ЭлементИмя.Ключ][ЭлементКлюч.Ключ] = ЭлементКлюч.Значение;

			КонецЦикла;

		КонецЦикла;

	КонецЕсли;

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

// Загружает объект типа ОписаниеТипов из указанного xml-источника.
//
// Параметры:
//  Источник         - xml-источник.
//


Процедура ЗаполнитьОписание(ОписаниеКонфигураций, ИменаКонфигураций)

	ПодсистемыКонфигурации = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
	Для Каждого Подсистема Из ПодсистемыКонфигурации.ПоИменам Цикл
		ИмяМодуля = Подсистема.Значение.ОсновнойСерверныйМодуль;
		КраткоеИмяБиблиотеки = СтрЗаменить(ИмяМодуля, "ОбновлениеИнформационнойБазы", "");
		ИменаКонфигураций.Добавить(КраткоеИмяБиблиотеки);
		Описание = Новый Структура("module", Подсистема.Значение.ОсновнойСерверныйМодуль);
		Описание.Вставить("name", Подсистема.Значение.Имя);
		ОписаниеКонфигураций.Вставить(КраткоеИмяБиблиотеки, Описание);
	КонецЦикла;

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

&НаСервере

Процедура ДобавитьВерсиюМодуля(ВерсииМодулей, ОбработчикиМодуля)

	Если ОбработчикиМодуля.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	Обработка = ОбъектОбработки();
	ОбработчикиМодуля.Сортировать("РедакцияЧислом УБЫВ");

	Максимум = ОбработчикиМодуля[0];
	ЭтоРазрабатываемаяБиблиотека = РазрабатываемыеПодсистемы.Найти(Максимум.Подсистема) <> Неопределено;

	Если ЭтоРазрабатываемаяБиблиотека Тогда
		Описание = ВерсииМодулей.Добавить();
		Описание.ИмяМодуля = Максимум.ИмяОсновногоСерверногоМодуля;
		Описание.Версия = Максимум.Версия;
	КонецЕсли;

	// Проверим максимальный номер сборки из обработчиков модуля
	Если ЗначениеЗаполнено(Максимум.Версия) Тогда
		НомераМаксимум = СтрРазделить(Максимум.Версия, ".");
	Иначе
		НомераМаксимум = СтрРазделить(НоваяВерсияКонфигурации, ".");
	КонецЕсли;
	ПерваяЦифраМаксимум = НомераМаксимум[0];
	НомераМаксимум.Удалить(0);
	Максимум3Последних = Обработка.ВерсияЧислом(НомераМаксимум);

	НомераКонфигурации = СтрРазделить(НоваяВерсияКонфигурации, ".");
	ПерваяЦифраКонфигурации = НомераКонфигурации[0];
	НомераКонфигурации.Удалить(0);
	Конфигурация3Последних = Обработка.ВерсияЧислом(НомераКонфигурации);
	Если ЭтоРазрабатываемаяБиблиотека
		И Число(ПерваяЦифраМаксимум) >= Число(ПерваяЦифраКонфигурации)
		И Максимум3Последних > Конфигурация3Последних Тогда
		НоваяВерсияКонфигурации = ПерваяЦифраКонфигурации + "." + СтрСоединить(НомераМаксимум, ".");
	КонецЕсли;

	// Проверим номер сборки заданный пользователем
	НомераКонфигурации = СтрРазделить(НоваяВерсияКонфигурации, ".");
	Если ЭтоРазрабатываемаяБиблиотека
		И НовыйНомерСборкиКонфигурации > Число(НомераКонфигурации[3]) Тогда
		НомераКонфигурации[3] = Формат(НовыйНомерСборкиКонфигурации, "ЧН=0; ЧГ=0");
		НоваяВерсияКонфигурации = СтрСоединить(НомераКонфигурации, ".");
		НомераМаксимум[3] = НомераКонфигурации[3];
	КонецЕсли;

	НомераМаксимум.Вставить(0,0);

	Если ЭтоРазрабатываемаяБиблиотека Тогда
		Описание.ВерсияРедакции = СтрСоединить(НомераМаксимум, ".");
		Описание.РедакцияЧислом = Обработка.ВерсияЧислом(Описание.ВерсияРедакции);
	КонецЕсли;

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

&НаСервере

Процедура УстановитьВерсиюМодуля(ТекстыМодулей, Модули)

	Если Модули.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	Модули.Сортировать("РедакцияЧислом УБЫВ");
	Максимум = Модули[0];
	Для Каждого Описание Из ТекстыМодулей Цикл

		Модуль = Модули.Найти(Описание.ИмяМодуля, "ИмяМодуля");
		Если Модуль = Неопределено Тогда
			Продолжить;
		КонецЕсли;

		НомераВерсии = СтрРазделить(Модуль.Версия, ".");
		НовыеНомера = СтрРазделить(Максимум.ВерсияРедакции, ".");
		НовыеНомера[0] = НомераВерсии[0];
		Описание.Версия = СтрСоединить(НовыеНомера, ".");

	КонецЦикла;

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

&НаСервере

Функция ОписаниеКодаМодуля(ИмяМодуля = "", ТекстПроцедуры = "", ПроцедураОбработки = "")

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

КонецФункции

&НаСервере

Функция ОписаниеВерсийМодулей()

	Описание = Новый ТаблицаЗначений;
	Описание.Колонки.Добавить("ИмяМодуля", Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(150)));
	Описание.Колонки.Добавить("Версия", , Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(30)));
	Описание.Колонки.Добавить("ВерсияРедакции", , Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(30)));
	Описание.Колонки.Добавить("РедакцияЧислом", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10, 0)));
	Возврат Описание;

КонецФункции

&НаСервере

Функция МодулиОбработчиковОбновления(Обработчики, РазметкаКода, ВыделенныеОбработчики = Неопределено)

	ТипСтрока150 = Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(150));
	Обработчики.Колонки.Добавить("МодульОбработчика", ТипСтрока150);
	Обработчики.Колонки.Добавить("ТэгиМодуляОбновления", ТипСтрока150);
	Обработчики.Колонки.Добавить("ВнешниеТэги", ТипСтрока150);

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

		ЧастиИмени = СтрРазделить(Обработчик.Процедура, ".");
		ЧастиИмени.Удалить(ЧастиИмени.ВГраница());
		Обработчик.МодульОбработчика = СтрСоединить(ЧастиИмени, ".");
		Обработчик.ИмяОбъекта = Обработчик.МодульОбработчика;
		Если ЧастиИмени.Количество() = 1 Тогда
			ЧастиИмени.Вставить(0, "ОбщийМодуль");
		Иначе
			ЧастиИмени[0] = ЕдинственноеЧисло[ЧастиИмени[0]];
		КонецЕсли;
		Обработчик.ИмяОбъекта = СтрСоединить(ЧастиИмени, ".");
		Обработчик.ТэгиМодуляОбновления = ТэгиМодуля;
		Если РазметкаКода.УстановитьТэги И РазметкаКода.МодульЛокализации Тогда
			Обработчик.ТэгиМодуляОбновления = РазметкаКода.ТэгиЛокализации;
		КонецЕсли;

		Если ВыводитьТолькоВыделенные Тогда
			ОбработчикВыделен = ВыделенныеОбработчики.Найти(Обработчик.Ссылка) <> Неопределено;
		КонецЕсли;

		Если ВыводитьТолькоВыделенные И ОбработчикВыделен Тогда
			ВыделенныеОбработчикиМодуля.Добавить(Обработчик.ИмяОбъекта);
		КонецЕсли;

	КонецЦикла;
	МодулиОбработчиков = Обработчики.Скопировать();
	МодулиОбработчиков.Свернуть("МодульОбработчика,ИмяОбъекта,ВнешниеТэги", "Изменен");
	МодулиОбработчиков.Сортировать("МодульОбработчика");

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

	Возврат МодулиОбработчиков;

КонецФункции

&НаСервере

Функция ВыделенныеОбработчики()

	Результат = Новый Массив;
	Для Каждого ИдСтроки Из Элементы.ОбработчикиОбновления.ВыделенныеСтроки Цикл
		Обработчик = Объект.ОбработчикиОбновления.НайтиПоИдентификатору(ИдСтроки);
		Результат.Добавить(Обработчик.Ссылка);
	КонецЦикла;
	Возврат Результат;

КонецФункции

&НаСервере

Процедура СброситьФлагИзменен()

	Отбор = Новый Структура("Изменен", Истина);
	Найденные = Объект.ОбработчикиОбновления.НайтиСтроки(Отбор);
	Для Каждого Обработчик Из Найденные Цикл
		Обработчик.Изменен = Ложь;
	КонецЦикла;

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

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

#Область ФормированиеКодаПроцедур

&НаСервере


Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	Если Не Пользователи.ОбщиеНастройкиВходаИспользуются() Тогда
		Элементы.ГруппаНастройкиВходаПользователей.Видимость = Ложь;
		Элементы.ГруппаВнешниеПользователи.Группировка
			= ГруппировкаПодчиненныхЭлементовФормы.ГоризонтальнаяВсегда;
	КонецЕсли;

	Если ОбщегоНазначения.РазделениеВключено()
	 Или СтандартныеПодсистемыСервер.ЭтоБазоваяВерсияКонфигурации()
	 Или ОбщегоНазначения.ЭтоАвтономноеРабочееМесто()
	 Или Не ПользователиСлужебный.ВнешниеПользователиВнедрены() Тогда

		Элементы.ГруппаВнешниеПользователи.Видимость = Ложь;
		Элементы.ОписаниеРаздела.Заголовок =
			НСтр("ru = 'Администрирование пользователей, настройка групп доступа, управление пользовательскими настройками.'");
	КонецЕсли;

	Если СтандартныеПодсистемыСервер.ЭтоБазоваяВерсияКонфигурации()
	 Или ОбщегоНазначения.ЭтоАвтономноеРабочееМесто() Тогда

		Элементы.ИспользоватьГруппыПользователей.Доступность = Ложь;
	КонецЕсли;

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

		Если ОбщегоНазначения.ЭтоАвтономноеРабочееМесто() Тогда
			Элементы.ОграничиватьДоступНаУровнеЗаписей.Доступность = Ложь;
		КонецЕсли;
	Иначе
		Элементы.ГруппаГруппыДоступа.Видимость = Ложь;
	КонецЕсли;

	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ДатыЗапретаИзменения") Тогда
		Элементы.ГруппаДатыЗапретаИзменения.Видимость = Ложь;
	КонецЕсли;

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

	Если ОбщегоНазначения.РазделениеВключено() Тогда
		Элементы.ВосстановлениеПаролей.Видимость = Ложь;
	КонецЕсли;

	// Обновление состояния элементов.
	УстановитьДоступность();

	НастройкиПрограммыПереопределяемый.НастройкиПользователейИПравПриСозданииНаСервере(ЭтотОбъект);

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

&НаКлиенте

Процедура ПриЗакрытии(ЗавершениеРаботы)
	Если ЗавершениеРаботы Тогда
		Возврат;
	КонецЕсли;
	ОбновитьИнтерфейсПрограммы();
КонецПроцедуры

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

	Если ИмяСобытия <> "Запись_НаборКонстант" Тогда
		Возврат;
	КонецЕсли;

	Если Источник = "ИспользоватьАнкетирование"
		И ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.Анкетирование") Тогда

		Прочитать();
		УстановитьДоступность();

	ИначеЕсли Источник = "ИспользоватьСкрытиеПерсональныхДанныхСубъектов" Тогда
		Прочитать();
	КонецЕсли;

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

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

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте

Процедура ИспользоватьГруппыПользователейПриИзменении(Элемент)
	Подключаемый_ПриИзмененииРеквизита(Элемент);
КонецПроцедуры

&НаКлиенте

Процедура ОграничиватьДоступНаУровнеЗаписейУниверсальноПриИзменении(Элемент)

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

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

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

&НаКлиенте

Процедура ОграничиватьДоступНаУровнеЗаписейПриИзменении(Элемент)

	Если НаборКонстант.ОграничиватьДоступНаУровнеЗаписейУниверсально Тогда
		ТекстВопроса =
			НСтр("ru = 'Настройки групп доступа вступят в силу постепенно
			           |(см. ход по ссылке ""Обновление доступа на уровне записей"").
			           |
			           |Обновление доступа может замедлить работу программы и выполняться
			           |от нескольких секунд до часов (в зависимости от объема данных).'");
		Если НаборКонстант.ОграничиватьДоступНаУровнеЗаписей Тогда
			ТекстВопроса = НСтр("ru = 'Включить ограничение доступа на уровне записей?'")
				+ Символы.ПС + Символы.ПС + ТекстВопроса;
		Иначе
			ТекстВопроса = НСтр("ru = 'Выключить ограничение доступа на уровне записей?'")
				+ Символы.ПС + Символы.ПС + ТекстВопроса;
		КонецЕсли;

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

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

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

&НаКлиенте


Функция Подключаемый_СтраницаОкончание_ПриОткрытии(Отказ, ПропуститьСтраницу, ЭтоПереходДалее)

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

	Возврат Неопределено;

КонецФункции

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

#Область ДополнительныеОбработчикиПереходов

&НаКлиенте

Процедура ИзменитьПорядковыйНомерПерехода(Итератор)

	ОчиститьСообщения();

	УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода + Итератор);

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

&НаКлиенте

Процедура УстановитьПорядковыйНомерПерехода(Знач Значение)

	ЭтоПереходДалее = (Значение > ПорядковыйНомерПерехода);

	ПорядковыйНомерПерехода = Значение;

	Если ПорядковыйНомерПерехода < 1 Тогда

		ПорядковыйНомерПерехода = 1;

	КонецЕсли;

	ПорядковыйНомерПереходаПриИзменении(ЭтоПереходДалее);

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

&НаКлиенте

Процедура ПорядковыйНомерПереходаПриИзменении(Знач ЭтоПереходДалее)

	// Выполняем обработчики событий перехода.
	ВыполнитьОбработчикиСобытийПерехода(ЭтоПереходДалее);

	// Устанавливаем отображение страниц.
	СтрокиПереходаТекущие = ТаблицаПереходов.НайтиСтроки(Новый Структура("ПорядковыйНомерПерехода", ПорядковыйНомерПерехода));

	Если СтрокиПереходаТекущие.Количество() = 0 Тогда
		ВызватьИсключение НСтр("ru = 'Не определена страница для отображения.'");
	КонецЕсли;

	СтрокаПереходаТекущая = СтрокиПереходаТекущие[0];

	Элементы.ПанельОсновная.ТекущаяСтраница  = Элементы[СтрокаПереходаТекущая.ИмяОсновнойСтраницы];
	Элементы.ПанельНавигации.ТекущаяСтраница = Элементы[СтрокаПереходаТекущая.ИмяСтраницыНавигации];

	Элементы.ПанельНавигации.ТекущаяСтраница.Доступность = Не (ЭтоПереходДалее И СтрокаПереходаТекущая.ДлительнаяОперация);

	// Устанавливаем текущую кнопку по умолчанию.
	КнопкаДалее = ПолучитьКнопкуФормыПоИмениКоманды(Элементы.ПанельНавигации.ТекущаяСтраница, "КомандаДалее");

	Если КнопкаДалее <> Неопределено Тогда

		КнопкаДалее.КнопкаПоУмолчанию = Истина;

	Иначе

		КнопкаГотово = ПолучитьКнопкуФормыПоИмениКоманды(Элементы.ПанельНавигации.ТекущаяСтраница, "КомандаГотово");

		Если КнопкаГотово <> Неопределено Тогда

			КнопкаГотово.КнопкаПоУмолчанию = Истина;

		КонецЕсли;

	КонецЕсли;

	Если ЭтоПереходДалее И СтрокаПереходаТекущая.ДлительнаяОперация Тогда

		ПодключитьОбработчикОжидания("ВыполнитьОбработчикДлительнойОперации", 0.1, Истина);

	КонецЕсли;

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

&НаКлиенте

Процедура ВыполнитьОбработчикиСобытийПерехода(Знач ЭтоПереходДалее)

	// Обработчики событий переходов.
	Если ЭтоПереходДалее Тогда

		СтрокиПерехода = ТаблицаПереходов.НайтиСтроки(Новый Структура("ПорядковыйНомерПерехода", ПорядковыйНомерПерехода - 1));

		Если СтрокиПерехода.Количество() > 0 Тогда
			СтрокаПерехода = СтрокиПерехода[0];

			// Обработчик ПриПереходеДалее.
			Если Не ПустаяСтрока(СтрокаПерехода.ИмяОбработчикаПриПереходеДалее)
				И Не СтрокаПерехода.ДлительнаяОперация Тогда

				ИмяПроцедуры = "[ИмяОбработчика](Отказ)";
				ИмяПроцедуры = СтрЗаменить(ИмяПроцедуры, "[ИмяОбработчика]", СтрокаПерехода.ИмяОбработчикаПриПереходеДалее);

				Отказ = Ложь;

				Результат = Вычислить(ИмяПроцедуры);

				Если Отказ Тогда

					УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода - 1);

					Возврат;

				КонецЕсли;

			КонецЕсли;
		КонецЕсли;

	Иначе

		СтрокиПерехода = ТаблицаПереходов.НайтиСтроки(Новый Структура("ПорядковыйНомерПерехода", ПорядковыйНомерПерехода + 1));

		Если СтрокиПерехода.Количество() > 0 Тогда
			СтрокаПерехода = СтрокиПерехода[0];

			// Обработчик ПриПереходеНазад.
			Если Не ПустаяСтрока(СтрокаПерехода.ИмяОбработчикаПриПереходеНазад)
				И Не СтрокаПерехода.ДлительнаяОперация Тогда

				ИмяПроцедуры = "[ИмяОбработчика](Отказ)";
				ИмяПроцедуры = СтрЗаменить(ИмяПроцедуры, "[ИмяОбработчика]", СтрокаПерехода.ИмяОбработчикаПриПереходеНазад);

				Отказ = Ложь;

				Результат = Вычислить(ИмяПроцедуры);

				Если Отказ Тогда

					УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода + 1);

					Возврат;

				КонецЕсли;

			КонецЕсли;
		КонецЕсли;

	КонецЕсли;

	СтрокиПереходаТекущие = ТаблицаПереходов.НайтиСтроки(Новый Структура("ПорядковыйНомерПерехода", ПорядковыйНомерПерехода));

	Если СтрокиПереходаТекущие.Количество() = 0 Тогда
		ВызватьИсключение НСтр("ru = 'Не определена страница для отображения.'");
	КонецЕсли;

	СтрокаПереходаТекущая = СтрокиПереходаТекущие[0];

	Если СтрокаПереходаТекущая.ДлительнаяОперация И Не ЭтоПереходДалее Тогда

		УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода - 1);
		Возврат;
	КонецЕсли;

	// обработчик ПриОткрытии
	Если Не ПустаяСтрока(СтрокаПереходаТекущая.ИмяОбработчикаПриОткрытии) Тогда

		ИмяПроцедуры = "[ИмяОбработчика](Отказ, ПропуститьСтраницу, ЭтоПереходДалее)";
		ИмяПроцедуры = СтрЗаменить(ИмяПроцедуры, "[ИмяОбработчика]", СтрокаПереходаТекущая.ИмяОбработчикаПриОткрытии);

		Отказ = Ложь;
		ПропуститьСтраницу = Ложь;

		Результат = Вычислить(ИмяПроцедуры);

		Если Отказ Тогда

			УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода - 1);

			Возврат;

		ИначеЕсли ПропуститьСтраницу Тогда

			Если ЭтоПереходДалее Тогда

				УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода + 1);

				Возврат;

			Иначе

				УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода - 1);

				Возврат;

			КонецЕсли;

		КонецЕсли;

	КонецЕсли;

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

&НаКлиенте

Процедура ВыполнитьОбработчикДлительнойОперации()

	СтрокиПереходаТекущие = ТаблицаПереходов.НайтиСтроки(Новый Структура("ПорядковыйНомерПерехода", ПорядковыйНомерПерехода));

	Если СтрокиПереходаТекущие.Количество() = 0 Тогда
		ВызватьИсключение НСтр("ru = 'Не определена страница для отображения.'");
	КонецЕсли;

	СтрокаПереходаТекущая = СтрокиПереходаТекущие[0];

	// Обработчик ОбработкаДлительнойОперации.
	Если Не ПустаяСтрока(СтрокаПереходаТекущая.ИмяОбработчикаДлительнойОперации) Тогда

		ИмяПроцедуры = "[ИмяОбработчика](Отказ, ПерейтиДалее)";
		ИмяПроцедуры = СтрЗаменить(ИмяПроцедуры, "[ИмяОбработчика]", СтрокаПереходаТекущая.ИмяОбработчикаДлительнойОперации);

		Отказ = Ложь;
		ПерейтиДалее = Истина;

		Результат = Вычислить(ИмяПроцедуры);

		Если Отказ Тогда

			УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода - 1);

			Возврат;

		ИначеЕсли ПерейтиДалее Тогда

			УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода + 1);

			Возврат;

		КонецЕсли;

	Иначе

		УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода + 1);

		Возврат;

	КонецЕсли;

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

&НаКлиенте

Функция ПолучитьКнопкуФормыПоИмениКоманды(ЭлементФормы, ИмяКоманды)

	Для Каждого Элемент Из ЭлементФормы.ПодчиненныеЭлементы Цикл

		Если ТипЗнч(Элемент) = Тип("ГруппаФормы") Тогда

			ЭлементФормыПоИмениКоманды = ПолучитьКнопкуФормыПоИмениКоманды(Элемент, ИмяКоманды);

			Если ЭлементФормыПоИмениКоманды <> Неопределено Тогда

				Возврат ЭлементФормыПоИмениКоманды;

			КонецЕсли;

		ИначеЕсли ТипЗнч(Элемент) = Тип("КнопкаФормы")
			И СтрНайти(Элемент.ИмяКоманды, ИмяКоманды) > 0 Тогда

			Возврат Элемент;

		Иначе

			Продолжить;

		КонецЕсли;

	КонецЦикла;

	Возврат Неопределено;

КонецФункции

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

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


Процедура ДополнениеВыгрузкиВариантВыгрузкиПриИзменении(Элемент)
	ДополнениеВыгрузкиВариантВыгрузкиУстановитьВидимость();
КонецПроцедуры

&НаКлиенте

Процедура ДополнениеВыгрузкиПериодОтбораСценарияУзлаПриИзменении(Элемент)
	ДополнениеВыгрузкиИзменениеПериодаСценарияУзла();
КонецПроцедуры

&НаКлиенте

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

&НаКлиенте

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

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

#Область ОбработчикиСобытийЭлементовТаблицыФормыДеревоИнформацииСтатистики

&НаКлиенте

Процедура ДеревоИнформацииСтатистикиВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)

	ОткрытьФормуСопоставления(Неопределено);

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

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

#Область ОбработчикиКомандФормы

&НаКлиенте

Процедура КомандаДалее(Команда)

	ИзменитьПорядковыйНомерПерехода(+1);

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

&НаКлиенте

Процедура КомандаОтмена(Команда)

	ОтменаСопоставления = Истина;
	Закрыть();

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

&НаКлиенте

Процедура КомандаГотово(Команда)
	// Обновляем все открытые динамические списки.
	ОбменДаннымиКлиент.ОбновитьВсеОткрытыеДинамическиеСписки();

	Результат = Новый Структура;
	Результат.Вставить("РезультатВыгрузкиДанных", РезультатВыгрузкиДанных);
	Результат.Вставить("РезультатЗагрузкиДанных", РезультатЗагрузкиДанных);

	ЗакрытьФормуБезусловно = Истина;
	Закрыть(Результат);

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

&НаКлиенте

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

&НаКлиенте

Процедура ПродолжитьСинхронизацию(Команда)

	ПорядковыйНомерПерехода = ПорядковыйНомерПерехода - 1;
	УстановитьПорядковыйНомерПерехода(ПорядковыйНомерПерехода + 1);

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

&НаКлиенте

Процедура ЗавершитьСинхронизацию(Команда)

	ЗавершитьСинхронизациюНаСервере();

	ЗакрытьФормуБезусловно = Истина;
	Закрыть();

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

&НаСервере

Процедура ЗавершитьСинхронизациюНаСервере()

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

	ОтменитьОчередьИПродолжитьНаСервере();

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

////////////////////////////////////////////////////////////////////////////////
// Страница СтраницаНачала

&НаКлиенте

Процедура ОткрытьКаталогОбменаИнформацией(Команда)

	ОткрытьКаталогОбменаИнформациейУзла();

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

&НаКлиенте

Процедура НастроитьПараметрыТранспортаСообщенийОбмена(Команда)

	Отбор              = Новый Структура("Корреспондент", Объект.УзелИнформационнойБазы);
	ЗначенияЗаполнения = Новый Структура("Корреспондент", Объект.УзелИнформационнойБазы);

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

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

////////////////////////////////////////////////////////////////////////////////
// Страница СтраницаИнформацииСтатистики

&НаКлиенте

Процедура ОбновитьИнформациюСопоставленияПолностью(Команда)

	ТекущиеДанные = Элементы.ДеревоИнформацииСтатистики.ТекущиеДанные;

	Если ТекущиеДанные <> Неопределено Тогда

		КлючТекущейСтроки = ТекущиеДанные.Ключ;

	КонецЕсли;

	Отказ = Ложь;

	КлючиСтрок = Новый Массив;

	ПолучитьКлючиВсехСтрок(КлючиСтрок, ДеревоИнформацииСтатистики.ПолучитьЭлементы());

	Если КлючиСтрок.Количество() > 0 Тогда

		ОбновитьИнформациюСопоставленияПоСтрокеНаСервере(Отказ, КлючиСтрок);

	КонецЕсли;

	Если Отказ Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'При получении информации статистики возникли ошибки.'"));
	Иначе

		РазвернутьДеревоИнформацииСтатистики(КлючТекущейСтроки);

		ПоказатьОповещениеПользователя(НСтр("ru = 'Сбор информации завершен'"));
	КонецЕсли;

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

&НаКлиенте

Процедура ВыполнитьЗагрузкуДанныхДляСтроки(Команда)

	Отказ = Ложь;

	ВыделенныеСтроки = Элементы.ДеревоИнформацииСтатистики.ВыделенныеСтроки;

	Если ВыделенныеСтроки.Количество() = 0 Тогда
		НСтрока = НСтр("ru = 'Выберите имя таблицы в поле статистической информации.'");
		ОбщегоНазначенияКлиент.СообщитьПользователю(НСтрока,,"ДеревоИнформацииСтатистики",, Отказ);
		Возврат;
	КонецЕсли;

	ЕстьНесопоставленныеОбъекты = Ложь;
	Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл
		СтрокаДерева = ДеревоИнформацииСтатистики.НайтиПоИдентификатору(ИдентификаторСтроки);

		Если ПустаяСтрока(СтрокаДерева.Ключ) Тогда
			Продолжить;
		КонецЕсли;

		Если СтрокаДерева.КоличествоОбъектовНесопоставленных <> 0 Тогда
			ЕстьНесопоставленныеОбъекты = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Если ЕстьНесопоставленныеОбъекты Тогда
		НСтрока = НСтр("ru = 'Имеются несопоставленные объекты.
		                     |При загрузке данных будут созданы дубли несопоставленных объектов. Продолжить?'");

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

	ВыполнитьЗагрузкуДанныхДляСтрокиПродолжение(ВыделенныеСтроки);
КонецПроцедуры

&НаКлиенте

Процедура ОткрытьФормуСопоставления(Команда)

	ТекущиеДанные = Элементы.ДеревоИнформацииСтатистики.ТекущиеДанные;

	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Если ПустаяСтрока(ТекущиеДанные.Ключ) Тогда
		Возврат;
	КонецЕсли;

	Если Не ТекущиеДанные.ИспользоватьПредварительныйПросмотр Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Для типа данных нельзя выполнить сопоставление объектов.'"));
		Возврат;
	КонецЕсли;

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

	ПараметрыФормы.Вставить("УзелИнформационнойБазы",               Объект.УзелИнформационнойБазы);
	ПараметрыФормы.Вставить("ИмяФайлаСообщенияОбмена",              Объект.ИмяФайлаСообщенияОбмена);

	ОткрытьФорму("Обработка.СопоставлениеОбъектовИнформационныхБаз.Форма", ПараметрыФормы, ЭтотОбъект);

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

////////////////////////////////////////////////////////////////////////////////
// Страница СтраницаОкончанияСопоставления

&НаКлиенте

Процедура ПерейтиВЖурналРегистрацииСобытийЗагрузкиДанных(Команда)

	ОбменДаннымиКлиент.ПерейтиВЖурналРегистрацииСобытийДанныхМодально(Объект.УзелИнформационнойБазы, ЭтотОбъект, "ЗагрузкаДанных");

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

&НаКлиенте


Процедура ПриЗавершенииВыгрузкиДанныхНаСервере(ПараметрыОбработчика, ДанныеВыгружены, СообщениеОбОшибке)

	МодульПомощникИнтерактивногоОбмена = ОбменДаннымиСервер.МодульПомощникИнтерактивногоОбменаДаннымиВМоделиСервиса();

	Если МодульПомощникИнтерактивногоОбмена = Неопределено Тогда
		ДанныеВыгружены = Ложь;
		Возврат;
	КонецЕсли;

	СтатусЗавершения = Неопределено;

	МодульПомощникИнтерактивногоОбмена.ПриЗавершенииВыгрузкиДанных(ПараметрыОбработчика, СтатусЗавершения);
	ПараметрыОбработчика = Неопределено;

	Если СтатусЗавершения.Отказ Тогда
		ДанныеВыгружены = Ложь;
		СообщениеОбОшибке = СтатусЗавершения.СообщениеОбОшибке;
		Возврат;
	Иначе
		ДанныеВыгружены = СтатусЗавершения.Результат.ДанныеВыгружены;

		Если Не ДанныеВыгружены Тогда
			СообщениеОбОшибке = СтатусЗавершения.Результат.СообщениеОбОшибке;
			Возврат;
		КонецЕсли;
	КонецЕсли;

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

&НаКлиенте

Процедура ЗавершениеВыгрузкиДанных()

	ОбработатьСтатусВыполненияФоновогоЗадания();

	ОтображаетсяПрогрессБар = Элементы.ПанельОсновная.ТекущаяСтраница = Элементы.СтраницаОжиданияСинхронизацииДанныхПрогрессБарЗагрузка
		Или Элементы.ПанельОсновная.ТекущаяСтраница = Элементы.СтраницаОжиданияСинхронизацииДанныхПрогрессБарВыгрузка;

	Если ИспользоватьПрогрессБар И ОтображаетсяПрогрессБар Тогда
		ПроцентВыполнения       = 100;
		ДопИнформацияВыполнение = "";
	КонецЕсли;

	ЗавершениеВыгрузкиНаСервере();

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

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

&НаСервере

Процедура ЗавершениеВыгрузкиНаСервере()

	РезультатВыполненияМетода = ПолучитьИзВременногоХранилища(РезультатВыполненияФоновогоЗадания.АдресРезультата);

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

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

	Если ЗначениеЗаполнено(СообщениеОбОшибке) Тогда

		ДлительнаяОперация                  = Ложь;
		ДлительнаяОперацияЗавершена         = Истина;
		ДлительнаяОперацияЗавершенаСОшибкой = Истина;

		ОбменДаннымиВызовСервера.ЗафиксироватьЗавершениеОбменаСОшибкой(
			Объект.УзелИнформационнойБазы,
			"ВыгрузкаДанных",
			ДатаНачалаОперации,
			СообщениеОбОшибке);

	КонецЕсли;

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

&НаСервере

Процедура ПриНачалеВыгрузкиДанныхЧерезВнутреннююПубликациюНаСервере()

	СтруктураДополнение = Неопределено;
	ПодготовитьСтруктуруДополненияВыгрузки(СтруктураДополнение);

	МодульОбменДаннымиВнутренняяПубликация = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиВнутренняяПубликация");
	МодульОбменДаннымиВнутренняяПубликация.ВыполнитьОбменДаннымиВручную(Объект.УзелИнформационнойБазы,
		ПараметрыОбменаЧерезВнутреннююПубликацию, СтруктураДополнение);

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

&НаКлиенте

Процедура ПриОжиданииВыгрузкиДанныхЧерезВнутреннююПубликацию()

	ПродолжитьОжидание = Ложь;
	ПриОжиданииВыгрузкиДанныхЧерезВнутреннююПубликациюНаСервере(ПараметрыОбменаЧерезВнутреннююПубликацию, ПродолжитьОжидание);

	Если ПродолжитьОжидание Тогда
		ОбменДаннымиКлиент.ОбновитьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжиданияВыгрузкиДанных);

		ПодключитьОбработчикОжидания("ПриОжиданииВыгрузкиДанныхЧерезВнутреннююПубликацию",
			ПараметрыОбработчикаОжиданияВыгрузкиДанных.ТекущийИнтервал, Истина);
	Иначе
		ПриЗавершенииВыгрузкиДанныхЧерезВнутреннююПубликацию();
	КонецЕсли;

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

&НаСервереБезКонтекста

Процедура ПриОжиданииВыгрузкиДанныхЧерезВнутреннююПубликациюНаСервере(ПараметрыОбмена, ПродолжитьОжидание)

	МодульОбменДаннымиВнутренняяПубликация = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиВнутренняяПубликация");
	МодульОбменДаннымиВнутренняяПубликация.ПриОжиданииВыгрузкиДанных(ПараметрыОбмена, ПродолжитьОжидание);

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

&НаКлиенте

Процедура ПриЗавершенииВыгрузкиДанныхЧерезВнутреннююПубликацию()

	ВыводитьОписаниеОшибкиПользователю = Истина;
	СообщениеОбОшибке = ПараметрыОбменаЧерезВнутреннююПубликацию.СообщениеОбОшибке;

	ИзменитьПорядковыйНомерПерехода(+1);

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

////////////////////////////////////////////////////////////////////////////////
// Страницы итоговой информации

&НаКлиенте

Функция Подключаемый_СтраницаОкончанияСопоставления_ПриОткрытии(Отказ, ПропуститьСтраницу, Знач ЭтоПереходДалее)

	ПолучитьСостоянияОбменовДанными(РезультатЗагрузкиДанных, РезультатВыгрузкиДанных, Объект.УзелИнформационнойБазы);

	ОбновитьОтображениеЭлементовСтатусаОбменаДанными();

	ЗакрытьФормуБезусловно = Истина;

	Возврат Неопределено;

КонецФункции

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

////////////////////////////////////////////////////////////////////////////////
// РАЗДЕЛ ИНИЦИАЛИЗАЦИИ ПЕРЕХОДОВ

&НаСервере


Процедура ПриОжиданииВыгрузкиДанных(ПараметрыОбработчика, ПродолжитьОжидание) Экспорт

	Если ПараметрыОбработчика.ДополнительныеПараметры.Свойство("ОжиданиеСессииВыгрузкиЗагрузкиДанных") Тогда

		ПриОжиданииСессииОбменаСообщениямиСистемы(
			ПараметрыОбработчика.ДополнительныеПараметры.ПараметрыОбработчикаСессии, ПродолжитьОжидание);

	ИначеЕсли ПараметрыОбработчика.ДополнительныеПараметры.Свойство("ОжиданиеДлительнойОперацииВыгрузкиЗагрузкиДанных") Тогда

		ПараметрыОбработчикаДлительнойОперации = ПараметрыОбработчика.ДополнительныеПараметры.ПараметрыОбработчикаДлительнойОперации;

		ЗаданиеВыполнено = Ложь;

		Если ПараметрыОбработчика.ДополнительныеПараметры.Свойство("ФоновоеЗаданиеВыполнено") Тогда
			ЗаданиеВыполнено = Истина;
		Иначе
			ПриОжиданииДлительнойОперации(ПараметрыОбработчикаДлительнойОперации, ПродолжитьОжидание);

			ЗаданиеВыполнено = Не ПродолжитьОжидание И Не ПараметрыОбработчикаДлительнойОперации.Отказ;
		КонецЕсли;

		Если ЗаданиеВыполнено Тогда

			Результат = ПолучитьИзВременногоХранилища(ПараметрыОбработчикаДлительнойОперации.АдресРезультата);

			Если Результат.Свойство("ПараметрыОбработчикаСессии") Тогда

				ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ОжиданиеСессииВыгрузкиЗагрузкиДанных");
				ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ПараметрыОбработчикаСессии", Результат.ПараметрыОбработчикаСессии);

				ПродолжитьОжидание = Истина;

			Иначе

				ПродолжитьОжидание = Ложь;

			КонецЕсли;

		КонецЕсли;

	Иначе

		ПриОжиданииСессииОбменаСообщениямиСистемы(ПараметрыОбработчика, ПродолжитьОжидание);

		Если Не ПродолжитьОжидание
			И Не ПараметрыОбработчика.Отказ Тогда

			НастройкиВыгрузкиХранилище = Неопределено;
			ПараметрыОбработчика.ДополнительныеПараметры.Свойство("НастройкиВыгрузки", НастройкиВыгрузкиХранилище);
			НастройкиВыгрузки = НастройкиВыгрузкиХранилище.Получить();

			ПараметрыКорреспондента = Неопределено;

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

				ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииСинхронизацииДанных(),
					УровеньЖурналаРегистрации.Ошибка, , , ПараметрыОбработчика.СообщениеОбОшибке);

				ПродолжитьОжидание = Ложь;
				Возврат;
			КонецПопытки;

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

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

			КлючФоновогоЗадания = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Обмен данными (%1)'"),
				НастройкиВыгрузки.Корреспондент);

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

			ПараметрыПроцедуры = Новый Структура;
			ПараметрыПроцедуры.Вставить("НастройкиВыгрузки", НастройкиВыгрузки);

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

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

			ПараметрыОбработчикаДлительнойОперации = Неопределено;
			ПриНачалеДлительнойОперации(ФоновоеЗадание, ПараметрыОбработчикаДлительнойОперации, ПродолжитьОжидание);

			ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ОжиданиеДлительнойОперацииВыгрузкиЗагрузкиДанных");
			ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ПараметрыОбработчикаДлительнойОперации", ПараметрыОбработчикаДлительнойОперации);

			Если Не ПродолжитьОжидание
				И Не ПараметрыОбработчика.Отказ Тогда
				ПараметрыОбработчика.ДополнительныеПараметры.Вставить("ФоновоеЗаданиеВыполнено");
				ПродолжитьОжидание = Истина;
			КонецЕсли;

		КонецЕсли;

	КонецЕсли;

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

// Параметры:
//   ПараметрыОбработчика - Структура - вспомогательные параметры:
//     * ДополнительныеПараметры - Структура - произвольные дополнительные параметры.
//   СтатусЗавершения - Структура - описание результата выполнения операции.
//

Процедура ПриЗавершенииВыгрузкиДанных(ПараметрыОбработчика, СтатусЗавершения) Экспорт

	ИнициализироватьСтатусЗавершенияДлительнойОперации(СтатусЗавершения);

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

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

		Если ПараметрыОбработчикаСессии.Отказ Тогда
			Результат.ДанныеВыгружены   = Ложь;
			Результат.СообщениеОбОшибке = ПараметрыОбработчикаСессии.СообщениеОбОшибке;
		КонецЕсли;

		СтатусЗавершения.Результат = Результат;

	КонецЕсли;

	ПараметрыОбработчика = Неопределено;

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

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

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

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

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

Процедура ПриОжиданииСессииОбменаСообщениямиСистемы(ПараметрыОбработчика, ПродолжитьОжидание)

	СтатусСессии = "";
	Попытка
		СтатусСессии = СтатусСессии(ПараметрыОбработчика.ИдентификаторОперации);
	Исключение
		СообщениеОбОшибке = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());

		ЗаписьЖурналаРегистрации(ОбменДаннымиВМоделиСервиса.СобытиеЖурналаРегистрацииМониторСинхронизацииДанных(),
			УровеньЖурналаРегистрации.Ошибка, , , СообщениеОбОшибке);

		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.СообщениеОбОшибке = СообщениеОбОшибке;
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;

		ПродолжитьОжидание  = Ложь;
		Возврат;
	КонецПопытки;

	Если СтатусСессии = "Успешно" Тогда

		ПродолжитьОжидание = Ложь;

	ИначеЕсли СтатусСессии = "Ошибка" Тогда

		ПараметрыОбработчика.Отказ = Истина;
		ПараметрыОбработчика.ИдентификаторОперации = Неопределено;
		ПродолжитьОжидание  = Ложь;

	Иначе

		ПродолжитьОжидание = Истина;

	КонецЕсли;

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