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

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

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

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

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

#Область ПроцедурыИФункцииДляВстраиванияПодсистемыВФормыОбъектовКонфигурации

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

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

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

// Возвращает Истина если используется уничтожение персональных данных, иначе Ложь.
// 
// Возвращаемое значение:
//  Булево
//
Функция ИспользоватьУничтожениеПерсональныхДанныхСубъектов() Экспорт
	
	Возврат ПолучитьФункциональнуюОпцию("ИспользоватьСкрытиеПерсональныхДанныхСубъектов");
	
КонецФункции

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

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

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

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

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

// Регистрирует всех субъектов с неуничтоженными персональными данными для расчета сроков хранения персональных данных.
Процедура ЗаполнитьСубъектыДляРасчетаСроковХраненияПерсональныхДанных() Экспорт

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

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

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

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

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

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

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

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

#Область ОбменДанными

// Устарела.
//
// Параметры:
//  Объект - ПланОбменаОбъект - узел плана обмена, для которого выполнялось получение данных.
//
Процедура ПослеЗагрузкиДанных(Объект) Экспорт
	
КонецПроцедуры

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

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

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

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

#Область ОбновлениеИнформационнойБазы

// См. ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковОбновления.
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
	
	Если Не ОбщегоНазначения.РазделениеВключено() Тогда
		Обработчик = Обработчики.Добавить();
		Обработчик.Версия = "3.0.1.53";
		Обработчик.Процедура = "ЗащитаПерсональныхДанных.ПеренестиЗащищаемыеОбластиПерсональныхДанных";
		Обработчик.РежимВыполнения = "Отложенно";
		Обработчик.ПроцедураЗаполненияДанныхОбновления =
			"ЗащитаПерсональныхДанных.ЗаполнитьДанныеОбновленияОбластейПерсональныхДанных";
		Обработчик.ЗапускатьИВПодчиненномУзлеРИБСФильтрами = Истина;
		Обработчик.ЧитаемыеОбъекты = "РегистрСведений.УдалитьОбластиПерсональныхДанных";
		Обработчик.ИзменяемыеОбъекты = "РегистрСведений.ОбластиПерсональныхДанных";
		Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
		Обработчик.Идентификатор = Новый УникальныйИдентификатор("7211dd8a-028a-49d9-a23a-d2738bf0995f");
		Обработчик.Комментарий = НСтр("ru = 'Перенос сведений о защищаемых областях персональных данных.'");
	КонецЕсли;
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "3.1.8.286";
	Обработчик.Процедура = "ЗащитаПерсональныхДанных.ЗаполнитьРегистрыДляУничтоженияПерсональныхДанных";
	Обработчик.РежимВыполнения = "Отложенно";
	Обработчик.ПроцедураЗаполненияДанныхОбновления =
		"ЗащитаПерсональныхДанных.ЗаполнитьДанныеОбновленияРегистровДляУничтоженияПерсональныхДанных";
	Обработчик.ЧитаемыеОбъекты = "РегистрСведений.СубъектыДляСкрытияПерсональныхДанных";
	Обработчик.ИзменяемыеОбъекты =
		"РегистрСведений.СубъектыДляРасчетаСроковХранения,РегистрСведений.УничтоженныеПерсональныеДанные";
	Обработчик.Идентификатор = Новый УникальныйИдентификатор("119a85d2-d77c-4b25-b746-60f6199c823e");
	Обработчик.Комментарий = НСтр("ru = 'Заполнение данных регистров для уничтожения персональных данных.'");
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "3.1.9.17";
	Обработчик.Процедура =
		"ЗащитаПерсональныхДанных.УстановитьРасписаниеРегламентногоЗаданияРасчетСроковХраненияПерсональныхДанных";
	Обработчик.РежимВыполнения = "Отложенно";
	Обработчик.ПроцедураЗаполненияДанныхОбновления =
		"ЗащитаПерсональныхДанных.ЗаполнитьДанныеОбновленияРасписанияРегламентногоЗаданияРасчетСроковХраненияПерсональныхДанных";
	Обработчик.ЧитаемыеОбъекты = "Константа.ИспользоватьСкрытиеПерсональныхДанныхСубъектов";
	Обработчик.ИзменяемыеОбъекты = "Константа.ИспользоватьСкрытиеПерсональныхДанныхСубъектов";
	Обработчик.Идентификатор = Новый УникальныйИдентификатор("e39f4562-8744-451f-be0a-0409e6667a9e");
	Обработчик.Комментарий =
		НСтр("ru = 'Установка расписания регламентного задания расчета сроков хранения персональных данных.'");
	
КонецПроцедуры

Процедура ЗаполнитьДанныеОбновленияОбластейПерсональныхДанных(ПараметрыОбновления) Экспорт

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

Процедура ЗаполнитьДанныеОбновленияРегистровДляУничтоженияПерсональныхДанных(ПараметрыОбновления) Экспорт

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

Процедура ЗаполнитьДанныеОбновленияРасписанияРегламентногоЗаданияРасчетСроковХраненияПерсональныхДанных(
	ПараметрыОбновления) Экспорт

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

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

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

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

	ПараметрыОбновления.ОбработкаЗавершена = Истина;
	
КонецПроцедуры

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

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

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

// Параметры:
//   СписокМакетов - Массив - макеты.
//
Процедура ПриПодготовкеСпискаМакетовВФорматеОфисныхДокументовФормируемыхНаСервере(СписокМакетов) Экспорт
	СписокМакетов.Добавить("Документ.СогласиеНаОбработкуПерсональныхДанных.ПФ_DOC_СогласиеНаОбработкуПерсональныхДанных_ru");
КонецПроцедуры

#Область ОбработчикиСобытийПодсистемКонфигурации

// См. ПользователиПереопределяемый.ПриОпределенииНастроекРегистрацииСобытийДоступаКДанным
Процедура ПриОпределенииНастроекРегистрацииСобытийДоступаКДанным(Настройки) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ОбластиПерсональныхДанных.ИмяОбласти КАК ИмяОбласти
	|ИЗ
	|	РегистрСведений.ОбластиПерсональныхДанных КАК ОбластиПерсональныхДанных
	|ГДЕ
	|	ОбластиПерсональныхДанных.ИспользованиеСобытийЖурналаРегистрации";
	КатегорииДанных = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ИмяОбласти");
	
	// Таблица сведений о персональных данных.
	ТаблицаСведений = СведенияОПерсональныхДанных();
	
	Для Каждого СтрокаСведений Из ТаблицаСведений Цикл
		Если КатегорииДанных.Найти(СтрокаСведений.ОбластьДанных) = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		// Составление описания использования события.
		ПоляРегистрации = СтрРазделить(СтрокаСведений.ПоляРегистрации, ",");
		Для Индекс = 0 По ПоляРегистрации.ВГраница() Цикл
			// Если требуется составить массив полей.
			Если СтрНайти(ПоляРегистрации[Индекс], "|") > 0 Тогда
				ПоляРегистрации[Индекс] = СтрРазделить(ПоляРегистрации[Индекс], "|");
			КонецЕсли;
		КонецЦикла;
		Настройка = Новый ОписаниеИспользованияСобытияДоступЖурналаРегистрации(СтрокаСведений.Объект);
		Настройка.ПоляДоступа = СтрРазделить(СтрокаСведений.ПоляДоступа, ",");
		Настройка.ПоляРегистрации = ПоляРегистрации;
		Настройки.Добавить(Настройка);
	КонецЦикла;
	
КонецПроцедуры

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

// См. ДатыЗапретаИзмененияПереопределяемый.ПриЗаполненииРазделовДатЗапретаИзменения.
Процедура ПриЗаполненииРазделовДатЗапретаИзменения(Разделы) Экспорт
	
	Раздел = Разделы.Добавить();
	Раздел.Имя  = "ОбработкаПерсональныхДанных";
	Раздел.Идентификатор = Новый УникальныйИдентификатор("527c98a3-3bfc-4bf9-8ec7-0247fdfa7a29");
	Раздел.Представление = НСтр("ru = 'Обработка персональных данных'");
	
КонецПроцедуры

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

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

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

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

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

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

// См. ОчередьЗаданийПереопределяемый.ПриПолученииСпискаШаблонов.
Процедура ПриПолученииСпискаШаблонов(ШаблоныЗаданий) Экспорт
	
	ШаблоныЗаданий.Добавить(Метаданные.РегламентныеЗадания.РасчетСроковХраненияПерсональныхДанных.Имя);
	
КонецПроцедуры

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

// См. УправлениеСвойствамиПереопределяемый.ПриПолученииПредопределенныхНаборовСвойств.
Процедура ПриПолученииПредопределенныхНаборовСвойств(Наборы) Экспорт
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_СогласиеНаОбработкуПерсональныхДанных";
	Набор.Идентификатор = Новый УникальныйИдентификатор("e7e9e299-1adf-442a-929f-c04f042e631e");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_ОтзывСогласияНаОбработкуПерсональныхДанных";
	Набор.Идентификатор = Новый УникальныйИдентификатор("bb5807bf-0b0e-48a3-8853-3c346da51798");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_АктОбУничтоженииПерсональныхДанных";
	Набор.Идентификатор = Новый УникальныйИдентификатор("66b2cf48-5ac3-4145-a115-af7de2a10f59");
	
КонецПроцедуры

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

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

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

#Область ОбменДанными

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

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

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

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

