Документооборот с контролирующими органами / Подписи под документами / Модуль формы

файл
&НаСервере
Перем КонтекстЭДОСервер Экспорт;

&НаСервере
Перем ТипыСообщенийСДИВамиВПроизвольномСообщении;

&НаСервере
Перем ТипыСообщенийСДИВамиВОсновании;

&НаКлиенте
Перем КонтекстЭДОКлиент;

#Область ОбработчикиСобытийФормы

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

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

&НаКлиенте
Процедура ПриОткрытии(Отказ)

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

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

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

&НаКлиенте
Процедура ЦиклОбменаПриИзменении(Элемент)
	ОтработатьИзменениеЦиклаОбмена();
КонецПроцедуры

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

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

&НаКлиенте
Процедура ДокументПредставлениеПриИзменении(Элемент)

	ПрорисоватьДокумент();
	СформироватьТаблицуПодписей();
	ОформитьСтрокиПодписей();
	УправлениеЭУ();

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

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

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

	// получаем список возможных имен файлов
	ЗаполнитьСписокДокументовСообщения(ТранспортноеСообщение);

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

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

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

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

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

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

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

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

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

&НаКлиенте
Процедура КомандаПодписиПроверить(Команда)

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

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

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

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

&НаСервере
Процедура ПрорисоватьТранспортноеСообщение()
	
	Если НЕ ЗначениеЗаполнено(ТранспортноеСообщение) Тогда
		ТранспортноеСообщениеПредставление = "";
	Иначе
		ТранспортноеСообщениеПредставление = "" + ТранспортноеСообщение.Тип + " от " + ТранспортноеСообщение.Дата;
	КонецЕсли;
	
КонецПроцедуры

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

	ПрорисоватьТранспортноеСообщение();
	ПрорисоватьДокумент();
	
КонецПроцедуры

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

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

	// извлекаем из ИБ тип документа
	Вложения = КонтекстЭДОСервер.ПолучитьВложенияТранспортногоСообщения(ТранспортноеСообщение, Ложь, , ИмяФайлаДокумента);
	Если Вложения.Количество() = 0 Тогда
		Если ЗначениеЗаполнено(ТранспортноеСообщение.Основание) Тогда
			Если ТипыСообщенийСДИВамиВОсновании = Неопределено Тогда 
				ОпределитьТипыСообщений("ТипыСообщенийСДИВамиВОсновании");
			КонецЕсли;
			Если ТипыСообщенийСДИВамиВОсновании.Найти(ТранспортноеСообщение.Тип) <> Неопределено Тогда
				Вложения = КонтекстЭДОСервер.ПолучитьВложенияТранспортногоСообщения(ТранспортноеСообщение.Основание, Ложь, , ИмяФайлаДокумента);
			КонецЕсли;
		Иначе
			Если ТипыСообщенийСДИВамиВПроизвольномСообщении = Неопределено Тогда 
				ОпределитьТипыСообщений("ТипыСообщенийСДИВамиВПроизвольномСообщении");
			КонецЕсли;
			ТипСообщенияОснования = ТипыСообщенийСДИВамиВПроизвольномСообщении[ТранспортноеСообщение.Тип];
			Если ЗначениеЗаполнено(ТипСообщенияОснования) Тогда
				СообщениеОснование = КонтекстЭДОСервер.ПолучитьСообщениеЦиклаОбмена(ТранспортноеСообщение.ЦиклОбмена, ТипСообщенияОснования);
				Если ЗначениеЗаполнено(СообщениеОснование) Тогда
					Вложения = КонтекстЭДОСервер.ПолучитьВложенияТранспортногоСообщения(СообщениеОснование, Ложь, , ИмяФайлаДокумента);
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	// прорисываем представление
	Если Вложения.Количество() = 0 Тогда
		ДокументПредставление = ИмяФайлаДокумента;
	Иначе
		ДокументПредставление = "" + Вложения[0].Тип + ": " + ИмяФайлаДокумента;
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция ОпределитьТипыСообщений(ПараметрВызова)

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

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

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

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

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

