Группы доступа / Модуль менеджера

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

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

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

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

// СтандартныеПодсистемы.ГрупповоеИзменениеОбъектов

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

// Конец СтандартныеПодсистемы.ГрупповоеИзменениеОбъектов

// СтандартныеПодсистемы.УправлениеДоступом

// Параметры:
//   Ограничение - см. УправлениеДоступомПереопределяемый.ПриЗаполненииОграниченияДоступа.Ограничение.
//
Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт
	
	Ограничение.Текст =
	"РазрешитьЧтениеИзменение
	|ГДЕ
	|	ЭтоГруппа
	|	ИЛИ Профиль <> Значение(Справочник.ПрофилиГруппДоступа.Администратор)
	|	  И ЭтоАвторизованныйПользователь(Ответственный)";

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

// Конец СтандартныеПодсистемы.УправлениеДоступом

// ТехнологияСервиса.ВыгрузкаЗагрузкаДанных

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

// Конец ТехнологияСервиса.ВыгрузкаЗагрузкаДанных

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

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

#КонецЕсли

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

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

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

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

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

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

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

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

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

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

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

// Устанавливает пометку удаления группам доступа, если установлена
// пометка удаления у профиля группы доступа. Требуется, например,
// при удалении предопределенных профилей групп доступа,
// т.к. платформа не вызывает обработчики объектов при
// установке пометки удаления бывшим предопределенным
// элементам в процессе обновления конфигурации базы данных.
//
// Параметры:
//  ЕстьИзменения - Булево - возвращаемое значение. Если производилась запись,
//                  устанавливается Истина, иначе не изменяется.
//
Процедура ПометитьНаУдалениеГруппыДоступаПомеченныхПрофилей(ЕстьИзменения = Неопределено) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("ПрофильАдминистратор", УправлениеДоступом.ПрофильАдминистратор());
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ГруппыДоступа.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ГруппыДоступа КАК ГруппыДоступа
	|ГДЕ
	|	ГруппыДоступа.Профиль <> &ПрофильАдминистратор
	|	И ГруппыДоступа.Профиль.ПометкаУдаления
	|	И НЕ ГруппыДоступа.ПометкаУдаления
	|	И НЕ ГруппыДоступа.Предопределенный";
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("Справочник.ГруппыДоступа");
	
	Пока Выборка.Следующий() Цикл
		ЭлементБлокировки.УстановитьЗначение("Ссылка", Выборка.Ссылка);
		НачатьТранзакцию();
		Попытка
			Блокировка.Заблокировать();
			ГруппаДоступаОбъект = Выборка.Ссылка.ПолучитьОбъект();
			ГруппаДоступаОбъект.ПометкаУдаления = Истина;
			ОбновлениеИнформационнойБазы.ЗаписатьОбъект(ГруппаДоступаОбъект);
			РегистрыСведений.ТаблицыГруппДоступа.ОбновитьДанныеРегистра(Выборка.Ссылка);
			РегистрыСведений.ЗначенияГруппДоступа.ОбновитьДанныеРегистра(Выборка.Ссылка);
			// @skip-check query-in-loop - Порционная обработка данных в транзакции
			ПользователиДляОбновления = ПользователиДляОбновленияРолей(Неопределено, ГруппаДоступаОбъект);
			УправлениеДоступом.ОбновитьРолиПользователей(ПользователиДляОбновления);
			ЕстьИзменения = Истина;
			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;
	КонецЦикла;
	
КонецПроцедуры

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

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

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

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

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

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

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

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

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

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

// См. ПользователиСлужебный.СериализованнаяСсылка
Функция СериализованнаяСсылка(Ссылка)
	Возврат ПользователиСлужебный.СериализованнаяСсылка(Ссылка);
КонецФункции

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