#Область ОбработчикиРегламентныхЗаданий

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

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

#Область ОбработчикиПодписокНаСобытия

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

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

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

	Источник.ДополнительныеСвойства.Вставить("ЭтоНовый", Источник.ЭтоНовый());
	
КонецПроцедуры

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

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

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

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

#Область СрокиХранения

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

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

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

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

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

// Выполняет расчет сроков хранения персональных данных субъектов.
// 
// Параметры:
//  ДанныеСубъектов - см. РегистрыСведений.СубъектыДляРасчетаСроковХранения.СубъектыДляРасчетаСроковХранения
//
Процедура ОбновитьСрокиХраненияПерсональныхДанныхСубъектов(ДанныеСубъектов)
	
	Если ДанныеСубъектов.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	НаборЗаписейСубъектыДляРасчета = РегистрыСведений.СубъектыДляРасчетаСроковХранения.СоздатьНаборЗаписей();
	НаборЗаписейСрокиХранения = РегистрыСведений.СрокиХраненияПерсональныхДанных.СоздатьНаборЗаписей();
	
	СрокиХранения = РассчитатьСрокиХраненияПерсональныхДанныхСубъектов(ДанныеСубъектов);

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

// Обновляет срок хранения персональных данных субъекта.
// 
// Параметры:
//  Субъект - ОпределяемыйТип.СубъектПерсональныхДанных
//
Процедура ОбновитьСрокХраненияПерсональныхДанныхСубъекта(Субъект) Экспорт
	
	ДанныеСубъектов = НоваяТаблицаДляРасчетаСроковХранения();
	НоваяСтрока = ДанныеСубъектов.Добавить();
	НоваяСтрока.Субъект = Субъект;
	
	ОбновитьСрокиХраненияПерсональныхДанныхСубъектов(ДанныеСубъектов);
	
КонецПроцедуры

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// См. ЗащитаПерсональныхДанныхСлужебный.ПредставлениеКатегорииПерсональныхДанных
Функция ПредставлениеКатегорииПерсональныхДанных(ИмяКатегории) Экспорт

	Возврат ЗащитаПерсональныхДанныхПовтИсп.ПредставлениеКатегорииПерсональныхДанных(ИмяКатегории);
	
КонецФункции

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

// См. ЗащитаПерсональныхДанныхСлужебный.МетаданныеПоТипамСубъекта
Функция МетаданныеПоТипамСубъекта() Экспорт
	
	Возврат ЗащитаПерсональныхДанныхПовтИсп.МетаданныеПоТипамСубъекта();
	
КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектов
Функция ТипыСубъектов() Экспорт
	
	Возврат ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектов();
	
КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектовДоступныхПоФункциональнымОпциям
Функция ТипыСубъектовДоступныхПоФункциональнымОпциям() Экспорт
	
	Возврат ЗащитаПерсональныхДанныхПовтИсп.ТипыСубъектовДоступныхПоФункциональнымОпциям();
	
КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.СубъектДоступенПоФункциональнымОпциям
Функция СубъектДоступенПоФункциональнымОпциям(ИмяОбъекта) Экспорт
	
	Возврат ЗащитаПерсональныхДанныхПовтИсп.СубъектДоступенПоФункциональнымОпциям(ИмяОбъекта);
	
КонецФункции

// См. ЗащитаПерсональныхДанныхПовтИсп.ИменаМетаданныхПоТипамСубъекта
Функция ИменаМетаданныхПоТипамСубъекта() Экспорт
	
	Возврат ЗащитаПерсональныхДанныхПовтИсп.ИменаМетаданныхПоТипамСубъекта();
	
КонецФункции

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

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

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

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

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

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

	Результат = Новый Структура;
	Результат.Вставить("СобытияЖурнала", СобытияЖурнала);
	ПоместитьВоВременноеХранилище(Результат, АдресХранилища);

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

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

// Возвращаемое значение:
//  СписокЗначений из Строка
//
Функция КонтролируемыеСобытияДоступа() Экспорт

	СписокСобытий = Новый СписокЗначений;
	СписокСобытий.Добавить("_$Access$_.Access", НСтр("ru = 'Доступ. Доступ'"));
	СписокСобытий.Добавить("_$Access$_.AccessDenied", НСтр("ru = 'Доступ. Отказ в доступе'"));
	
	Возврат СписокСобытий;
	
КонецФункции

// Возвращаемое значение:
//  СписокЗначений из Строка
//
Функция КонтролируемыеСобытияАутентификации() Экспорт

	СписокСобытий = Новый СписокЗначений;
	СписокСобытий.Добавить("_$Session$_.Authentication", НСтр("ru = 'Сеанс. Аутентификация'"));
	СписокСобытий.Добавить("_$Session$_.AuthenticationError", НСтр("ru = 'Сеанс. Ошибка аутентификации'"));
	СписокСобытий.Добавить("_$Session$_.Start", НСтр("ru = 'Сеанс. Начало'"));
	СписокСобытий.Добавить("_$Session$_.Finish", НСтр("ru = 'Сеанс. Завершение'"));
	
	Возврат СписокСобытий;
	