&НаКлиенте
Процедура ОформитьСтрокиПодписейПослеПолучениеСвойствСертификатов(Результат, ВходящийКонтекст) Экспорт
	
	Если Результат.Выполнено И Результат.Сертификаты.Количество() > 0 Тогда
		
		СвойстваСертификатов = Результат.Сертификаты;
	
		Если СвойстваСертификатов <> Неопределено Тогда
			Для Каждого ЭлементСтроки Из ПодписиПредставление Цикл
				Для каждого СвойстваСертификата Из СвойстваСертификатов Цикл
					
					ОтпечатокСертификата = ЭлементСтроки.ЭЦПСертификат;
					Если СвойстваСертификата.Отпечаток = ЭлементСтроки.ЭЦПСертификат Тогда
						
						ЭлементСтроки.СвойстваСертификата = СвойстваСертификата;
					
						// прорисовываем ячейку "Сертификат"
						Если ЗначениеЗаполнено(ОтпечатокСертификата) Тогда
							Если СвойстваСертификата = Неопределено Тогда
								ЭлементСтроки.ЭЦПСертификатПредставление = "Отпечаток: " + ОтпечатокСертификата;
							Иначе
								ЭлементСтроки.ЭЦПСертификатПредставление = КонтекстЭДОКлиент.ПредставлениеСертификатаПоСвойствам(СвойстваСертификата);
							КонецЕсли;
						КонецЕсли;
						
						// прорисовываем статус проверки
						Если ЭлементСтроки.ЭЦПСтатусПроверки = КонтекстЭДОКлиент.СтруктураСсылочныхДанных.Перечисления_СтатусыПроверкиЭЦП_ПустаяСсылка Тогда
							ЭлементСтроки.ЭЦПСтатусПроверкиПредставление = "<не проверена>";
						Иначе
							ЭлементСтроки.ЭЦПСтатусПроверкиПредставление = Строка(ЭлементСтроки.ЭЦПСтатусПроверки);
						КонецЕсли;
					
					КонецЕсли;
				КонецЦикла; 
				
			КонецЦикла;
		КонецЕсли;
		
	Иначе
		Для Каждого ЭлементСтроки Из ПодписиПредставление Цикл
			Если ЭлементСтроки.ЭЦПСтатусПроверки = КонтекстЭДОКлиент.СтруктураСсылочныхДанных.Перечисления_СтатусыПроверкиЭЦП_ПустаяСсылка Тогда
				ЭлементСтроки.ЭЦПСтатусПроверкиПредставление = "<не проверена>";
			Иначе
				ЭлементСтроки.ЭЦПСтатусПроверкиПредставление = Строка(ЭлементСтроки.ЭЦПСтатусПроверки);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура ОтработатьИзменениеЦиклаОбмена()
	
	Если ТранспортноеСообщение.ЦиклОбмена <> ЦиклОбмена Тогда
		ТранспортноеСообщение = Неопределено;
		ОтработатьИзменениеТранспортногоСообщения();
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура ОтработатьИзменениеТранспортногоСообщения()

	Если ЗначениеЗаполнено(ТранспортноеСообщение) Тогда
		ЦиклОбмена = ТранспортноеСообщение.ЦиклОбмена;
		МестоХраненияКлюча = КриптографияЭДКОКлиентСервер.КонтекстМоделиХраненияКлюча(ЦиклОбмена);
	КонецЕсли;

	ЗаполнитьСписокДокументовСообщения(ТранспортноеСообщение);
	Если СписокДокументов.НайтиПоЗначению(ИмяФайлаДокумента) = Неопределено Тогда
		ИмяФайлаДокумента = "";
		Если СписокДокументов.Количество() > 0 Тогда
			ИмяФайлаДокумента = СписокДокументов[0].Значение;
		КонецЕсли;
	КонецЕсли;

	ПрорисоватьТранспортноеСообщение();
	ПрорисоватьДокумент();

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

