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

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

#Область ДляВызоваИзДругихПодсистем

// СтандартныеПодсистемы.ВариантыОтчетов

// Задать настройки формы отчета.
//
// Параметры:
//   Форма - ФормаКлиентскогоПриложения
//         - Неопределено
//   КлючВарианта - Строка
//                - Неопределено
//   Настройки - см. ОтчетыКлиентСервер.НастройкиОтчетаПоУмолчанию
//
Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт

	Настройки.ФормироватьСразу = Истина;
	Настройки.Печать.ПолеСверху = 5;
	Настройки.Печать.ПолеСлева = 5;
	Настройки.Печать.ПолеСнизу = 5;
	Настройки.Печать.ПолеСправа = 5;
	
КонецПроцедуры

// Конец СтандартныеПодсистемы.ВариантыОтчетов

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

#КонецОбласти
	
#Область ОбработчикиСобытий

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

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

Функция ИнформацияОСертификатах()

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

	Запрос = Новый Запрос;
	
	Запрос.Текст = 
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	СертификатыКлючейЭлектроннойПодписиИШифрованияПользователи.Ссылка КАК Сертификат
	|ПОМЕСТИТЬ СертификатыПользователя
	|ИЗ
	|	Справочник.СертификатыКлючейЭлектроннойПодписиИШифрования.Пользователи КАК СертификатыКлючейЭлектроннойПодписиИШифрованияПользователи
	|ГДЕ
	|	&УсловиеПоПользователю1
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.Ссылка КАК Сертификат,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.ДанныеСертификата КАК ДанныеСертификата,
	|	ВЫБОР
	|		КОГДА СертификатыКлючейЭлектроннойПодписиИШифрования.ДействителенДо МЕЖДУ &ТекущаяДата И &СрокДействияИстекает
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК СрокДействияИстекает,
	|	ВЫБОР
	|		КОГДА НЕ СертификатыПользователя.Сертификат ЕСТЬ NULL
	|				ИЛИ СертификатыКлючейЭлектроннойПодписиИШифрования.Пользователь <> ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК Используется,
	|	ВЫБОР
	|		КОГДА СертификатыКлючейЭлектроннойПодписиИШифрования.КемВыдан ПОДОБНО ""%Тестовый%""
	|				ИЛИ СертификатыКлючейЭлектроннойПодписиИШифрования.КемВыдан ПОДОБНО ""%test%""
	|				ИЛИ СертификатыКлючейЭлектроннойПодписиИШифрования.Наименование ПОДОБНО ""%_Тест%""
	|				ИЛИ СертификатыКлючейЭлектроннойПодписиИШифрования.Наименование ПОДОБНО ""%_Test%""
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК Тестовый,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.Фирма КАК Фирма,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.КемВыдан КАК КемВыдан,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.Организация КАК Организация,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.ФизическоеЛицо КАК ФизическоеЛицо,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.Отозван КАК Отозван,
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.ДействителенДо КАК ДействителенДо
	|ИЗ
	|	Справочник.СертификатыКлючейЭлектроннойПодписиИШифрования КАК СертификатыКлючейЭлектроннойПодписиИШифрования
	|		ЛЕВОЕ СОЕДИНЕНИЕ СертификатыПользователя КАК СертификатыПользователя
	|		ПО СертификатыКлючейЭлектроннойПодписиИШифрования.Ссылка = СертификатыПользователя.Сертификат
	|ГДЕ
	|	СертификатыКлючейЭлектроннойПодписиИШифрования.ДействителенДо > &ДействителенПосле
	|	И &УсловиеПоПользователю2
	|	И НЕ СертификатыКлючейЭлектроннойПодписиИШифрования.ПометкаУдаления
	|
	|УПОРЯДОЧИТЬ ПО
	|	ДействителенДо УБЫВ";
	
	Если ЗначениеЗаполнено(ПараметрыЗапроса.Пользователь) Тогда
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоПользователю1", "СертификатыКлючейЭлектроннойПодписиИШифрованияПользователи.Пользователь = &Пользователь");
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоПользователю2", "(СертификатыКлючейЭлектроннойПодписиИШифрования.Пользователь = &Пользователь
	|			ИЛИ СертификатыКлючейЭлектроннойПодписиИШифрования.Добавил = &Пользователь
	|			ИЛИ НЕ СертификатыПользователя.Сертификат ЕСТЬ NULL)");
		Запрос.УстановитьПараметр("Пользователь", ПараметрыЗапроса.Пользователь);
	Иначе
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоПользователю1", "ИСТИНА");
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеПоПользователю2", "ИСТИНА");
	КонецЕсли;
	
	Запрос.УстановитьПараметр("ДействителенПосле", ПараметрыЗапроса.ДействителенПосле);
	Запрос.УстановитьПараметр("СрокДействияИстекает", ТекущаяДатаСеанса() + 30*24*60*60);
	Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
	
	ИнформацияОСертификатах = Запрос.Выполнить().Выгрузить();
	ИнформацияОСертификатах.Колонки.Добавить("ЭтоКвалифицированныйСертификат", Новый ОписаниеТипов("Булево"));
	ИнформацияОСертификатах.Колонки.Добавить("Квалифицированный", Новый ОписаниеТипов("Булево"));
	ИнформацияОСертификатах.Колонки.Добавить("ТребуетсяМЧД", Новый ОписаниеТипов("Булево"));
	ИнформацияОСертификатах.Колонки.Добавить("ТребуетсяВыпуститьСертификатФизическогоЛица", Новый ОписаниеТипов("Булево"));
	ИнформацияОСертификатах.Колонки.Добавить("Предупреждение", Новый ОписаниеТипов("Строка"));
	ИнформацияОСертификатах.Колонки.Добавить("ИННЮЛ", Новый ОписаниеТипов("Строка"));
	ИнформацияОСертификатах.Колонки.Добавить("ИНН", Новый ОписаниеТипов("Строка"));
	ИнформацияОСертификатах.Колонки.Добавить("ОГРН", Новый ОписаниеТипов("Строка"));
	ИнформацияОСертификатах.Колонки.Добавить("КомуВыдан", Новый ОписаниеТипов("Строка"));
	ИнформацияОСертификатах.Колонки.Добавить("ДатаОкончания", Новый ОписаниеТипов("Дата"));
	ИнформацияОСертификатах.Колонки.Добавить("ИспользуетсяЗакрытыйКлюч", Новый ОписаниеТипов("Булево"));
	ИнформацияОСертификатах.Колонки.Добавить("ДатаОкончанияЗакрытогоКлюча", Новый ОписаниеТипов("Дата"));
	ИнформацияОСертификатах.Колонки.Добавить("СертификатФизическогоЛица", Новый ОписаниеТипов("Булево"));
	ИнформацияОСертификатах.Колонки.Добавить("НовыйСертификат", Новый ОписаниеТипов("СправочникСсылка.СертификатыКлючейЭлектроннойПодписиИШифрования"));
	ИнформацияОСертификатах.Колонки.Добавить("ОрганизацияУказаннаяВДанныхСертификата", Новый ОписаниеТипов("Строка"));
	ИнформацияОСертификатах.Колонки.Добавить("МашиночитаемаяДоверенность");
	
	Для Каждого Строка Из ИнформацияОСертификатах Цикл
		
		ДанныеСертификата = Строка.ДанныеСертификата.Получить();
		Если Не ЗначениеЗаполнено(ДанныеСертификата) Тогда
			Строка.Предупреждение = НСтр("ru='Не заполнены данные сертификата в справочнике'");
			Продолжить;
		КонецЕсли;
		Попытка
			СертификатКриптографии = Новый СертификатКриптографии(ДанныеСертификата);
			СвойстваСертификата = ЭлектроннаяПодписьСлужебныйКлиентСервер.СвойстваСертификата(
				СертификатКриптографии, ЭлектроннаяПодписьСлужебный.РазницаСУниверсальнымВременем(), ДанныеСертификата);
		Исключение
			Строка.Предупреждение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru='Не удалось прочитать данные сертификата: %1'"), ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
			Продолжить;
		КонецПопытки;
		
		Строка.ДатаОкончания = СвойстваСертификата.ДатаОкончания;
		Строка.ДатаОкончанияЗакрытогоКлюча = СвойстваСертификата.ДатаОкончанияЗакрытогоКлюча;
		
		СвойстваСубъектаСертификата = ЭлектроннаяПодписьСлужебныйКлиентСервер.СвойстваСубъектаСертификата(СертификатКриптографии);
		Если СвойстваСубъектаСертификата.Свойство("ИННЮЛ") Тогда
			Строка.ИННЮЛ = СвойстваСубъектаСертификата.ИННЮЛ;
		КонецЕсли;
		Если СвойстваСубъектаСертификата.Свойство("ИНН") Тогда
			Строка.ИНН = СвойстваСубъектаСертификата.ИНН;
		КонецЕсли;
		Если СвойстваСубъектаСертификата.Свойство("ОГРН") Тогда
			Строка.ОГРН = СвойстваСубъектаСертификата.ОГРН;
		ИначеЕсли СвойстваСубъектаСертификата.Свойство("ОГРНИП") Тогда
			Строка.ОГРН = СвойстваСубъектаСертификата.ОГРНИП;
		КонецЕсли;
		Строка.ОрганизацияУказаннаяВДанныхСертификата = СвойстваСубъектаСертификата.Организация;
		Строка.КомуВыдан = СвойстваСертификата.КомуВыдан;
		
		Если Не ЭтоСертификатИздателя(Строка.ОГРН) Тогда
			Результат = ЭлектроннаяПодписьСлужебный.РезультатПроверкиУдостоверяющегоЦентраСертификата(СертификатКриптографии, ТекущаяДатаСеанса(), Ложь, СвойстваСертификата);
			
			Если ЗначениеЗаполнено(Результат.Предупреждение.ТекстОшибки) Тогда
				Строка.Предупреждение = Результат.Предупреждение.ТекстОшибки;
			ИначеЕсли ЗначениеЗаполнено(Результат.Предупреждение.ДополнительныеСведения) Тогда
				Строка.Предупреждение = Результат.Предупреждение.ДополнительныеСведения;
			КонецЕсли;
			
			Строка.Квалифицированный = Не Строка.Тестовый И Результат.ЭтоКвалифицированныйСертификат;
			Строка.ТребуетсяВыпуститьСертификатФизическогоЛица = Результат.ЭтоКвалифицированныйСертификат 
				И Не Результат.Государственный И ЗначениеЗаполнено(Строка.Фирма);
			
			Строка.СертификатФизическогоЛица = ЗначениеЗаполнено(Строка.ИНН) И Не ЗначениеЗаполнено(Строка.ИННЮЛ)
				И Не ЗначениеЗаполнено(Строка.ОГРН);
			
			Строка.ТребуетсяМЧД = Результат.ЭтоКвалифицированныйСертификат И Строка.СертификатФизическогоЛица 
				И (Не Результат.Государственный Или ЭтоСертификатКазначейства(СертификатКриптографии));
			
			// СтандартныеПодсистемы.МашиночитаемыеДоверенности
			Если ПараметрыЗапроса.НайтиМЧД И Результат.ЭтоКвалифицированныйСертификат Тогда
					
				ОтборДляДоверенностейПоСертификату = МодульМашиночитаемыеДоверенностиФНС.ОтборДляДоверенностейПоСертификату(
					СертификатКриптографии, "Представитель");
				ВыбранныеПоля = Новый Массив;
				ВыбранныеПоля.Добавить("МашиночитаемаяДоверенность");
				Доверенности = МодульМашиночитаемыеДоверенностиФНС.ДоверенностиСОтбором(ОтборДляДоверенностейПоСертификату, 
					ВыбранныеПоля);
				
				Если Доверенности.Количество() > 0 Тогда
					Строка.МЧД = Доверенности[0].МашиночитаемаяДоверенность;
				КонецЕсли;
			КонецЕсли;
			// Конец СтандартныеПодсистемы.МашиночитаемыеДоверенности
			
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПараметрыЗапроса.НайтиПеревыпущенныеСертификаты Тогда
		
		ИнформацияОСертификатах.Индексы.Добавить("ИНН, Квалифицированный");
		
		Для Каждого Строка Из ИнформацияОСертификатах Цикл
			
			Если Не ЗначениеЗаполнено(Строка.ИНН) И Не ЗначениеЗаполнено(Строка.ИННЮЛ) Тогда
				Продолжить;
			КонецЕсли;
			
			Отбор = Новый Структура;
			Если ЗначениеЗаполнено(Строка.ИНН) Тогда
				Отбор.Вставить("ИНН", Строка.ИНН);
			Иначе
				Отбор.Вставить("ИННЮЛ", Строка.ИННЮЛ);
			КонецЕсли;

			Если Строка.Квалифицированный Тогда
				Отбор.Вставить("Квалифицированный", Истина);
			ИначеЕсли Строка.Тестовый Тогда
				Отбор.Вставить("Тестовый", Истина);
			Иначе
				Отбор.Вставить("ЭтоКвалифицированныйСертификат", Строка.ЭтоКвалифицированныйСертификат);
			КонецЕсли;
			
			Отбор.Вставить("Отозван", Ложь);

			Найдено = ИнформацияОСертификатах.НайтиСтроки(Отбор);
			Если Найдено.Количество() > 0 Тогда
				Если Найдено[0].ДействителенДо > Строка.ДействителенДо Тогда
					Строка.НовыйСертификат = Найдено[0].Сертификат;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	Возврат ИнформацияОСертификатах;
	
КонецФункции

Функция ЭтоСертификатИздателя(ОГРН)
	
	Если Не ЗначениеЗаполнено(ОГРН) Тогда
		Возврат Ложь;
	КонецЕсли;
	Если ОГРН = "1047707030513" 
		Или ОГРН = "1047797019830"
		Или ОГРН = "1047702026701"
		Или ОГРН = "1037700013020" Тогда
		Возврат Истина;
	КонецЕсли;
	Возврат Ложь;
	
КонецФункции

Функция ЭтоСертификатКазначейства(СертификатКриптографии)
	
	СвойстваИздателяСертификата = ЭлектроннаяПодписьСлужебныйКлиентСервер.СвойстваИздателяСертификата(СертификатКриптографии);

	Если СвойстваИздателяСертификата.Свойство("ОГРН") И СвойстваИздателяСертификата.ОГРН = "1047797019830" Тогда
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

#КонецОбласти
	
#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли