Настройки новостей / Модуль менеджера

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

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

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

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

Процедура ОбработкаЗагрузки(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователяИБ)

	Если НЕ ПроверитьПраваДоступа("ОбработкаЗагрузки") Тогда
		Возврат;
	КонецЕсли;

	ТипСтрока            = Тип("Строка");
	ТипСтруктура         = Тип("Структура");
	ТипХранилищеЗначения = Тип("ХранилищеЗначения");
	ТипЛентаНовостей     = Тип("СправочникСсылка.ЛентыНовостей");
	ТипПользователь      = Тип("СправочникСсылка.Пользователи");

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

	// Глобальные настройки.
	Если (КлючОбъекта = "НастройкиПолученияНовостей") // Структура
			ИЛИ (КлючОбъекта = "НастройкиАвтоудаленияНовостей") // Структура
			ИЛИ (КлючОбъекта = "СистемнаяИнформация_ВерсияПриложения") // Строка
			ИЛИ (КлючОбъекта = "СостояниеПодсистемы") // Структура
			ИЛИ (КлючОбъекта = "НастройкиЖурналаРегистрации") Тогда // Структура

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

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

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

	// Настройки для области данных.
	ИначеЕсли (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанных")
			ИЛИ (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанныхДляРедактирования") Тогда // Структура

		// Эта настройка может храниться или в константе НастройкиНовостей (для модели сервиса в неразделенном режиме или в коробке),
		//  или в регистре сведений "НастройкиНовостейОбластиДанных".
		// Причем для области данных настройки может и не быть. Тогда брать настройку из константы.

		УстановитьПривилегированныйРежим(Истина);

			// Для этого ключа объекта не действует КлючНастроек.
			Настройки = Неопределено;
			Настройки = ПровестиВалидациюНастроек(Настройки, КлючОбъекта, "");

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

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

		УстановитьПривилегированныйРежим(Ложь);

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

	ИначеЕсли КлючОбъекта = "ОтборыПоЛентамНовостейДляОбластиДанных" Тогда
		// Для этого ключа объекта КлючНастроек = СправочникСсылка.ЛентаНовостей, или не введен.
		// Фактически настройки хранятся в регистре сведений ОтборыПоЛентамНовостейДляОбластиДанных.
		// Для коробки вернуть данные из регистра сведений ОтборыПоЛентамНовостейДляОбластиДанных.
		// Для модели сервиса, неразделенного режима, вернуть пустой список.
		// Для модели сервиса, разделенного режима, вернуть данные из регистра сведений
		//   ОтборыПоЛентамНовостейДляОбластиДанных для этой области данных.

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

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

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

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

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

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

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

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

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

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

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

	КонецЕсли;

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

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

	Если НЕ ПроверитьПраваДоступа("ОбработкаПолученияОписания") Тогда
		Возврат;
	КонецЕсли;

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

	// Пользовательские настройки.
	ИначеЕсли КлючОбъекта = "НастройкиПоказаНовостей" Тогда
		// Для этого ключа объекта не действует КлючНастроек.
	ИначеЕсли КлючОбъекта = "ОтключенныеПанелиКонтекстныхНовостей" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ОтборыПоЛентамНовостейПользовательские" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ОтключенныеЛентыНовостей" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ДоступныеЛентыНовостей" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ЛентыНовостейПодпискаВключена" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ЛентыНовостейПодпискаВключенаПользователем" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ЛентыНовостейПодпискаОтключенаПользователем" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ЛентыНовостейВсеНастройки" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	ИначеЕсли КлючОбъекта = "ВидимостьЛентНовостей" Тогда
		ОписаниеНастроек = Новый ОписаниеНастроек;
	КонецЕсли;

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

Процедура ОбработкаСохранения(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователяИБ)

	Если НЕ ПроверитьПраваДоступа("ОбработкаСохранения") Тогда
		Возврат;
	КонецЕсли;

	ТипСтруктура         = Тип("Структура");
	ТипХранилищеЗначения = Тип("ХранилищеЗначения");

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

	// Глобальные настройки.
	Если (КлючОбъекта = "НастройкиПолученияНовостей")
			ИЛИ (КлючОбъекта = "НастройкиАвтоудаленияНовостей")
			ИЛИ (КлючОбъекта = "СистемнаяИнформация_ВерсияПриложения")
			ИЛИ (КлючОбъекта = "СостояниеПодсистемы")
			ИЛИ (КлючОбъекта = "НастройкиЖурналаРегистрации") Тогда

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

	// Глобальные настройки.
	ИначеЕсли (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистратором") Тогда

		Настройки = ПровестиВалидациюНастроек(Настройки, КлючОбъекта, "");

		УстановитьПривилегированныйРежим(Истина);

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

		УстановитьПривилегированныйРежим(Ложь);

	// Настройки для области данных.
	ИначеЕсли (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанных")
			ИЛИ (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанныхДляРедактирования") Тогда

		Настройки = ПровестиВалидациюНастроек(Настройки, КлючОбъекта, "");

		УстановитьПривилегированныйРежим(Истина);

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

		УстановитьПривилегированныйРежим(Ложь);

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

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

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

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

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

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

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

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

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

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

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

	ИначеЕсли КлючОбъекта = "ВидимостьЛентНовостей" Тогда
		// Для этого ключа объекта не действует КлючНастроек;
		// Эта настройка по сути не является настройкой и хранится в каждой ленте новостей, в табличной части;
		// Поэтому для нее настройка не сохраняется. Настроить и сохранить ее может администратор, редактируя каждую ленту новостей.

	КонецЕсли;

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

Процедура ОбработкаУстановкиОписания(КлючОбъекта, КлючНастроек, ОписаниеНастроек, ИмяПользователяИБ)

	Если НЕ ПроверитьПраваДоступа("ОбработкаУстановкиОписания") Тогда
		Возврат;
	КонецЕсли;

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

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

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

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

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

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

	ТипСтруктура                         = Тип("Структура");
	ТипЧисло                             = Тип("Число");
	ТипБулево                            = Тип("Булево");
	ТипСтрока                            = Тип("Строка");
	ТипДата                              = Тип("Дата");
	ТипСписокЗначений                    = Тип("СписокЗначений");
	ТипМассив                            = Тип("Массив");
	ТипЛентаНовостей                     = Тип("СправочникСсылка.ЛентыНовостей");
	ТипПользовательСистемыВзаимодействия = Тип("ПользовательСистемыВзаимодействия");

	Если (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистратором") Тогда
		// Для этого ключа объекта не действует КлючНастроек.
		// Обязательные поля:
		// - СписокНовостей_ИнтервалАвтообновления - Число(6.0), неотрицательное, по-умолчанию 360 минут (6 часов), минимум 1 минута.
		//     Если настройка отсутствует в области данных в модели сервиса, то значение берется из этой, неразделенной настройки.
		//     В этом случае значение должно быть 60, 180 или 360. Если это не так, то изменить на 0.
		Результат = Новый Структура("
			|СписокНовостей_ИнтервалАвтообновления",
			360); // минут

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

			Если ТипЗнч(Результат.СписокНовостей_ИнтервалАвтообновления) = ТипЧисло
					И (Результат.СписокНовостей_ИнтервалАвтообновления >= 1)
					И (Результат.СписокНовостей_ИнтервалАвтообновления <= 999999) Тогда
				// Корректное значение
			Иначе
				Результат.СписокНовостей_ИнтервалАвтообновления = 360;
			КонецЕсли;

		КонецЕсли;

	ИначеЕсли (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанных")
			ИЛИ (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанныхДляРедактирования") Тогда
		// Для этого ключа объекта не действует КлючНастроек.
		// Обязательные поля:
		// - СписокНовостей_ИнтервалАвтообновления - Число(6.0), неотрицательное, по-умолчанию 360 минут (6 часов), минимум 1 минута.
		Если (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанных") Тогда
			Результат = Новый Структура("
				|СписокНовостей_ИнтервалАвтообновления",
				360); // минут
		ИначеЕсли (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанныхДляРедактирования") Тогда
			Результат = Новый Структура("
				|СписокНовостей_ИнтервалАвтообновления",
				0); // минут
		КонецЕсли;

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

			// Для разделенного режима есть особенности:
			// - значение "0" означает удаление настройки и использование значения из константы;
			// - Допустимые значения: 0, 60, 180, 360. При этом "0" допустим только для "ДляРедактирования".

			Если (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанных") Тогда

				// Значение может наследоваться из "НастройкиПоказаНовостейНастроенныеАдминистратором".
				Если ТипЗнч(Результат.СписокНовостей_ИнтервалАвтообновления) = ТипЧисло
						И (Результат.СписокНовостей_ИнтервалАвтообновления >= 1)
						И (Результат.СписокНовостей_ИнтервалАвтообновления <= 999999) Тогда
					// Корректное значение
				Иначе
					Результат.СписокНовостей_ИнтервалАвтообновления = 360;
				КонецЕсли;

			ИначеЕсли (КлючОбъекта = "НастройкиПоказаНовостейНастроенныеАдминистраторомДляОбластиДанныхДляРедактирования") Тогда

				Если ТипЗнч(Результат.СписокНовостей_ИнтервалАвтообновления) = ТипЧисло
						И (
							(Результат.СписокНовостей_ИнтервалАвтообновления = 0)
							ИЛИ (Результат.СписокНовостей_ИнтервалАвтообновления = 60)
							ИЛИ (Результат.СписокНовостей_ИнтервалАвтообновления = 180)
							ИЛИ (Результат.СписокНовостей_ИнтервалАвтообновления = 360)) Тогда
					// Корректное значение
				Иначе
					Результат.СписокНовостей_ИнтервалАвтообновления = 0;
				КонецЕсли;

			КонецЕсли;

		КонецЕсли;

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

		Если ТипЗнч(Настройки) = ТипСтруктура Тогда
			// Проверять:
			//  заполнение (есть ли такое свойство. Если нет - добавить со значением по-умолчанию);
			//  правильный тип;
			//  правильный интервал значения (вхождение в список значений, минимум, максимум).
			ЗаполнитьЗначенияСвойств(Результат, Настройки);
			Если ТипЗнч(Результат.ОтборНовостей_ТолькоАктивные) <> ТипБулево Тогда
				Результат.ОтборНовостей_ТолькоАктивные = Истина;
			КонецЕсли;
			Если ТипЗнч(Результат.ОтображаемыеНовости_Вариант) <> ТипСтрока
					ИЛИ (
						ВРег(Результат.ОтображаемыеНовости_Вариант) <> ВРег("Все")
						И ВРег(Результат.ОтображаемыеНовости_Вариант) <> ВРег("Количество")
						И ВРег(Результат.ОтображаемыеНовости_Вариант) <> ВРег("Период")) Тогда
				Результат.ОтображаемыеНовости_Вариант = "Все";
			КонецЕсли;
			Если ТипЗнч(Результат.ОтображаемыеНовости_Количество) <> ТипЧисло
					ИЛИ Результат.ОтображаемыеНовости_Количество < 1
					ИЛИ Результат.ОтображаемыеНовости_Количество > 9999 Тогда
				Результат.ОтображаемыеНовости_Количество = 25;
			КонецЕсли;
			Если ТипЗнч(Результат.ОтображаемыеНовости_ПериодЧасов) <> ТипЧисло
					ИЛИ Результат.ОтображаемыеНовости_ПериодЧасов < 1
					ИЛИ Результат.ОтображаемыеНовости_ПериодЧасов > 999999 Тогда
				Результат.ОтображаемыеНовости_ПериодЧасов = 168;
			КонецЕсли;
			Если ТипЗнч(Результат.Форма_РазмещениеПанелей) <> ТипСтрока
					ИЛИ (
						ВРег(Результат.Форма_РазмещениеПанелей) <> ВРег("Текст новости справа от списка новостей") // АПК:1297 Это идентификатор.
						И ВРег(Результат.Форма_РазмещениеПанелей) <> ВРег("Текст новости под списком новостей") // АПК:1297 Это идентификатор.
						И ВРег(Результат.Форма_РазмещениеПанелей) <> ВРег("Текст новости не отображается") // АПК:1297 Это идентификатор.
						И ВРег(Результат.Форма_РазмещениеПанелей) <> ВРег("Текст новости не отображается, есть предпросмотр")) Тогда // АПК:1297 Это идентификатор.
				Результат.Форма_РазмещениеПанелей = "Текст новости справа от списка новостей"; // АПК:1297 Это идентификатор.
			КонецЕсли;
			Если ТипЗнч(Результат.СписокРаскрытыхПапок) <> ТипСписокЗначений Тогда
				Результат.СписокРаскрытыхПапок = Новый СписокЗначений;
			Иначе
				МаксимальныйВариантОтбора = 9;
				// Все значения элементов списка должны быть структурами с ключами ВариантОтбора (число 1.0) и ЗначениеОтбора (Строка или ЛентаНовостей).
				ПравильныйСписок = Новый СписокЗначений;
				Для Каждого ТекущийЭлемент Из Результат.СписокРаскрытыхПапок Цикл
					Если ТипЗнч(ТекущийЭлемент.Значение) = ТипСтруктура Тогда
						ТекущийЭлементЗначениеЭталон = Новый Структура;
							ТекущийЭлементЗначениеЭталон.Вставить("ВариантОтбора" , Неопределено);
							ТекущийЭлементЗначениеЭталон.Вставить("ЗначениеОтбора", Неопределено);
						ЗаполнитьЗначенияСвойств(ТекущийЭлементЗначениеЭталон, ТекущийЭлемент.Значение);
						ЭтоПравильныйЭлемент = Истина;
						Если НЕ ((ТипЗнч(ТекущийЭлементЗначениеЭталон.ВариантОтбора) = ТипЧисло)
								И ТекущийЭлементЗначениеЭталон.ВариантОтбора >= 0
								И ТекущийЭлементЗначениеЭталон.ВариантОтбора <= МаксимальныйВариантОтбора) Тогда
							ЭтоПравильныйЭлемент = Ложь;
						КонецЕсли;
						Если (ТипЗнч(ТекущийЭлементЗначениеЭталон.ЗначениеОтбора) <> ТипСтрока
								И ТипЗнч(ТекущийЭлементЗначениеЭталон.ЗначениеОтбора) <> ТипЛентаНовостей
								И ТекущийЭлементЗначениеЭталон.ЗначениеОтбора <> Неопределено) Тогда // Для папок "Все" нет значения отбора
							ЭтоПравильныйЭлемент = Ложь;
						КонецЕсли;
						Если ЭтоПравильныйЭлемент = Истина Тогда
							ПравильныйСписок.Добавить(ТекущийЭлемент.Значение);
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				Результат.СписокРаскрытыхПапок = ПравильныйСписок;
			КонецЕсли;
		КонецЕсли;

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

	ИначеЕсли КлючОбъекта = "ОтключенныеПанелиКонтекстныхНовостей" Тогда
		// Для этого ключа объекта КлючНастроек = Строка, где через символ "|" объединены измерения
		//  регистра "ОтключенныеПанелиКонтекстныхНовостей": Метаданные и Форма.
		// Фактически настройки хранятся в регистре сведений ОтключенныеПанелиКонтекстныхНовостей.

		НастройкиЭталон = Новый Структура;
			НастройкиЭталон.Вставить("ОбластьДанных"       , 0);
			НастройкиЭталон.Вставить("Метаданные"          , "");
			НастройкиЭталон.Вставить("Форма"               , "");
			НастройкиЭталон.Вставить("ДатаОтключения"      , '00010101');
			НастройкиЭталон.Вставить("ДатаПоследнейНовости", '00010101');

		ИмяМетаданных = "";
		ИмяФормы      = "";
		МассивИзмерений = СтрРазделить(КлючНастроек, "|", Истина);
		Если МассивИзмерений.Количество() >= 1 Тогда
			ИмяМетаданных = МассивИзмерений[0];
		КонецЕсли;
		Если МассивИзмерений.Количество() >= 2 Тогда
			ИмяФормы = МассивИзмерений[1];
		КонецЕсли;

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

	ИначеЕсли КлючОбъекта = "НастройкиПолученияНовостей" Тогда
		// Для этого ключа объекта не действует КлючНастроек.
		// Обязательные поля:
		// - ВебСервисыТаймаутСоединенияСекунд             - Число(3.0), неотрицательное, по-умолчанию 30 (секунд);
		// - ВебСервисыКоличествоПопытокСоединения         - Число(2.0), неотрицательное, по-умолчанию 1;
		// - HTTPСоединениеТаймаутСоединенияСекунд         - Число(3.0), неотрицательное, по-умолчанию 30 (секунд);
		// - HTTPСоединениеКоличествоПопытокСоединения     - Число(2.0), неотрицательное, по-умолчанию 1;
		// - HTTPСоединениеКоличествоПопытокПолученияФайла - Число(2.0), неотрицательное, по-умолчанию 1.
		Результат = Новый Структура;
			Результат.Вставить("ВебСервисыТаймаутСоединенияСекунд"            , 30);
			Результат.Вставить("ВебСервисыКоличествоПопытокСоединения"        , 1);
			Результат.Вставить("HTTPСоединениеТаймаутСоединенияСекунд"        , 30);
			Результат.Вставить("HTTPСоединениеКоличествоПопытокСоединения"    , 1);
			Результат.Вставить("HTTPСоединениеКоличествоПопытокПолученияФайла", 1);

		Если ТипЗнч(Настройки) = ТипСтруктура Тогда
			// Проверять:
			//  заполнение (есть ли такое свойство. Если нет - добавить со значением по-умолчанию);
			//  правильный тип;
			//  правильный интервал значения (вхождение в список значений, минимум, максимум).
			ЗаполнитьЗначенияСвойств(Результат, Настройки);
			Если ТипЗнч(Результат.ВебСервисыТаймаутСоединенияСекунд) <> ТипЧисло
					ИЛИ Результат.ВебСервисыТаймаутСоединенияСекунд < 1
					ИЛИ Результат.ВебСервисыТаймаутСоединенияСекунд > 999 Тогда
				Результат.ВебСервисыТаймаутСоединенияСекунд = 30;
			КонецЕсли;
			//
			Если ТипЗнч(Результат.ВебСервисыКоличествоПопытокСоединения) <> ТипЧисло
					ИЛИ Результат.ВебСервисыКоличествоПопытокСоединения < 1
					ИЛИ Результат.ВебСервисыКоличествоПопытокСоединения > 5 Тогда
				Результат.ВебСервисыКоличествоПопытокСоединения = 1;
			КонецЕсли;
			//
			Если ТипЗнч(Результат.HTTPСоединениеТаймаутСоединенияСекунд) <> ТипЧисло
					ИЛИ Результат.HTTPСоединениеТаймаутСоединенияСекунд < 1
					ИЛИ Результат.HTTPСоединениеТаймаутСоединенияСекунд > 999 Тогда
				Результат.HTTPСоединениеТаймаутСоединенияСекунд = 30;
			КонецЕсли;
			//
			Если ТипЗнч(Результат.HTTPСоединениеКоличествоПопытокСоединения) <> ТипЧисло
					ИЛИ Результат.HTTPСоединениеКоличествоПопытокСоединения < 1
					ИЛИ Результат.HTTPСоединениеКоличествоПопытокСоединения > 5 Тогда
				Результат.HTTPСоединениеКоличествоПопытокСоединения = 1;
			КонецЕсли;
			//
			Если ТипЗнч(Результат.HTTPСоединениеКоличествоПопытокПолученияФайла) <> ТипЧисло
					ИЛИ Результат.HTTPСоединениеКоличествоПопытокПолученияФайла < 1
					ИЛИ Результат.HTTPСоединениеКоличествоПопытокПолученияФайла > 5 Тогда
				Результат.HTTPСоединениеКоличествоПопытокПолученияФайла = 1;
			КонецЕсли;
		КонецЕсли;

	ИначеЕсли КлючОбъекта = "НастройкиАвтоудаленияНовостей" Тогда
		// Для этого ключа объекта не действует КлючНастроек.
		// Обязательные поля:
		// - АвтоудалениеНовостей_Актуальные_Месяцев        - Число(3.0), неотрицательное, по-умолчанию 0 (не удалять);
		// - АвтоудалениеНовостей_Неактуальные_Дней         - Число(3.0), неотрицательное, по-умолчанию 30;
		// - АвтоудалениеНовостей_ПомеченныеНаУдаление_Дней - Число(3.0), неотрицательное, по-умолчанию 30;
		// - АвтоудалениеНовостей_СтараяВерсия_Дней         - Число(3.0), неотрицательное, по-умолчанию 30.
		Результат = Новый Структура;
			Результат.Вставить("АвтоудалениеНовостей_Актуальные_Месяцев"       , 0);
			Результат.Вставить("АвтоудалениеНовостей_Неактуальные_Дней"        , 30);
			Результат.Вставить("АвтоудалениеНовостей_ПомеченныеНаУдаление_Дней", 30);
			Результат.Вставить("АвтоудалениеНовостей_СтараяВерсия_Дней"        , 30);

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

	ИначеЕсли КлючОбъекта = "ОтборыПоЛентамНовостейПользовательские" 
			ИЛИ КлючОбъекта = "ОтборыПоЛентамНовостейНастроенныеАдминистратором"
			ИЛИ КлючОбъекта = "ОтборыПоЛентамНовостейДляОбластиДанных" Тогда

		// 1. В Настройках должна передаваться таблица значений с колонками:
		// - ЛентаНовостей (не должно быть пустых значений);
		// - КатегорияНовостей (не должно быть пустых значений);
		// - ЗначениеКатегорииНовостей (могут быть пустые значения).
		// 2. ЗначениеКатегорииНовостей должно быть правильного типа (КатегорияНовостей);
		// 3. Не должно быть повторений, т.е. таблицу в конце обработки надо свернуть;
		// 4. КатегорияНовостей должна быть прописана в табличной части ЛентаНовостей.ДоступныеКатегорииНовостей;
		// 5. Автоматически заполняемая Категория не должна заполняться.

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

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

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

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

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

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

		ПравильнаяТаблица.Свернуть("ЛентаНовостей, КатегорияНовостей, ЗначениеКатегорииНовостей");
		Результат = ПравильнаяТаблица;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	КонецЕсли;

	Возврат Результат;

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

// Проверяет права доступа.
//
// Параметры:
//  ИмяПроцедуры - Имя вызывающей процедуры, для записи в журнал регистрации.
//
// Возвращаемое значение:
//   Булево - Истина, если права есть, Ложь если прав нет.
//
Функция ПроверитьПраваДоступа(ИмяПроцедуры)

	Результат = Истина;

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

	Возврат Результат;

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

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

#КонецЕсли

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