// Только для внутреннего использования.
//
// Параметры:
//  Объект - СправочникОбъект.ГруппыДоступа
//         - СправочникОбъект.ПрофилиГруппДоступа
//         - ОпределяемыйТип.ЗначениеДоступаОбъект - для регистрации изменений использования групп значений доступа
//             и состава иерархии родителя, если значение доступа используется с нижестоящими значениями.
//         - Структура:
//            * ИзменениеВидовДоступа - ТаблицаЗначений:
//                ** ВидДоступа    - ОпределяемыйТип.ЗначениеДоступа
//                ** Использование - Булево - новое использование вида доступа после изменения
//                     в регистре сведений ИспользуемыеВидыДоступа.
//                ** ВидИзменения  - Строка - одна из строк "Добавлено", "Удалено", "Изменено".
//            * ИзменениеСоставовГруппПользователей - см. ПользователиСлужебный.НовоеИзменениеСоставовГруппДляРегистрации
//
//  СтарыеЗначения - Структура - старые значения свойств, когда объект не типа структура.
//                 - Неопределено - когда объект типа структура.
//
Процедура ЗарегистрироватьИзменениеРазрешенныхЗначений(Объект, СтарыеЗначения) Экспорт
	
	Если ТипЗнч(Объект) = Тип("Структура") Тогда
		Источник = Новый Массив;
		ПредставлениеИсточника = Неопределено;
		Если Объект.Свойство("ИзменениеВидовДоступа") Тогда
			НавигационнаяСсылкаИсточника = "e1cib/list/РегистрСведений.ИспользуемыеВидыДоступа";
			МетаданныеОбъекта = Метаданные.РегистрыСведений.ИспользуемыеВидыДоступа;
		Иначе
			НавигационнаяСсылкаИсточника = "e1cib/list/РегистрСведений.СоставыГруппПользователей";
			МетаданныеОбъекта = Метаданные.РегистрыСведений.СоставыГруппПользователей;
		КонецЕсли;
	Иначе
		Источник = СериализованнаяСсылка(Объект.Ссылка);
		ПредставлениеИсточника = ПредставлениеСсылки(Объект.Ссылка);
		НавигационнаяСсылкаИсточника = ПолучитьНавигационнуюСсылку(Объект.Ссылка);
		МетаданныеОбъекта = Объект.Метаданные();
	КонецЕсли;
	
	Данные = Новый Структура;
	Данные.Вставить("ВерсияСтруктурыДанных", 1);
	Данные.Вставить("Источник", Источник);
	Данные.Вставить("НавигационнаяСсылкаИсточника", НавигационнаяСсылкаИсточника);
	Данные.Вставить("ПредставлениеИсточника", ПредставлениеИсточника);
	Данные.Вставить("ИзменениеВидовДоступа", Новый Массив);
	Данные.Вставить("ПредставлениеВидовДоступа", Новый Массив);
	Данные.Вставить("ИзменениеЗначенийДоступа", Новый Массив);
	Данные.Вставить("ИзменениеГруппЗначенийДоступа", Новый Массив);
	Данные.Вставить("ПредставлениеГруппДоступа", Новый Массив);
	Данные.Вставить("ПредставлениеЗначенийДоступа", Новый Массив);
	
	СвойстваВидовДоступа = УправлениеДоступомСлужебный.СвойстваВидовДоступа();
	
	Если ТипЗнч(Объект) = Тип("СправочникОбъект.ГруппыДоступа") Тогда
		
		// Добавление изменений состава видов доступа и флажка ВсеРазрешены.
		СтарыеЗначения.Вставить("ВидыДоступаПрофиля", Неопределено);
		СвойстваПрофиля = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Объект.Профиль,
			"ПометкаУдаления, ВидыДоступа, ЗначенияДоступа");
		Если СтарыеЗначения.Профиль = Объект.Профиль Тогда
			СтарыеЗначения.ВидыДоступаПрофиля = СвойстваПрофиля.ВидыДоступа;
		ИначеЕсли ЗначениеЗаполнено(СтарыеЗначения.Профиль) Тогда
			СтарыеЗначения.ВидыДоступаПрофиля = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(
				СтарыеЗначения.Профиль, "ВидыДоступа");
		КонецЕсли;
		ПредустановленныеВидыДоступаПрофиля = ?(ЗначениеЗаполнено(СтарыеЗначения.Ссылка),
			Неопределено, Новый Соответствие);
		НовыеВидыДоступа = ВидыДоступаБезПовторений(Объект.ВидыДоступа.Выгрузить(),,
			СвойстваПрофиля.ВидыДоступа, ПредустановленныеВидыДоступаПрофиля);
		ИзменениеВидовДоступа = ИзменениеСоставаВидовДоступа(НовыеВидыДоступа, СтарыеЗначения);
		
		// Добавление изменений состава значений и групп значений доступа, флажка ВключаяНижестоящие,
		// а также значений доступа, у которых вид доступа добавлен / удален / изменен флажок ВсеРазрешены.
		ИзменениеЗначенийДоступа = ИзменениеСоставаЗначенийДоступа(Объект,
			СтарыеЗначения, ИзменениеВидовДоступа, СвойстваВидовДоступа);
		
		Если Не ЗначениеЗаполнено(ИзменениеВидовДоступа)
		   И Не ЗначениеЗаполнено(ИзменениеЗначенийДоступа) Тогда
			Возврат;
		КонецЕсли;
		
		// Добавление неизмененных видов доступа, для которых изменились значения доступа.
		ДобавитьВидыДоступаДляКоторыхИзменилисьЗначенияДоступа(ИзменениеЗначенийДоступа,
			ИзменениеВидовДоступа, НовыеВидыДоступа);
		
		ИзменениеВидовДоступа.ЗаполнитьЗначения(Объект.Ссылка, "ГруппаДоступаИлиПрофиль");
		ИзменениеЗначенийДоступа.ЗаполнитьЗначения(Объект.Ссылка, "ГруппаДоступаИлиПрофиль");
		
		// Добавление предустановленных видов доступа профиля и их значений при создании группы доступа.
		ДобавитьПредустановленныеВидыДоступаСоЗначениями(ИзменениеВидовДоступа, ИзменениеЗначенийДоступа,
			Объект.Профиль, ПредустановленныеВидыДоступаПрофиля, СвойстваПрофиля.ЗначенияДоступа, СвойстваВидовДоступа);
		
		// Заполнение состава измененных групп значений доступа.
		// Заполнение нижестоящих значений доступа с флажком ВключаяНижестоящие и при изменении флажка.
		ИзменениеГруппЗначенийДоступа = ЗначенияГруппЗначений(ИзменениеЗначенийДоступа, СвойстваВидовДоступа);
		УдалитьЛишниеНеизмененныеЗначенияИГруппы(ИзменениеЗначенийДоступа, ИзменениеГруппЗначенийДоступа);
		
		// Добавление представления группы доступа.
		ПометкаУдаленияПрофиля = ?(ТипЗнч(СвойстваПрофиля.ПометкаУдаления) = Тип("Булево"),
			СвойстваПрофиля.ПометкаУдаления, Ложь);
		
		Свойства = Новый Структура;
		Свойства.Вставить("ГруппаДоступа", СериализованнаяСсылка(Объект.Ссылка));
		Свойства.Вставить("Представление", ПредставлениеСсылки(Объект.Ссылка));
		Свойства.Вставить("ПометкаУдаления", Объект.ПометкаУдаления);
		Свойства.Вставить("Профиль", СериализованнаяСсылка(Объект.Профиль));
		Свойства.Вставить("ПредставлениеПрофиля", ПредставлениеСсылки(Объект.Профиль));
		Свойства.Вставить("ПометкаУдаленияПрофиля", ПометкаУдаленияПрофиля);
		Свойства.Вставить("СтарыеЗначенияСвойств", Новый Структура);
		
		Если Объект.ПометкаУдаления <> СтарыеЗначения.ПометкаУдаления Тогда
			Свойства.СтарыеЗначенияСвойств.Вставить("ПометкаУдаления", СтарыеЗначения.ПометкаУдаления);
		КонецЕсли;
		Если Объект.Профиль <> СтарыеЗначения.Профиль Тогда
			Свойства.СтарыеЗначенияСвойств.Вставить("Профиль", СериализованнаяСсылка(СтарыеЗначения.Профиль));
			СтароеПредставлениеПрофиля = ПредставлениеСсылки(СтарыеЗначения.Профиль);
			Если Свойства.ПредставлениеПрофиля <> СтароеПредставлениеПрофиля Тогда
				Свойства.СтарыеЗначенияСвойств.Вставить("ПредставлениеПрофиля", СтароеПредставлениеПрофиля);
			КонецЕсли;
		КонецЕсли;
		Если ПометкаУдаленияПрофиля <> СтарыеЗначения.ПометкаУдаленияПрофиля Тогда
			Свойства.СтарыеЗначенияСвойств.Вставить("ПометкаУдаленияПрофиля", СтарыеЗначения.ПометкаУдаленияПрофиля);
		КонецЕсли;
		Данные.ПредставлениеГруппДоступа.Добавить(Свойства);
		
	ИначеЕсли ТипЗнч(Объект) = Тип("СправочникОбъект.ПрофилиГруппДоступа") Тогда
		
		// Добавление изменений состава видов доступа и флажков ВсеРазрешены, Предустановленный.
		ВидыДоступаСИзменениемПредустановки = Новый Массив;
		НовыеВидыДоступа = ВидыДоступаБезПовторений(Объект.ВидыДоступа.Выгрузить(), Истина);
		ИзменениеВидовДоступа = ИзменениеСоставаВидовДоступа(НовыеВидыДоступа,
			СтарыеЗначения, Истина, ВидыДоступаСИзменениемПредустановки);
		
		// Добавление изменений состава значений и групп значений доступа, флажка ВключаяНижестоящие,
		// а также значений доступа, у которых вид доступа добавлен / удален / изменен флажок ВсеРазрешены.
		ИзменениеЗначенийДоступа = ИзменениеСоставаЗначенийДоступа(Объект, СтарыеЗначения,
			ИзменениеВидовДоступа, СвойстваВидовДоступа);
		
		Если Не ЗначениеЗаполнено(ИзменениеВидовДоступа)
		   И Не ЗначениеЗаполнено(ИзменениеЗначенийДоступа) Тогда
			Возврат;
		КонецЕсли;
		
		// Добавление неизмененных видов доступа, для которых изменились значения доступа.
		ДобавитьВидыДоступаДляКоторыхИзменилисьЗначенияДоступа(ИзменениеЗначенийДоступа,
			ИзменениеВидовДоступа, НовыеВидыДоступа);
		
		ИзменениеВидовДоступа.ЗаполнитьЗначения(Объект.Ссылка, "ГруппаДоступаИлиПрофиль");
		ИзменениеЗначенийДоступа.ЗаполнитьЗначения(Объект.Ссылка, "ГруппаДоступаИлиПрофиль");
		
		// Добавление видов и значений доступа групп доступа профиля,
		// для видов доступа профиля с измененным признаком Предустановленный.
		СвойстваГруппДоступа = СвойстваГруппДоступаПрофиля(Объект.Ссылка, ВидыДоступаСИзменениемПредустановки);
		ЗаполнитьВидыИЗначенияДоступа(ИзменениеВидовДоступа,
			ИзменениеЗначенийДоступа, СвойстваГруппДоступа, СвойстваВидовДоступа);
		
		// Заполнение состава измененных групп значений доступа.
		// Заполнение нижестоящих значений доступа с флажком ВключаяНижестоящие и при изменении флажка.
		ИзменениеГруппЗначенийДоступа = ЗначенияГруппЗначений(ИзменениеЗначенийДоступа, СвойстваВидовДоступа);
		УдалитьЛишниеНеизмененныеЗначенияИГруппы(ИзменениеЗначенийДоступа, ИзменениеГруппЗначенийДоступа);
		
		// Добавление представлений групп доступа профиля.
		СериализованнаяСсылкаПрофиля = СериализованнаяСсылка(Объект.Ссылка);
		ПредставлениеПрофиля = ПредставлениеСсылки(Объект.Ссылка);
		СтарыеЗначенияСвойств = Новый Структура;
		Если Объект.ПометкаУдаления <> СтарыеЗначения.ПометкаУдаления Тогда
			СтарыеЗначенияСвойств.Вставить("ПометкаУдаленияПрофиля",
				?(ТипЗнч(СтарыеЗначения.ПометкаУдаления) = Тип("Булево"),
					СтарыеЗначения.ПометкаУдаления, Ложь));
		КонецЕсли;
		СтароеПредставлениеПрофиля = ПредставлениеСсылки(СтарыеЗначения.Ссылка);
		Если ПредставлениеПрофиля <> СтароеПредставлениеПрофиля Тогда
			СтарыеЗначенияСвойств.Вставить("ПредставлениеПрофиля", СтароеПредставлениеПрофиля);
		КонецЕсли;
		Если Не ЗначениеЗаполнено(СвойстваГруппДоступа.ГруппыДоступа) Тогда
			НоваяСтрока = СвойстваГруппДоступа.ГруппыДоступа.Добавить();
			НоваяСтрока.ГруппаДоступа = Справочники.ГруппыДоступа.ПустаяСсылка();
			НоваяСтрока.Представление = "<" + НСтр("ru = 'Нет группы доступа'",
				ОбщегоНазначения.КодОсновногоЯзыка()) + ">";
		КонецЕсли;
		Для Каждого ОписаниеГруппыДоступа Из СвойстваГруппДоступа.ГруппыДоступа Цикл
			Свойства = Новый Структура;
			Свойства.Вставить("ГруппаДоступа", СериализованнаяСсылка(ОписаниеГруппыДоступа.ГруппаДоступа));
			Свойства.Вставить("Представление", ОписаниеГруппыДоступа.Представление);
			Свойства.Вставить("ПометкаУдаления", ОписаниеГруппыДоступа.ПометкаУдаления);
			Свойства.Вставить("Профиль", СериализованнаяСсылкаПрофиля);
			Свойства.Вставить("ПредставлениеПрофиля", ПредставлениеПрофиля);
			Свойства.Вставить("ПометкаУдаленияПрофиля", Объект.ПометкаУдаления);
			Свойства.Вставить("СтарыеЗначенияСвойств", СтарыеЗначенияСвойств);
			Данные.ПредставлениеГруппДоступа.Добавить(Свойства);
		КонецЦикла;
		
	ИначеЕсли ТипЗнч(Объект) <> Тип("Структура")
	      Или Объект.Свойство("ИзменениеСоставовГруппПользователей") Тогда
		
		ИзменениеВидовДоступа = НовоеИзменениеВидовДоступа();
		ИзменениеЗначенийДоступа = НовоеИзменениеЗначенийДоступа();
		ИзменениеГруппЗначенийДоступа = Неопределено;
		
		Если ТипЗнч(Объект) = Тип("Структура") Тогда
			ИзменениеГруппЗначенийДоступа = Объект.ИзменениеСоставовГруппПользователей.Скопировать(,
				"ГруппаПользователей, Пользователь, ВидИзменения");
			ИзменениеГруппЗначенийДоступа.Колонки.ГруппаПользователей.Имя = "ГруппаЗначений";
			ИзменениеГруппЗначенийДоступа.Колонки.Пользователь.Имя = "ЗначениеДоступа";
			Отбор = Новый Структура("ВидИзменения", "Изменено");
			НайденныеСтроки = ИзменениеГруппЗначенийДоступа.НайтиСтроки(Отбор);
			Для Каждого НайденнаяСтрока Из НайденныеСтроки Цикл
				ИзменениеГруппЗначенийДоступа.Удалить(НайденнаяСтрока);
			КонецЦикла;
			СвойстваПрофилейИГруппДоступа = СвойстваПрофилейИГруппДоступаИзмененийГруппЗначений(
				ИзменениеГруппЗначенийДоступа);
			
		ИначеЕсли СтарыеЗначения.Свойство("ГруппаДоступа")
		      Или СтарыеЗначения.Свойство("ГруппыДоступа") Тогда
			
			Свойства = СвойстваВидовДоступа.ЗначенияДоступаСГруппами.ПоТипамДляОбновления.Получить(ТипЗнч(Объект));
			Если Свойства = Неопределено
			 Или Свойства.ТипГруппЗначений <> Тип("Неопределено") Тогда
				Возврат;
			КонецЕсли;
			ИзменениеГруппЗначенийДоступа = ИзменениеГруппЗначенийДоступа(Объект,
				СтарыеЗначения, Свойства.НесколькоГруппЗначений);
			
			СвойстваПрофилейИГруппДоступа = СвойстваПрофилейИГруппДоступаИзмененийГруппЗначений(
				ИзменениеГруппЗначенийДоступа);
			
		ИначеЕсли СтарыеЗначения.Свойство("Родитель") Тогда
			Свойства = СвойстваВидовДоступа.ПоТипамЗначенийСИерархией.Получить(ТипЗнч(Объект));
			Если Свойства = Неопределено Тогда
				Возврат;
			КонецЕсли;
			ИзменениеГруппЗначенийДоступа = ИзменениеЗначенийДоступаРодителей(Объект, СтарыеЗначения);
			
			СвойстваПрофилейИГруппДоступа = СвойстваПрофилейИГруппДоступаИзмененийГруппЗначений(
				ИзменениеГруппЗначенийДоступа, Истина);
		КонецЕсли;
		
		ЗаполнитьВидыИЗначенияДоступа(ИзменениеВидовДоступа,
			ИзменениеЗначенийДоступа, СвойстваПрофилейИГруппДоступа, СвойстваВидовДоступа);
		
		УдалитьЛишниеНеизмененныеЗначенияИГруппы(ИзменениеЗначенийДоступа, ИзменениеГруппЗначенийДоступа);
		
		// Добавление представлений групп доступа профилей.
		ЗаполнитьПредставлениеГруппДоступаПрофилей(Данные, СвойстваПрофилейИГруппДоступа.ГруппыДоступа);
	Иначе
		// Добавление изменения использования видов доступа.
		Для Каждого Строка Из Объект.ИзменениеВидовДоступа Цикл
			Свойства = Новый Структура;
			Свойства.Вставить("ВидДоступа",   СериализованнаяСсылка(Строка.ВидДоступа));
			Свойства.Вставить("Используется", Строка.Используется);
			Свойства.Вставить("ВидИзменения", Строка.ВидИзменения);
			Данные.Источник.Добавить(Свойства);
		КонецЦикла;
		
		ИзменениеВидовДоступа = НовоеИзменениеВидовДоступа();
		ИзменениеЗначенийДоступа = НовоеИзменениеЗначенийДоступа();
		
		СвойстваПрофилейИГруппДоступа = СвойстваПрофилейИГруппДоступаИзмененийВидовДоступа(Объект.ИзменениеВидовДоступа);
		ЗаполнитьВидыИЗначенияДоступа(ИзменениеВидовДоступа,
			ИзменениеЗначенийДоступа, СвойстваПрофилейИГруппДоступа, СвойстваВидовДоступа);
		
		// Заполнение состава измененных групп значений доступа.
		// Заполнение нижестоящих значений доступа с флажком ВключаяНижестоящие.
		ИзменениеГруппЗначенийДоступа = ЗначенияГруппЗначений(ИзменениеЗначенийДоступа, СвойстваВидовДоступа);
		
		// Добавление представлений групп доступа профилей.
		ЗаполнитьПредставлениеГруппДоступаПрофилей(Данные, СвойстваПрофилейИГруппДоступа.ГруппыДоступа);
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(ИзменениеВидовДоступа)
	   И Не ЗначениеЗаполнено(ИзменениеЗначенийДоступа) Тогда
		Возврат;
	КонецЕсли;
	
	// Заполнение изменений видов доступа.
	Для Каждого Строка Из ИзменениеВидовДоступа Цикл
		Свойства = Новый Структура;
		Свойства.Вставить("ГруппаДоступаИлиПрофиль", СериализованнаяСсылка(Строка.ГруппаДоступаИлиПрофиль));
		Свойства.Вставить("ВидДоступа",              СериализованнаяСсылка(Строка.ВидДоступа));
		Свойства.Вставить("ВсеРазрешены",            Строка.ВсеРазрешены);
		Свойства.Вставить("Предустановленный",       Строка.Предустановленный);
		Свойства.Вставить("ВидИзменения",            Строка.ВидИзменения);
		Свойства.Вставить("СтарыеЗначенияСвойств",   Строка.СтарыеЗначенияСвойств);
		Данные.ИзменениеВидовДоступа.Добавить(Свойства);
	КонецЦикла;
	
	// Заполнение представлений видов доступа.
	РегистрируемыеВидыДоступа = ИзменениеВидовДоступа.Скопировать(, "ВидДоступа");
	РегистрируемыеВидыДоступа.Свернуть("ВидДоступа");
	СвойстваВидовДоступаПоТипам = СвойстваВидовДоступа.ПоТипамГруппИЗначений;
	ИспользуемыеВидыДоступа = УправлениеДоступомСлужебный.ИспользуемыеВидыДоступа(Истина);
	ПредставлениеВидовДоступа = УправлениеДоступомСлужебный.ПредставлениеВидовДоступа();
	
	Для Каждого Строка Из РегистрируемыеВидыДоступа Цикл
		ТипЗначенияВидаДоступа = ТипЗнч(Строка.ВидДоступа);
		Свойства = Новый Структура;
		Свойства.Вставить("ВидДоступа", СериализованнаяСсылка(Строка.ВидДоступа));
		Свойства.Вставить("Используется", ИспользуемыеВидыДоступа.Получить(Строка.ВидДоступа) <> Неопределено);
		Свойства.Вставить("Имя", "");
		Свойства.Вставить("Представление", "");
		СвойстваВидаДоступа = СвойстваВидовДоступаПоТипам.Получить(ТипЗначенияВидаДоступа);
		Если СвойстваВидаДоступа = Неопределено Тогда
			Свойства.Представление = "? " + Строка(ТипЗначенияВидаДоступа);
		Иначе
			Свойства.Имя = СвойстваВидаДоступа.Имя;
			Свойства.Представление = ПредставлениеВидовДоступа.Получить(ТипЗначенияВидаДоступа);
		КонецЕсли;
		Данные.ПредставлениеВидовДоступа.Добавить(Свойства);
	КонецЦикла;
	
	// Заполнение изменений значений доступа.
	Для Каждого Строка Из ИзменениеЗначенийДоступа Цикл
		Свойства = Новый Структура;
		Свойства.Вставить("ГруппаДоступаИлиПрофиль", СериализованнаяСсылка(Строка.ГруппаДоступаИлиПрофиль));
		Свойства.Вставить("ВидДоступа",              СериализованнаяСсылка(Строка.ВидДоступа));
		Свойства.Вставить("ЗначениеДоступа",         СериализованнаяСсылка(Строка.ЗначениеДоступа));
		Свойства.Вставить("ЭтоГруппаЗначений",       Строка.ЭтоГруппаЗначений);
		Свойства.Вставить("ВключаяНижестоящие",      Строка.ВключаяНижестоящие);
		Свойства.Вставить("ВидИзменения",            Строка.ВидИзменения);
		Свойства.Вставить("СтарыеЗначенияСвойств",   Строка.СтарыеЗначенияСвойств);
		Данные.ИзменениеЗначенийДоступа.Добавить(Свойства);
	КонецЦикла;
	
	РегистрируемыеЗначения = ИзменениеЗначенийДоступа.Скопировать(, "ЗначениеДоступа");
	
	// Заполнение изменений групп значений доступа.
	Если ЗначениеЗаполнено(ИзменениеГруппЗначенийДоступа) Тогда
		Для Каждого Строка Из ИзменениеГруппЗначенийДоступа Цикл
			Свойства = Новый Структура;
			Свойства.Вставить("ГруппаЗначений",  СериализованнаяСсылка(Строка.ГруппаЗначений));
			Свойства.Вставить("ЗначениеДоступа", СериализованнаяСсылка(Строка.ЗначениеДоступа));
			Свойства.Вставить("ВидИзменения",    Строка.ВидИзменения);
			Данные.ИзменениеГруппЗначенийДоступа.Добавить(Свойства);
			РегистрируемыеЗначения.Добавить().ЗначениеДоступа = Строка.ГруппаЗначений;
			РегистрируемыеЗначения.Добавить().ЗначениеДоступа = Строка.ЗначениеДоступа;
		КонецЦикла;
	КонецЕсли;
	
	// Заполнение представлений значений и групп значений доступа.
	РегистрируемыеЗначения.Свернуть("ЗначениеДоступа");
	КодыПеречислений = УправлениеДоступомСлужебныйПовтИсп.КодыПеречислений();
	ПеречисленияТипВсеСсылки = Перечисления.ТипВсеСсылки();
	Для Каждого Строка Из РегистрируемыеЗначения Цикл
		Свойства = Новый Структура;
		Свойства.Вставить("Значение", СериализованнаяСсылка(Строка.ЗначениеДоступа));
		Свойства.Вставить("Представление", ПредставлениеСсылки(Строка.ЗначениеДоступа));
		Свойства.Вставить("НавигационнаяСсылка", "");
		Если СтрНачинаетсяС(Свойства.Значение, "{") Тогда
			Если ПеречисленияТипВсеСсылки.СодержитТип(ТипЗнч(Строка.ЗначениеДоступа)) Тогда
				Свойства.НавигационнаяСсылка = СтрШаблон("e1cib/list/%1?name=%2",
					Строка.ЗначениеДоступа.Метаданные().ПолноеИмя(), КодыПеречислений.Получить(Строка.ЗначениеДоступа));
			Иначе
				Свойства.НавигационнаяСсылка = ПолучитьНавигационнуюСсылку(Строка.ЗначениеДоступа);
			КонецЕсли;
		КонецЕсли;
		Данные.ПредставлениеЗначенийДоступа.Добавить(Свойства);
	КонецЦикла;
	
	ИмяСобытия = УправлениеДоступомСлужебный.ИмяСобытияИзменениеРазрешенныхЗначенийДляЖурналаРегистрации();
	
	ЗаписьЖурналаРегистрации(ИмяСобытия,
		УровеньЖурналаРегистрации.Информация,
		МетаданныеОбъекта,
		ОбщегоНазначения.ЗначениеВСтрокуXML(Данные),
		,
		РежимТранзакцииЗаписиЖурналаРегистрации.Транзакционная);
	