КонецФункции

// Возвращаемое значение:
//  Массив из Строка
//
Функция КонтролируемыеПриложенияДоступа() Экспорт
	
	СписокПриложений = Новый Массив;
	СписокПриложений.Добавить("1CV8");			// идентификатор приложения 1С:Предприятие в режиме запуска "Толстый клиент"
	СписокПриложений.Добавить("1CV8C");			// идентификатор приложения 1С:Предприятие в режиме запуска "Тонкий клиент"
	СписокПриложений.Добавить("WebClient");		// идентификатор приложения 1С:Предприятие в режиме запуска "Веб-клиент"
	СписокПриложений.Добавить("BackgroundJob");	// идентификатор фонового задания 

	Возврат СписокПриложений;
	
КонецФункции

// Возвращаемое значение:
//  Массив из Строка
//
Функция КонтролируемыеПриложенияАутентификации()
	
	СписокПриложений = КонтролируемыеПриложенияДоступа();
	СписокПриложений.Удалить(СписокПриложений.Найти("BackgroundJob"));

	Возврат СписокПриложений;
	
КонецФункции

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

// См. ЗащитаПерсональныхДанныхСлужебный.КатегорииПерсональныхДанных
Функция КатегорииПерсональныхДанных() Экспорт
	
	Возврат ЗащитаПерсональныхДанныхПовтИсп.КатегорииПерсональныхДанных();
	
КонецФункции

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

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

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

// Возвращаемое значение:
//  Структура:
//   * ДатаПолучения - Дата
//   * СрокДействия - Дата
//   * ДокументОснование - ДокументСсылка.СогласиеНаОбработкуПерсональныхДанных
//
Функция ОписаниеСогласия()
	
	Описание = Новый Структура;
	
	Описание.Вставить("ДатаПолучения", Дата(1, 1, 1));
	Описание.Вставить("СрокДействия", Дата(1, 1, 1));
	Описание.Вставить("ДокументОснование", Документы.СогласиеНаОбработкуПерсональныхДанных.ПустаяСсылка());
	
	Возврат Описание;
	
КонецФункции

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

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

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

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

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

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

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

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

// Параметры:
//  ТекстЗапроса - Строка
// 
// Возвращаемое значение:
//  Массив из ОпределяемыйТип.СубъектПерсональныхДанных
//
Функция СубъектыПоЗапросу(ТекстЗапроса)
	
	МетаданныеСубъектов = МетаданныеПоТипамСубъекта();
	
	Субъекты = Новый Массив;
	
	Для Каждого МетаданныеСубъекта Из МетаданныеСубъектов Цикл
		Запрос = Новый Запрос;
		Запрос.Текст = ТекстЗапросаДляТипаСубъекта(МетаданныеСубъекта.Значение, ТекстЗапроса);
		//@skip-check query-in-loop - запрос в цикле по разным типам субъектов, проектное решение.
		РезультатЗапроса = Запрос.Выполнить();
		НовыеСубъекты = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
		ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Субъекты, НовыеСубъекты);
	КонецЦикла;
	
	Возврат Субъекты;
	
КонецФункции

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

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

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

// Параметры:
//  УничтоженныеДанные - ТаблицаЗначений:
//   * Субъект - ОпределяемыйТип.СубъектПерсональныхДанных
//   * ДатаСкрытия - Дата
//
Процедура ЗаполнитьРегистрУничтоженныхДанных(УничтоженныеДанные)
	
	НаборЗаписей = РегистрыСведений.УничтоженныеПерсональныеДанные.СоздатьНаборЗаписей();
	
	Для Каждого СтрокаТаблицы Из УничтоженныеДанные Цикл
		
		НаборЗаписей.Отбор.Субъект.Установить(СтрокаТаблицы.Субъект);
		
		НоваяЗапись = НаборЗаписей.Добавить();
		НоваяЗапись.Субъект = СтрокаТаблицы.Субъект;
		НоваяЗапись.ДатаУничтожения = СтрокаТаблицы.ДатаСкрытия;
		
		ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей);
		
		НаборЗаписей.Очистить();
		
	КонецЦикла;
	
КонецПроцедуры

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

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

#Область ИзменениеНастроекСкрытияПерсональныхДанных

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

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

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

#Область РаботаСДеревомКатегорийПерсональныхДанных

Функция ИмяРеквизитаДеревоКатегорий()
	Возврат "КатегорииПерсональныхДанных";
КонецФункции

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

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

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

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