&НаСервере
Процедура ЗаполнитьСписокДокументовСообщения(ТранспортноеСообщение)

	Если СписокДокументов.Количество() > 0 Тогда
		СписокДокументов.Очистить();
	КонецЕсли;
	
	ТипыДИВ = Новый Массив;
	
	// ФНС 141
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ЗапросИОН);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.НеформализованныйДокумент);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ОписаниеНеформализованногоДокумента);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ОтветНаЗапросИОН);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПодтверждениеОбОтправке);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.Протокол2НДФЛ);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПротоколВходногоКонтроля);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.Реестр2НДФЛ);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ТекстовоеСообщениеНеформализованногоДокумента);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.УведомлениеОбУточненииНБО);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ФайлОтчетности);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.Форма2НДФЛ);
	
	// ПФР 190
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ФайлОписанияСведенийПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.СведенияПриложениеПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПротоколПриложениеПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПротоколПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПодтверждениеПолученияОтчетностиПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ФайлОтчетностиПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ФайлОписанияЗапросаПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ОтветНаЗапросПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ОтветПриложениеНаЗапросПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПодтверждениеПолученияЗапросПФР);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ЗапросИОС);
	
	// ФСГС 313
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.УведомлениеОПриемеВОбработкуОтчетаФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.УведомлениеОНесоответствииФорматуОтчетаФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.УведомлениеОбУточненииОтчетаФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.УведомлениеОбОтказеОтчетаФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ИзвещениеОПолученииДокументаФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПодтверждениеОператораФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ФайлОтчетностиФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПисьмоФСГС);
	ТипыДИВ.Добавить(Перечисления.ТипыСодержимогоТранспортногоКонтейнера.ПриложениеПисьмаФСГС);

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

	Если ТипыСообщенийСДИВамиВОсновании = Неопределено Тогда 
		ОпределитьТипыСообщений("ТипыСообщенийСДИВамиВОсновании");
	КонецЕсли;

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

		Если ТипыСообщенийСДИВамиВПроизвольномСообщении = Неопределено Тогда 
			ОпределитьТипыСообщений("ТипыСообщенийСДИВамиВПроизвольномСообщении");
		КонецЕсли;

		ТипСообщенияОснования = ТипыСообщенийСДИВамиВПроизвольномСообщении[ТранспортноеСообщение.Тип];
		Если ЗначениеЗаполнено(ТипСообщенияОснования) Тогда
			Запрос.Текст = Запрос.Текст + "
		                      |
		                      |ОБЪЕДИНИТЬ ВСЕ
		                      |
		                      |ВЫБРАТЬ
		                      |	СодержимоеТранспортныхКонтейнеров.Тип,
		                      |	СодержимоеТранспортныхКонтейнеров.ИмяФайла,
		                      |	2
		                      |ИЗ
		                      |	РегистрСведений.СодержимоеТранспортныхКонтейнеров КАК СодержимоеТранспортныхКонтейнеров
		                      |ГДЕ
		                      |	СодержимоеТранспортныхКонтейнеров.ТранспортноеСообщение.ЦиклОбмена = &ЦиклОбмена
		                      |	И СодержимоеТранспортныхКонтейнеров.ТранспортноеСообщение.Тип В(&ТипОснования)
		                      |	И СодержимоеТранспортныхКонтейнеров.Тип В(&Тип)";
			Запрос.УстановитьПараметр("ЦиклОбмена", ТранспортноеСообщение.ЦиклОбмена);
			Запрос.УстановитьПараметр("ТипОснования", ТипСообщенияОснования);
		КонецЕсли;
	КонецЕсли;
	
	// выполняем запрос
	ТаблицаДИВ = Запрос.Выполнить().Выгрузить();
	
	// находим ДИВы, полученные из сообщения-основания
	ДИВИзОснований = ТаблицаДИВ.НайтиСтроки(Новый Структура("Источник", 2));
	
	// если ДИВы аналогичного типа и с аналогичным именем есть в сообщении, введенном на основании, то удалим из таблицы ДИВ сообщения-основания
	Для Каждого СтрДИВ Из ДИВИзОснований Цикл
		СледуетУдалить = (ТаблицаДИВ.НайтиСтроки(Новый Структура("Тип, ИмяФайла, Источник", СтрДИВ.Тип, СтрДИВ.ИмяФайла, 1)).Количество() > 0);
		Если СледуетУдалить Тогда
			ТаблицаДИВ.Удалить(СтрДИВ);
		КонецЕсли;
	КонецЦикла;
	
	// сортируем по именам таблицу ДИВов перед формированием результата
	ТаблицаДИВ.Сортировать("ИмяФайла");
	
	// формируем список-результат
	Для Каждого Стр Из ТаблицаДИВ Цикл
		СписокДокументов.Добавить(Стр.ИмяФайла, "" + Стр.Тип + ": " + Стр.ИмяФайла);
	КонецЦикла;


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

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

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

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

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