КонецПроцедуры

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Результат.Добавить(Выборка.Родитель1);
		Если ЗначениеЗаполнено(Выборка.Родитель1) Тогда
			Результат.Добавить(Выборка.Родитель2);
			Если ЗначениеЗаполнено(Выборка.Родитель2) Тогда
				Результат.Добавить(Выборка.Родитель3);
				Если ЗначениеЗаполнено(Выборка.Родитель3) Тогда
					Результат.Добавить(Выборка.Родитель4);
					Если ЗначениеЗаполнено(Выборка.Родитель4) Тогда
						ДополнительныйРезультат = ЗначениеСРодителями(Выборка.Родитель5);
						Для Каждого Значение Из ДополнительныйРезультат Цикл
							Результат.Добавить(Значение);
						КонецЦикла;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

#Область ПроцедурыИФункцииДляПоддержкиОбменаДаннымиВРИБ

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

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


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

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

// Для процедуры ОбработатьИзменениеЗарегистрированноеПриПолученииДанных.
Процедура ОбработатьЗарегистрированноеИзменениеГруппДоступа(ИмяВидаСсылок, ОчисткаРегистрации)

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

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

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

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

#Область НачальноеЗаполнение

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

// Смотри также ОбновлениеИнформационнойБазыПереопределяемый.ПриНачальномЗаполненииЭлементов
// 
// Параметры:
//   КодыЯзыков - см. ОбновлениеИнформационнойБазыПереопределяемый.ПриНачальномЗаполненииЭлементов.КодыЯзыков
//   Элементы - см. ОбновлениеИнформационнойБазыПереопределяемый.ПриНачальномЗаполненииЭлементов.Элементы
//   ТабличныеЧасти - см. ОбновлениеИнформационнойБазыПереопределяемый.ПриНачальномЗаполненииЭлементов.ТабличныеЧасти
//
Процедура ПриНачальномЗаполненииЭлементов(КодыЯзыков, Элементы, ТабличныеЧасти) Экспорт

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

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

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

Процедура ЗаполнитьПрофильГруппыДоступаАдминистраторы() Экспорт
	
	Объект = УправлениеДоступом.ГруппаДоступаАдминистраторы().ПолучитьОбъект();
	Если Объект.Профиль <> УправлениеДоступом.ПрофильАдминистратор() Тогда
		Объект.Профиль = УправлениеДоступом.ПрофильАдминистратор();
		ОбновлениеИнформационнойБазы.ЗаписатьДанные(Объект);
	КонецЕсли;
	
КонецПроцедуры

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

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

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

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

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

#КонецЕсли

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