&НаСервереБезКонтекста
Функция ПолучитьОтправителя(ТранспортноеСообщение)
	Возврат ТранспортноеСообщение.Отправитель;
КонецФункции

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

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

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

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

&НаСервере
Процедура УдалитьПодписиНаСервере(ТекущаяСтрока)
	
	ПодписиТекущаяСтрока = ПодписиПредставление.НайтиПоИдентификатору(ТекущаяСтрока);
	ТранспортноеСообщениеПодписи = ПодписиТекущаяСтрока.ТранспортноеСообщение;
	ИмяФайлаПодписи = ПодписиТекущаяСтрока.ИмяФайла;
	
	МенеджерЗаписи = РегистрыСведений.СодержимоеТранспортныхКонтейнеров.СоздатьМенеджерЗаписи();
	ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ПодписиТекущаяСтрока);
	МенеджерЗаписи.Удалить();
	
	МассивФайлов = ОбщегоНазначенияЭДКО.ПрикрепленныеФайлыКОбъектуИзСправочника(
		ТранспортноеСообщениеПодписи,
		"ТранспортноеСообщениеПрисоединенныеФайлы",
		ИмяФайлаПодписи);
	Если МассивФайлов.Количество() > 0 Тогда
		ПрисоединенныйФайлОбъект = МассивФайлов[0].ПолучитьОбъект();
		ПрисоединенныйФайлОбъект.УстановитьПометкуУдаления(Истина);
	КонецЕсли;
	
КонецПроцедуры

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

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

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

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

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

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

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

&НаСервере
Функция ЗаписатьРезультатПроверкиВРегистр(ТекущаяСтрока, РезультатПроверки)
	
	ПодписиТекущаяСтрока = ПодписиПредставление.НайтиПоИдентификатору(ТекущаяСтрока);
	
	МенеджерЗаписи = РегистрыСведений.СодержимоеТранспортныхКонтейнеров.СоздатьМенеджерЗаписи();
	ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ПодписиТекущаяСтрока);
	МенеджерЗаписи.Прочитать();
	
	МенеджерЗаписи.ЭЦПСтатусПроверки = ?(РезультатПроверки, Перечисления.СтатусыПроверкиЭЦП.Валидна, Перечисления.СтатусыПроверкиЭЦП.НеВалидна);
	
	Попытка
		МенеджерЗаписи.Записать(Истина);
		Возврат Истина;
	Исключение
		Возврат Строка( "Не удалось записать результат проверки:
		|
		|" + ИнформацияОбОшибке().Описание);
	КонецПопытки;
	
КонецФункции

&НаКлиенте
Процедура КомандаПодписиПроверитьПослеПроверки(Результат, ВходящийКонтекст) Экспорт

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

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

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

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

Связанные материалы