Процедура НайтиБитыеСсылкиВНезависимыхНеПериодическихРегистрахСведений(ОбъектМетаданных, ПараметрыПроверки, ПроверенныеСсылки)

	МаксимальноеКоличество = МаксимальноеКоличествоПроверенныхСсылок();
	ИнформацияОНезависимомРегистре = ИнформацияОНезависимомРегистре(ОбъектМетаданных);
	ПоляВыборки         = ИнформацияОНезависимомРегистре.ПоляВыборки;
	ИнформацияОРегистре = ИнформацияОНезависимомРегистре.ИнформацияОРегистре;

	ИмяТаблицы = СтрЗаменить(ОбъектМетаданных.ПолноеИмя(), ".", "");
	УсловиеПоИзмерениям = "";
	ПоляУпорядочивания  = "";

	ОписаниеИзмерений = ОбъектМетаданных.Измерения;
	Для Каждого Измерение Из ОписаниеИзмерений Цикл
		УсловиеПоИзмерениям = УсловиеПоИзмерениям + ?(ЗначениеЗаполнено(УсловиеПоИзмерениям), " И ", "") + ИмяТаблицы + "." + Измерение.Имя + " >= &" + Измерение.Имя;
		ПоляУпорядочивания  = ПоляУпорядочивания + ?(ЗначениеЗаполнено(ПоляУпорядочивания), ", ", "") + ИмяТаблицы + "." + Измерение.Имя;
	КонецЦикла;

	ТекстЗапроса =
	"ВЫБРАТЬ ПЕРВЫЕ 1000
	|	&ПоляВыборки КАК ПоляВыборки
	|ИЗ
	|	&ОбъектМетаданных КАК ПсевдонимЗаданнойТаблицы
	|ГДЕ
	|	&Условие
	|
	|УПОРЯДОЧИТЬ ПО
	|	&ПоляУпорядочивания";

	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПоляУпорядочивания", ПоляУпорядочивания);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПоляВыборки КАК ПоляВыборки", ПоляВыборки);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ОбъектМетаданных", ОбъектМетаданных.ПолноеИмя());
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПсевдонимЗаданнойТаблицы", ИмяТаблицы);

	ТекстПервогоЗапроса   = СтрЗаменить(ТекстЗапроса, "&Условие", "Истина");
	ТекстЗапросаСУсловием = СтрЗаменить(ТекстЗапроса, "&Условие", УсловиеПоИзмерениям);

	Запрос = Новый Запрос(ТекстПервогоЗапроса);

	Результат       = Запрос.Выполнить().Выгрузить();
	ЭтоПервыйПроход = Истина;

	Пока Результат.Количество() > 0 Цикл

		// Последняя запись уже проверена на предыдущей итерации.
		Если Не ЭтоПервыйПроход И Результат.Количество() = 1 Тогда
			Прервать;
		КонецЕсли;

		Для Каждого СтрокаРезультата Из Результат Цикл

			Если Не ЭтоПервыйПроход И Результат.Индекс(СтрокаРезультата) = 0 Тогда
				Продолжить;
			КонецЕсли;

			Для Каждого ИнформацияОРеквизите Из ИнформацияОРегистре Цикл

				ТекущаяСсылка = СтрокаРезультата[ИнформацияОРеквизите.ИмяМетаданных + ИнформацияОРеквизите.ТипМетаданныхВИменительномПадеже + "Ссылка"];
				Если Не ЭтоБитаяСсылка(ТекущаяСсылка, ПроверенныеСсылки) Тогда
					Продолжить;
				КонецЕсли;

				ДополнительнаяИнформация = Новый Структура;
				Для Каждого Измерение Из ОписаниеИзмерений Цикл
					ИзмерениеСсылка = СтрокаРезультата[Измерение.Имя + "ИзмерениеСсылка"];
					ДополнительнаяИнформация.Вставить(Измерение.Имя, ИзмерениеСсылка);
				КонецЦикла;

				БитаяСсылка = СтрокаРезультата[ИнформацияОРеквизите.ИмяМетаданных + ИнформацияОРеквизите.ТипМетаданныхВИменительномПадеже + "Ссылка"];
				Проблема = ОписаниеПроблемы(ОбщегоНазначения.ИдентификаторОбъектаМетаданных(ОбъектМетаданных), ПараметрыПроверки); // @skip-check query-in-loop - порционная проверка ведения учета
				Проблема.УточнениеПроблемы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'У регистра сведений ""%1"" в %2, по комбинации измерений ""%3"" указана ссылка на несуществующий элемент: ""%4"" (%5).'"),
					ОбъектМетаданных.Представление(), ИнформацияОРеквизите.ТипМетаданныхВТворительномПадеже,
					ПоляУпорядочивания,
					БитаяСсылка,
					ТипЗнч(БитаяСсылка));
				Проблема.ДополнительнаяИнформация = Новый ХранилищеЗначения(ДополнительнаяИнформация);
				ЗаписатьПроблему(Проблема, ПараметрыПроверки); // @skip-check query-in-loop - порционная проверка ведения учета

			КонецЦикла;

		КонецЦикла;

		Если ПроверенныеСсылки.Количество() >= МаксимальноеКоличество Тогда
			ПроверенныеСсылки.Очистить();
		КонецЕсли;

		Если ЭтоПервыйПроход Тогда
			ЭтоПервыйПроход = Ложь;
			Запрос.Текст = ТекстЗапросаСУсловием;
		КонецЕсли;

		Для Каждого Измерение Из ОписаниеИзмерений Цикл
			Запрос.УстановитьПараметр(Измерение.Имя, СтрокаРезультата[Измерение.Имя + "ИзмерениеСсылка"]);
		КонецЦикла;

		Результат = Запрос.Выполнить().Выгрузить(); // @skip-check query-in-loop - порционная проверка ведения учета

	КонецЦикла;

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

// Параметры:
//   ОбъектМетаданных - ОбъектМетаданныхРегистрБухгалтерии
//   ПараметрыПроверки - см. КонтрольВеденияУчета.ОписаниеПроблемы
//   ВидыСубконто - Массив
//   ПроверенныеСсылки - Соответствие
//


Функция ОтменитьПроведениеОбъектаВИБ(Объект, Отправитель, КомпонентыОбмена = Неопределено) Экспорт

	ВремяНачала = ОбменДаннымиОценкаПроизводительности.НачатьЗамер();

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

	// Проверка на коллизии дат запрета загрузки.
	Объект.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения");

	// Параметр "СинхронизацияДанныхЧерезУниверсальныйФорматУдалениеДвижений" используется при
	// обработке удаления движений, например, в модуле набора записей регистра накопления.
	// Если разработчик определил такой параметр в правилах конвертации, пропускаем данный этап.
	Если НЕ Объект.ДополнительныеСвойства.Свойство("СинхронизацияДанныхЧерезУниверсальныйФорматУдалениеДвижений") Тогда

		Объект.ДополнительныеСвойства.Вставить("СинхронизацияДанныхЧерезУниверсальныйФорматУдалениеДвижений", Истина);

	КонецЕсли;

	ПроведениеДокументаОтменено = Ложь;

	НачатьТранзакцию();
	Попытка

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

			ОбменДаннымиСервер.УстановитьОбменДаннымиЗагрузка(Объект, Ложь, Ложь, Отправитель);
			Объект.Записать(РежимЗаписиДокумента.ОтменаПроведения);

			ОбменДаннымиСервер.УстановитьОбменДаннымиЗагрузка(Объект, Истина, Ложь, Отправитель);

		Иначе

			// Устанавливаем режим загрузки данных для объекта.
			ОбменДаннымиСервер.УстановитьОбменДаннымиЗагрузка(Объект, Истина, Ложь, Отправитель);

			// Отменяем проведение документа.
			Объект.Проведен = Ложь;
			Объект.Записать();

			ОбменДаннымиСервер.УдалитьДвиженияУДокумента(Объект);

		КонецЕсли;

		Объект.ДополнительныеСвойства.Удалить("СинхронизацияДанныхЧерезУниверсальныйФорматУдалениеДвижений");

		ПроведениеДокументаОтменено = Истина;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
	КонецПопытки;

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

	Возврат ПроведениеДокументаОтменено;

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

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

Процедура ЗаполнитьТабличнуюЧастьОбъектаНачальнымиДанными(
	ТабличнаяЧастьОбъектаПослеОбработки,
	ТабличнаяЧастьОбъектаДоОбработки,
	Знач КлючевыеПоля = "",
	КолонкиДляВключения = "",
	КолонкиДляИсключения = "") Экспорт

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

	СоответствиеСтарыхИНовыхДанныхТЧ = СоответствиеСтарыхИНовыхДанныхТЧ(
		ТабличнаяЧастьОбъектаПослеОбработки,
		ТабличнаяЧастьОбъектаДоОбработки,
		КлючевыеПоля);

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

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

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

// Возвращает таблицу поддерживаемых в обмене объектов формата для указанного плана обмена.
// Перечень формируется на основании правил обмена из модулей менеджера обмена по соответствующим версиям.
//
// Параметры:
//  ИмяПланаОбмена - Строка - имя плана обмена XDTO.
//  Режим          - Строка - вид запрашиваемой информации: "Отправка" | "Получение" | "ОтправкаПолучение".
//                            "Отправка" - будут возвращены все объекты, для которых поддерживается отправка;
//                            "Получение" - будут возвращены все объекты, для которых поддерживается получение;
//                            "ОтправкаПолучение" - будут возвращены все поддерживаемые объекты.
//                            По умолчанию "ОтправкаПолучение".
//  УзелОбмена     - ПланОбменаСсылка
//                 - Неопределено - узел плана обмена, соответствующий корреспонденту.
//
// Возвращаемое значение:
//  ТаблицаЗначений - состав поддерживаемых объектов формата в разрезе версий:
//    * Версия    - Строка - версия формата, например, "1.5".
//    * Объект    - Строка - имя объекта формата, например, "Справочник.Номенклатура".
//    * Отправка  - Булево - признак поддержки отправки данного объекта формата.
//    * Получение - Булево - признак поддержки получения данного объекта формата.
//


Функция ВыборкаДанных(КомпонентыОбмена, ПравилоОбработки)

	АлгоритмВыборки = ПравилоОбработки.ВыборкаДанных;
	Если ЗначениеЗаполнено(АлгоритмВыборки) Тогда

		МенеджерОбмена = КомпонентыОбмена.МенеджерОбмена;
		СтруктураПараметров = Новый Структура();
		СтруктураПараметров.Вставить("КомпонентыОбмена", КомпонентыОбмена);

		Попытка
			ВыборкаДанных = МенеджерОбмена.ВыполнитьФункциюМодуляМенеджера(ПравилоОбработки.ВыборкаДанных, СтруктураПараметров);
		Исключение

			ШаблонОписанияОшибки = НСтр("ru = 'Событие: %1.
					|Обработчик: %2.
					|ПОД: %3.
					|
					|Ошибка выполнения обработчика.
					|%4.'");

			ТекстОшибки = Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОписанияОшибки,
				КомпонентыОбмена.НаправлениеОбмена,
				"ВыборкаДанных",
				ПравилоОбработки.Имя,
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

			ВызватьИсключение ТекстОшибки;

		КонецПопытки;

	Иначе

		ТекстЗапроса =
		"ВЫБРАТЬ
		|	ПсевдонимТаблицыМетаданных.Ссылка
		|ИЗ
		|	&ИмяТаблицыМетаданных КАК ПсевдонимТаблицыМетаданных";

		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", ПравилоОбработки.ИмяТаблицыДляВыборки);

		Запрос = Новый Запрос(ТекстЗапроса);
		ВыборкаДанных = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

	КонецЕсли;

	Возврат ВыборкаДанных;

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

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

#Область ОбработчикиСобытийПравилКонвертации
// Функция - "обертка" вызова обработчика ПКО ПриОтправкеДанных.
//
// Параметры:
//  ДанныеИБ         - ссылка на выгружаемый объект информационной базы.
//                     Может быть также структура ключевых свойств, если выгружается не объект, а ссылка.
//  ДанныеXDTO       - Структура - в которую выгружаются данные. По составу идентичная объекту XDTO.
//  ИмяОбработчика   - Строка - имя процедуры-обработчика в модуле менеджера.
//  КомпонентыОбмена - Структура - содержит все правила и параметры обмена.
//  СтекВыгрузки     - Массив - содержит ссылки на выгружаемые объекты с учетом вложенности.
//

Процедура ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, Знач ИмяОбработчика, КомпонентыОбмена, СтекВыгрузки)

	МенеджерОбмена = КомпонентыОбмена.МенеджерОбмена;
	СтруктураПараметров = Новый Структура();
	СтруктураПараметров.Вставить("ДанныеИБ", ДанныеИБ);
	СтруктураПараметров.Вставить("ДанныеXDTO", ДанныеXDTO);
	СтруктураПараметров.Вставить("КомпонентыОбмена", КомпонентыОбмена);
	СтруктураПараметров.Вставить("СтекВыгрузки", СтекВыгрузки);

	Попытка

		ВремяНачала = ОбменДаннымиОценкаПроизводительности.НачатьЗамер();

		МенеджерОбмена.ВыполнитьПроцедуруМодуляМенеджера(ИмяОбработчика, СтруктураПараметров);

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

	Исключение

		ШаблонОписанияОшибки = НСтр("ru = 'Событие: %1.
				|Обработчик: %2.
				|Объект: %3.
				|
				|Ошибка выполнения обработчика.
				|%4.'");

		ТекстОшибки = Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОписанияОшибки,
			КомпонентыОбмена.НаправлениеОбмена,
			"ПриОтправкеДанных",
			ПредставлениеОбъектаДляПротокола(ДанныеИБ),
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

		ВызватьИсключение ТекстОшибки;

	КонецПопытки;

	ДанныеXDTO       = СтруктураПараметров.ДанныеXDTO;
	КомпонентыОбмена = СтруктураПараметров.КомпонентыОбмена;
	СтекВыгрузки     = СтруктураПараметров.СтекВыгрузки;

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

// Функция - "обертка" вызова обработчика ПКО ПриКонвертацииДанныхXDTO.
//
// Параметры:
//  ПолученныеДанные - объект информационной базы, в который происходит загрузка данных.
//  ДанныеXDTO       - Структура - из которой загружаются данные. По составу идентичная загружаемому объекту XDTO.
//  КомпонентыОбмена - Структура - содержит все правила и параметры обмена.
//  ИмяОбработчика   - Строка - имя процедуры-обработчика в модуле менеджера.
//

Процедура ПриКонвертацииДанныхXDTO(ДанныеXDTO, ПолученныеДанные, КомпонентыОбмена, Знач ИмяОбработчика)

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

	Попытка

		ВремяНачала = ОбменДаннымиОценкаПроизводительности.НачатьЗамер();

		МенеджерОбмена.ВыполнитьПроцедуруМодуляМенеджера(ИмяОбработчика, СтруктураПараметров);

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

	Исключение

		ШаблонОписанияОшибки = НСтр("ru = 'Событие: %1.
				|Обработчик: %2.
				|Объект: %3.
				|
				|Ошибка выполнения обработчика.
				|%4.'");

		ТекстОшибки = Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОписанияОшибки,
			КомпонентыОбмена.НаправлениеОбмена,
			"ПриКонвертацииДанныхXDTO",
			ПредставлениеОбъектаДляПротокола(ПолученныеДанные),
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

		ВызватьИсключение ТекстОшибки;

	КонецПопытки;

	ДанныеXDTO               = СтруктураПараметров.ДанныеXDTO;
	ПолученныеДанные         = СтруктураПараметров.ПолученныеДанные;
	КомпонентыОбмена         = СтруктураПараметров.КомпонентыОбмена;

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

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

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

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

	Попытка

		ВремяНачала = ОбменДаннымиОценкаПроизводительности.НачатьЗамер();

		МенеджерОбмена.ВыполнитьПроцедуруМодуляМенеджера(ИмяОбработчика, СтруктураПараметров);

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

	Исключение

		ШаблонОписанияОшибки = НСтр("ru = 'Событие: %1.
				|Обработчик: %2.
				|Объект: %3.
				|
				|Ошибка выполнения обработчика.
				|%4.'");

		ТекстОшибки = Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОписанияОшибки,
			КомпонентыОбмена.НаправлениеОбмена,
			"ПередЗаписьюПолученныхДанных",
			ПредставлениеОбъектаДляПротокола(?(ДанныеИБ <> Неопределено, ДанныеИБ, ПолученныеДанные)),
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

		ВызватьИсключение ТекстОшибки;

	КонецПопытки;

	ДанныеИБ                 = СтруктураПараметров.ДанныеИБ;
	ПолученныеДанные         = СтруктураПараметров.ПолученныеДанные;
	КомпонентыОбмена         = СтруктураПараметров.КомпонентыОбмена;
	КонвертацияСвойств       = СтруктураПараметров.КонвертацияСвойств;

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


Процедура ОбновитьВсеОткрытыеДинамическиеСписки() Экспорт

	Типы = ОбменДаннымиВызовСервера.ВсеСсылочныеТипыКонфигурации();

	Для Каждого Тип Из Типы Цикл

		ОповеститьОбИзменении(Тип);

	КонецЦикла;

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

// Регистрирует обработчик для открытия новой формы сразу после закрытия текущей.
//

Процедура ОткрытьФормуПослеЗакрытияТекущей(ТекущаяФорма, Знач ИмяФормы, Знач Параметры = Неопределено, Знач ПараметрыОткрытия = Неопределено) Экспорт

	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("ИмяФормы",          ИмяФормы);
	ДополнительныеПараметры.Вставить("Параметры",         Параметры);
	ДополнительныеПараметры.Вставить("ПараметрыОткрытия", ПараметрыОткрытия);

	ДополнительныеПараметры.Вставить("ПредыдущееОповещениеОЗакрытии",  ТекущаяФорма.ОписаниеОповещенияОЗакрытии);

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

// Отложенное открытие

Процедура ОбработчикОткрытияФормыПослеЗакрытияТекущей(Знач РезультатЗакрытия, Знач ДополнительныеПараметры) Экспорт

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

	Если ДополнительныеПараметры.ПредыдущееОповещениеОЗакрытии <> Неопределено Тогда
		ВыполнитьОбработкуОповещения(ДополнительныеПараметры.ПредыдущееОповещениеОЗакрытии, РезультатЗакрытия);
	КонецЕсли;

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

// Открывает инструкцию по восстановлению/изменению пароля синхронизации данных
// с автономным рабочим местом.
//

Процедура ОткрытьИнструкциюКакИзменитьПарольСинхронизацииДанных(Знач АдресДляВосстановленияПароляУчетнойЗаписи) Экспорт

	Если ПустаяСтрока(АдресДляВосстановленияПароляУчетнойЗаписи) Тогда

		ПоказатьПредупреждение(, НСтр("ru = 'Адрес инструкции для восстановления пароля учетной записи не задан.'"));

	Иначе

		ФайловаяСистемаКлиент.ОткрытьНавигационнуюСсылку(АдресДляВосстановленияПароляУчетнойЗаписи);

	КонецЕсли;

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

////////////////////////////////////////////////////////////////////////////////
// Локальные служебные процедуры и функции.

Процедура ПриЗакрытииФормыНастройкиУзлаПланаОбмена(Форма, ИмяРеквизитаФормы)

	Если Не Форма.ПроверитьЗаполнение() Тогда
		Возврат;
	КонецЕсли;

	Для Каждого НастройкаОтбора Из Форма[ИмяРеквизитаФормы] Цикл

		Если ТипЗнч(Форма[НастройкаОтбора.Ключ]) = Тип("ДанныеФормыКоллекция") Тогда

			СтруктураТабличнойЧасти = Форма[ИмяРеквизитаФормы][НастройкаОтбора.Ключ];

			Для Каждого Элемент Из СтруктураТабличнойЧасти Цикл

				СтруктураТабличнойЧасти[Элемент.Ключ].Очистить();

				Для Каждого СтрокаКоллекции Из Форма[НастройкаОтбора.Ключ] Цикл

					СтруктураТабличнойЧасти[Элемент.Ключ].Добавить(СтрокаКоллекции[Элемент.Ключ]);

				КонецЦикла;

			КонецЦикла;

		Иначе

			Форма[ИмяРеквизитаФормы][НастройкаОтбора.Ключ] = Форма[НастройкаОтбора.Ключ];

		КонецЕсли;

	КонецЦикла;

	Форма.Модифицированность = Ложь;
	Форма.Закрыть(Форма[ИмяРеквизитаФормы]);

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

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// СЛУЖЕБНЫЙ ПРОГРАММНЫЙ ИНТЕРФЕЙС ИНТЕРАКТИВНОГО ДОПОЛНЕНИЯ ВЫГРУЗКИ
//

// Обработка диалогов интерактивного дополнения.
//
// Параметры:
//     ДополнениеВыгрузки           - Структура
//                                  - ДанныеФормыСтруктура - настройки выгрузки.
//     Владелец, Уникальность, Окно - параметры открытия окна формы.
//
// Возвращаемое значение:
//     Открытая форма
//

Функция ОткрытьФормуДополненияВыгрузкиСценарийУзла(Знач ДополнениеВыгрузки, Знач Владелец=Неопределено, Знач Уникальность=Неопределено, Знач Окно=Неопределено) Экспорт

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

	Возврат ОткрытьФорму(ДополнениеВыгрузки.ПараметрыСценарияДополнения.ВариантДополнительно.ИмяФормыОтбора,
		ПараметрыФормы, Владелец, Уникальность, Окно);
КонецФункции

// Обработка диалогов интерактивного дополнения.
//
// Параметры:
//     ДополнениеВыгрузки           - Структура
//                                  - ДанныеФормыСтруктура - настройки выгрузки.
//     Владелец, Уникальность, Окно - параметры открытия окна формы.
//
// Возвращаемое значение:
//     Открытая форма
//

Функция ОткрытьФормуДополненияВыгрузкиВсеДокументы(Знач ДополнениеВыгрузки, Знач Владелец=Неопределено, Знач Уникальность=Неопределено, Знач Окно=Неопределено) Экспорт
	ПараметрыФормы = Новый Структура;

	ПараметрыФормы.Вставить("Заголовок", НСтр("ru = 'Добавление документов для отправки'") );
	ПараметрыФормы.Вставить("ДействиеВыбора", 1);

	ПараметрыФормы.Вставить("ВыборПериода", Истина);
	ПараметрыФормы.Вставить("ПериодДанных", ДополнениеВыгрузки.ПериодОтбораВсехДокументов);

	ПараметрыФормы.Вставить("АдресКомпоновщикаНастроек", ДополнениеВыгрузки.АдресКомпоновщикаВсехДокументов);

	ПараметрыФормы.Вставить("АдресХранилищаФормы", ДополнениеВыгрузки.АдресХранилищаФормы);

	Возврат ОткрытьФорму("Обработка.ИнтерактивноеИзменениеВыгрузки.Форма.РедактированиеПериодаИОтбора",
		ПараметрыФормы, Владелец, Уникальность, Окно);
КонецФункции

// Обработка диалогов интерактивного дополнения.
//
// Параметры:
//     ДополнениеВыгрузки           - Структура
//                                  - ДанныеФормыСтруктура - настройки выгрузки.
//     Владелец, Уникальность, Окно - параметры открытия окна формы.
//
// Возвращаемое значение:
//     Открытая форма
//

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

	ПараметрыФормы.Вставить("ДействиеВыбора", 2);
	ПараметрыФормы.Вставить("НастройкиОбъекта", ДополнениеВыгрузки);

	ПараметрыФормы.Вставить("ОткрытаПоСценарию", Истина);
	Возврат ОткрытьФорму("Обработка.ИнтерактивноеИзменениеВыгрузки.Форма",
		ПараметрыФормы, Владелец, Уникальность, Окно);
КонецФункции

// Обработка диалогов интерактивного дополнения.
//
// Параметры:
//     ДополнениеВыгрузки           - Структура
//                                  - ДанныеФормыСтруктура - настройки выгрузки.
//     Владелец, Уникальность, Окно - параметры открытия окна формы.
//
// Возвращаемое значение:
//     Открытая форма
//

Функция ОткрытьФормуДополненияВыгрузкиСоставДанных(Знач ДополнениеВыгрузки, Знач Владелец=Неопределено, Знач Уникальность=Неопределено, Знач Окно=Неопределено) Экспорт
	ПараметрыФормы = Новый Структура;

	ПараметрыФормы.Вставить("НастройкиОбъекта", ДополнениеВыгрузки);
	Если ДополнениеВыгрузки.ВариантВыгрузки=3 Тогда
		ПараметрыФормы.Вставить("УпрощенныйРежим", Истина);
	КонецЕсли;

	Возврат ОткрытьФорму("Обработка.ИнтерактивноеИзменениеВыгрузки.Форма.СоставВыгрузки",
		ПараметрыФормы, Владелец, Уникальность, Окно);
КонецФункции

// Обработка диалогов интерактивного дополнения.
//
// Параметры:
//     ДополнениеВыгрузки           - Структура
//                                  - ДанныеФормыСтруктура - настройки выгрузки.
//     Владелец, Уникальность, Окно - параметры открытия окна формы.
//
// Возвращаемое значение:
//     Открытая форма
//


Функция ПравилаДляПланаОбменаИзКонфигурации(ИмяПланаОбмена, ЛитералИмениМакета)

	СписокПравил = Новый СписокЗначений;

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

	Для Каждого Макет Из Метаданные.ПланыОбмена[ИмяПланаОбмена].Макеты Цикл

		Если СтрНайти(Макет.Имя, ЛитералИмениМакета) <> 0 И СтрНайти(Макет.Имя, "Корреспондента") = 0 Тогда

			СписокПравил.Добавить(Макет.Имя, Макет.Синоним);

		КонецЕсли;

	КонецЦикла;

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

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

Функция СоставПланаОбмена(ИмяПланаОбмена, Периодические = Истина, Справочные = Истина) Экспорт

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

	СоставПланаОбмена = Метаданные.ПланыОбмена.Найти(ИмяПланаОбмена).Состав;
	Для Каждого ЭлементСостава Из СоставПланаОбмена Цикл

		МетаданныеОбъекта = ЭлементСостава.Метаданные;
		Описание = ОписаниеОбъектаМетаданных(МетаданныеОбъекта);
		Если Описание.ИндексКартинки >= 0 Тогда
			Если Не Периодические И Описание.Периодический Тогда
				Продолжить;
			ИначеЕсли Не Справочные И Описание.Справочный Тогда
				Продолжить;
			КонецЕсли;

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

	ТаблицаРезультата.Сортировать("ПредставлениеСписка");
	Возврат ТаблицаРезультата;

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

// Возвращает описание объекта метаданных.
//
// Параметры:
//   Мета - ОбъектМетаданных - объект метаданных.
//
// Возвращаемое значение:
//   Структура:
//     * ИндексКартинки - Число - индекс картинки.
//     * Периодический - Булево - Истина, если объект периодический.
//     * Справочный - Булево - Истина, если объект справочный.
//     * Тип - Тип - ссылочный тип значения.
//

Функция ОписаниеОбъектаМетаданных(Мета)

	Результат = Новый Структура("ИндексКартинки, Периодический, Справочный, Тип", -1, Ложь, Ложь);

	Если Метаданные.Справочники.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 3;
		Результат.Справочный = Истина;
		Результат.Тип = Тип("СправочникСсылка." + Мета.Имя);

	ИначеЕсли Метаданные.Документы.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 7;
		Результат.Периодический = Истина;
		Результат.Тип = Тип("ДокументСсылка." + Мета.Имя);

	ИначеЕсли Метаданные.ПланыВидовХарактеристик.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 9;
		Результат.Справочный = Истина;
		Результат.Тип = Тип("ПланВидовХарактеристикСсылка." + Мета.Имя);

	ИначеЕсли Метаданные.ПланыСчетов.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 11;
		Результат.Справочный = Истина;
		Результат.Тип = Тип("ПланСчетовСсылка." + Мета.Имя);

	ИначеЕсли Метаданные.ПланыВидовРасчета.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 13;
		Результат.Справочный = Истина;
		Результат.Тип = Тип("ПланВидовРасчетаСсылка." + Мета.Имя);

	ИначеЕсли Метаданные.БизнесПроцессы.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 23;
		Результат.Периодический = Истина;
		Результат.Тип = Тип("БизнесПроцессСсылка." + Мета.Имя);

	ИначеЕсли Метаданные.Задачи.Содержит(Мета) Тогда
		Результат.ИндексКартинки = 25;
		Результат.Периодический  = Истина;
		Результат.Тип = Тип("ЗадачаСсылка." + Мета.Имя);

	КонецЕсли;

	Возврат Результат;
КонецФункции

// Функция возвращает имя каталога временных файлов.
//
// Возвращаемое значение:
//  Строка - путь к каталогу временных файлов.
//

Функция КаталогВременногоХранилищаФайлов(БезопасныйРежим = Неопределено) Экспорт

	Если ОбщегоНазначения.ИнформационнаяБазаФайловая() И НЕ ОбщегоНазначения.РежимОтладки() Тогда

		Возврат СокрЛП(КаталогВременныхФайлов());

	КонецЕсли;

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

	ОбщийТипПлатформы = "";
	Если ОбщегоНазначения.ЭтоLinuxСервер() Тогда

		Результат         = Константы.КаталогСообщенийОбменаДаннымиДляLinux.Получить();
		ОбщийТипПлатформы = "Linux";

	Иначе

		Результат         = Константы.КаталогСообщенийОбменаДаннымиДляWindows.Получить();
		ОбщийТипПлатформы = "Windows";

	КонецЕсли;

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

	Если ПустаяСтрока(Результат) Тогда

		Результат = СокрЛП(КаталогВременныхФайлов());

	Иначе

		Результат = СокрЛП(Результат);

		// Проверка существования каталога.
		Каталог = Новый Файл(Результат);
		Если Не Каталог.Существует() Тогда

			ПредставлениеКонстанты = ?(ОбщийТипПлатформы = "Linux",
				Метаданные.Константы.КаталогСообщенийОбменаДаннымиДляLinux.Представление(),
				Метаданные.Константы.КаталогСообщенийОбменаДаннымиДляWindows.Представление());

			ШаблонСообщения = НСтр("ru = 'Каталог временных файлов не существует.
					|Необходимо убедиться, что в настройках программы задано правильное значение параметра
					|""%1"".'", ОбщегоНазначения.КодОсновногоЯзыка());

			ТекстСообщения = СтрШаблон(ШаблонСообщения, ПредставлениеКонстанты);
			ВызватьИсключение(ТекстСообщения);

		КонецЕсли;

	КонецЕсли;

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

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

// Инициализирует колонки таблицы правил регистрации по свойствам.
//
//  Возвращаемое значение:
//    ДеревоЗначений
//

Функция ИнициализацияТаблицыОтборПоСвойствамПланаОбмена() Экспорт

	Обработка = Обработки.ЗагрузкаПравилРегистрацииОбъектов;
	Возврат Обработка.ИнициализацияТаблицыОтборПоСвойствамПланаОбмена();

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

// Инициализирует колонки таблицы правил регистрации по свойствам.
//
//  Возвращаемое значение:
//    ДеревоЗначений
//

Функция ИнициализацияТаблицыОтборПоСвойствамОбъекта() Экспорт

	Обработка = Обработки.ЗагрузкаПравилРегистрацииОбъектов;
	Возврат Обработка.ИнициализацияТаблицыОтборПоСвойствамОбъекта();

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

Функция ЭтоРегистр(ПолноеИмяОбъекта) Экспорт

	ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
	Возврат ОбщегоНазначения.ЭтоРегистр(ОбъектМетаданных);

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

Функция ЭтоДокумент(ПолноеИмяОбъекта) Экспорт

	ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
	Возврат ОбщегоНазначения.ЭтоДокумент(ОбъектМетаданных);

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

Функция ЭтоСправочник(ПолноеИмяОбъекта) Экспорт

	ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
	Возврат ОбщегоНазначения.ЭтоСправочник(ОбъектМетаданных);

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

Функция ЭтоПеречисление(ПолноеИмяОбъекта) Экспорт

	ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъекта);
	Возврат ОбщегоНазначения.ЭтоПеречисление(ОбъектМетаданных);

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


Функция КоличествоПроблемОбменаДанными(УзлыОбмена = Неопределено)

	ПараметрыПоискаПроблем = РегистрыСведений.РезультатыОбменаДанными.ПараметрыПоискаПроблем();
	ПараметрыПоискаПроблем.УзлыПланаОбмена = УзлыОбмена;

	ТипыПроблем = Новый Массив;
	ТипыПроблем.Добавить(Перечисления.ТипыПроблемОбменаДанными.НезаполненныеРеквизиты);
	ТипыПроблем.Добавить(Перечисления.ТипыПроблемОбменаДанными.НепроведенныйДокумент);
	ТипыПроблем.Добавить(Перечисления.ТипыПроблемОбменаДанными.ОшибкаПроверкиСконвертированногоОбъекта);

	ПараметрыПоискаПроблем.ТипПроблемы = ТипыПроблем;

	Возврат РегистрыСведений.РезультатыОбменаДанными.КоличествоПроблем(ПараметрыПоискаПроблем);

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

Функция КоличествоПроблемВерсионирования(УзлыОбмена = Неопределено, Знач ПараметрыЗапроса = Неопределено) Экспорт

	Если ПараметрыЗапроса = Неопределено Тогда
		ПараметрыЗапроса = ПараметрыЗапросаКоличествоПроблемВерсионирования();
	КонецЕсли;

	ИспользуетсяВерсионирование = ОбменДаннымиПовтИсп.ИспользуетсяВерсионирование(, Истина);

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

	Возврат 0;

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

Функция ПараметрыЗапросаКоличествоПроблемВерсионирования() Экспорт

	Результат = Новый Структура;

	Результат.Вставить("ЭтоКоличествоКоллизий",      Неопределено);
	Результат.Вставить("УчитыватьПроигнорированные", Ложь);
	Результат.Вставить("Период",                     Неопределено);
	Результат.Вставить("СтрокаПоиска",               "");

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

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

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

Процедура ЗарегистрироватьОшибкуПроведенияДокумента(
		Объект,
		УзелОбмена,
		ТекстИсключения,
		РегистрироватьПроблемыВРезультатахОбмена = Истина)

	СообщенияПользователю = ПолучитьСообщенияПользователю(Истина);
	ТекстСообщения = ТекстИсключения;
	Для Каждого Сообщение Из СообщенияПользователю Цикл

		Если СтрНайти(Сообщение.Текст, "СтандартныеПодсистемы.ДлительныеОперации") > 0 Тогда

			Продолжить;

		КонецЕсли;

		ТекстСообщения = ТекстСообщения + ?(ПустаяСтрока(ТекстСообщения), "", Символы.ПС) + Сообщение.Текст;

	КонецЦикла;
	ТекстСообщения = СокрЛП(ТекстСообщения);

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

	ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииОбменДанными(), УровеньЖурналаРегистрации.Предупреждение,,, СтрокаСообщения);

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

			СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения,
				Строка(Объект), ОписаниеОшибки);

			ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииОбменДанными(), УровеньЖурналаРегистрации.Ошибка,,, СтрокаСообщения);
		КонецПопытки
	КонецЕсли;

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

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


Функция РаспаковатьZipФайл(Знач ПолноеИмяФайлаАрхива, Знач ПутьРаспаковкиФайлов, Знач ПарольАрхива = "") Экспорт

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

	Архиватор = Неопределено;
	Попытка
		Архиватор = Новый ЧтениеZipФайла(ПолноеИмяФайлаАрхива, ПарольАрхива);
		Архиватор.ИзвлечьВсе(ПутьРаспаковкиФайлов, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
	Исключение
		ИнформацияОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Ошибка при распаковке файлов архива ""%1"" в каталог ""%2"" по причине:
			|%3'"),
			ПолноеИмяФайлаАрхива,
			ПутьРаспаковкиФайлов,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииОбменДанными(),
			УровеньЖурналаРегистрации.Ошибка, , , ИнформацияОбОшибке);

		Результат = Ложь;
	КонецПопытки;

	Если Архиватор <> Неопределено Тогда
		Архиватор.Закрыть();
	КонецЕсли;

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

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

// Запаковывает указанный каталог в файл архива ZIP.
//
// Параметры:
//  ПолноеИмяФайлаАрхива  - Строка - имя файла архива, в который необходимо запаковать.
//  МаскаУпаковкиФайлов    - Строка - имя файла, помещаемого в архив, или маска.
//			Недопустимо использование в именах файлов и папок букв национальных алфавитов, которые при
//			преобразовании из символов UNICODE в узкие символы могут быть преобразованы с потерей информации.
//			Рекомендуется использовать в именах файлов и папок символы латинского алфавита.
//  ПарольАрхива          - Строка - пароль для архива. По умолчанию пустая строка.
//
// Возвращаемое значение:
//  Результат - Булево - Истина, если успешно, Ложь, если нет.
//

Функция ЗапаковатьВZipФайл(Знач ПолноеИмяФайлаАрхива, Знач МаскаУпаковкиФайлов, Знач ПарольАрхива = "") Экспорт

	// Возвращаемое значение функции.
	Результат = Истина;

	Попытка

		Архиватор = Новый ЗаписьZipФайла(ПолноеИмяФайлаАрхива, ПарольАрхива);

	Исключение
		Архиватор = Неопределено;
		СообщитьОбОшибке(ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
		Возврат Ложь;
	КонецПопытки;

	Попытка

		Архиватор.Добавить(МаскаУпаковкиФайлов, РежимСохраненияПутейZIP.НеСохранятьПути);
		Архиватор.Записать();

	Исключение
		ИнформацияОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Ошибка при запаковке файлов ""%1"" в архив ""%2"" по причине:
			|%3'"),
			МаскаУпаковкиФайлов,
			ПолноеИмяФайлаАрхива,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));

		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииОбменДанными(),
			УровеньЖурналаРегистрации.Ошибка, , , ИнформацияОбОшибке);

		Результат = Ложь;
	КонецПопытки;

	Архиватор = Неопределено;

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

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

// Возвращает количество записей в таблице базы данных.
//
// Параметры:
//  ИмяТаблицы - Строка - полное имя таблицы базы данных. Например: "Справочник.Контрагенты.Заказы".
//
// Возвращаемое значение:
//  Число - количество записей в таблице базы данных.
//

Функция КоличествоЗаписейВТаблицеБазыДанных(Знач ИмяТаблицы) Экспорт

	ТекстЗапроса = "
	|ВЫБРАТЬ
	|	Количество(*) КАК Количество
	|ИЗ
	|	#ИмяТаблицы
	|";

	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяТаблицы", ИмяТаблицы);

	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;

	Выборка = Запрос.Выполнить().Выбрать();
	Выборка.Следующий();

	Возврат Выборка["Количество"];

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

// Возвращает количество записей во временной таблице базы данных.
//
// Параметры:
//  ИмяТаблицы - Строка - имя таблицы. Например: "ВременнаяТаблица1".
//  МенеджерВременныхТаблиц - менеджер временных таблиц, который содержит указатель на временную таблицу ИмяТаблицы.
//
// Возвращаемое значение:
//  Число - количество записей в таблице базы данных.
//

Функция КоличествоЗаписейВоВременнойТаблицеБазыДанных(Знач ИмяТаблицы, МенеджерВременныхТаблиц) Экспорт

	ТекстЗапроса = "
	|ВЫБРАТЬ
	|	Количество(*) КАК Количество
	|ИЗ
	|	#ИмяТаблицы
	|";

	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяТаблицы", ИмяТаблицы);

	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;

	Выборка = Запрос.Выполнить().Выбрать();
	Выборка.Следующий();

	Возврат Выборка["Количество"];

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

// Возвращает ключ сообщения журнала регистрации.
//

Функция КлючСообщенияЖурналаРегистрации(УзелИнформационнойБазы, ДействиеПриОбмене) Экспорт

	ИмяПланаОбмена     = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(УзелИнформационнойБазы);

	КлючСообщения = НСтр("ru = 'Обмен данными.[ИмяПланаОбмена].[ДействиеПриОбмене]'",
		ОбщегоНазначения.КодОсновногоЯзыка());

	КлючСообщения = СтрЗаменить(КлючСообщения, "[ИмяПланаОбмена]",    ИмяПланаОбмена);
	КлючСообщения = СтрЗаменить(КлючСообщения, "[ДействиеПриОбмене]", ДействиеПриОбмене);

	Возврат КлючСообщения;

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

// Возвращает признак того, что реквизит входит в подмножество стандартных реквизитов.
//
// Параметры:
//   СтандартныеРеквизиты - ОписанияСтандартныхРеквизитов - коллекция стандартных реквизитов.
//   ИмяРеквизита - Строка - имя проверяемого реквизита.
//
// Возвращаемое значение:
//   Булево - Истина, если заданный реквизит является стандартным.
//

Функция ЭтоСтандартныйРеквизит(СтандартныеРеквизиты, ИмяРеквизита) Экспорт

	Для Каждого Реквизит Из СтандартныеРеквизиты Цикл

		Если Реквизит.Имя = ИмяРеквизита Тогда

			Возврат Истина;

		КонецЕсли;

	КонецЦикла;

	Возврат Ложь;

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

// Формирует и возвращает ключ таблицы данных.
// Ключ таблицы используется для выборочной загрузки данных из сообщения обмена по заданному ключу.
//

Функция КлючТаблицыДанных(Знач ТипИсточника, Знач ТипПриемника, Знач ЭтоУдалениеОбъекта) Экспорт

	Возврат ТипИсточника + "#" + ТипПриемника + "#" + Строка(ЭтоУдалениеОбъекта);

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

Функция НадоВыполнитьОбработчик(Объект, Ссылка, ИмяСвойства)

	НомерПослеОбработки = Объект[ИмяСвойства];

	НомерПередОбработкой = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, ИмяСвойства);

	НомерПередОбработкой = ?(НомерПередОбработкой = Неопределено, 0, НомерПередОбработкой);

	Возврат НомерПередОбработкой <> НомерПослеОбработки;

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

Функция ЗаполнитьПараметрыПодключенияВнешнегоСоединения(НастройкиТранспорта)

	ПараметрыПодключения = ОбщегоНазначенияКлиентСервер.СтруктураПараметровДляУстановкиВнешнегоСоединения();

	ПараметрыПодключения.ВариантРаботыИнформационнойБазы             = НастройкиТранспорта.COMВариантРаботыИнформационнойБазы;
	ПараметрыПодключения.КаталогИнформационнойБазы                   = НастройкиТранспорта.COMКаталогИнформационнойБазы;
	ПараметрыПодключения.ИмяСервера1СПредприятия                     = НастройкиТранспорта.COMИмяСервера1СПредприятия;
	ПараметрыПодключения.ИмяИнформационнойБазыНаСервере1СПредприятия = НастройкиТранспорта.COMИмяИнформационнойБазыНаСервере1СПредприятия;
	ПараметрыПодключения.АутентификацияОперационнойСистемы           = НастройкиТранспорта.COMАутентификацияОперационнойСистемы;
	ПараметрыПодключения.ИмяПользователя                             = НастройкиТранспорта.COMИмяПользователя;
	ПараметрыПодключения.ПарольПользователя                          = НастройкиТранспорта.COMПарольПользователя;

	Возврат ПараметрыПодключения;
КонецФункции

Функция ДобавитьЛитералКИмениФайла(Знач ПолноеИмяФайла, Знач Литерал)

	Если ПустаяСтрока(ПолноеИмяФайла) Тогда
		Возврат "";
	КонецЕсли;

	ИмяФайлаБезРасширения = Сред(ПолноеИмяФайла, 1, СтрДлина(ПолноеИмяФайла) - 4);

	Расширение = Прав(ПолноеИмяФайла, 3);

	Результат = "[ИмяФайлаБезРасширения]_[Литерал].[Расширение]";

	Результат = СтрЗаменить(Результат, "[ИмяФайлаБезРасширения]", ИмяФайлаБезРасширения);
	Результат = СтрЗаменить(Результат, "[Литерал]",               Литерал);
	Результат = СтрЗаменить(Результат, "[Расширение]",            Расширение);

	Возврат Результат;
КонецФункции

Функция НаименованиеПредопределенногоУзлаПланаОбмена(ИмяПланаОбмена) Экспорт

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

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


Процедура ВыполнитьОбработчикПРОПриОбработке(Отказ, ПРО, Объект, ДополнительныеПараметры)

	ТекстЗапроса = ДополнительныеПараметры.ТекстЗапроса;
	ПараметрыЗапроса = ДополнительныеПараметры.ПараметрыЗапроса;
	ИспользоватьКэш = ДополнительныеПараметры.ИспользоватьКэш;
	Выгрузка = ДополнительныеПараметры.Выгрузка;
	ДополнительныеСвойства = ДополнительныеПараметры.ДополнительныеСвойства;

	Если ПРО.ЕстьОбработчикПриОбработке Тогда

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

	КонецЕсли;

	ДополнительныеПараметры.ТекстЗапроса = ТекстЗапроса;
	ДополнительныеПараметры.ПараметрыЗапроса = ПараметрыЗапроса;
	ДополнительныеПараметры.ИспользоватьКэш = ИспользоватьКэш;

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

Процедура ВыполнитьОбработчикПРОПриОбработкеДополнительный(Отказ, ПРО, Объект, ТекстЗапроса, ПараметрыЗапроса, ИспользоватьКэш, ДополнительныеСвойства = Неопределено)

	Если ПРО.ЕстьОбработчикПриОбработкеДополнительный Тогда

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

	КонецЕсли;

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

Процедура ВыполнитьОбработчикПРОПослеОбработки(ПРО, Отказ, Объект, ОбъектМетаданных, Получатели, Знач Выгрузка)

	Если ПРО.ЕстьОбработчикПослеОбработки Тогда

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

	КонецЕсли;

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

Функция ПараметрыПакетнойРегистрации() Экспорт

	Параметры = Новый Структура;
	Параметры.Вставить("ЕстьПРО_СПакетнойРегистрацией", Ложь);
	Параметры.Вставить("ЕстьПРО_БезПакетнойРегистрации",Ложь);
	Параметры.Вставить("СсылкиПоФильтруПакетнойРегистрации", Новый Массив);
	Параметры.Вставить("СсылкиНеПоФильтруПакетнойРегистрации", Новый Массив);
	Параметры.Вставить("СозданиеНачальногоОбраза", Ложь);

	Возврат Параметры;

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

Процедура ВыполнитьПакетнуюРегистрациюДляУзла(Узел, МассивСсылок, Параметры) Экспорт

	Если МассивСсылок.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	ИмяПланаОбмена = ОбменДаннымиПовтИсп.ПолучитьИмяПланаОбмена(Узел);
	ПолноеИмяОбъекта = МассивСсылок[0].Метаданные().ПолноеИмя();

	РежимВыгрузкиОбъекта = ОбменДаннымиПовтИсп.РежимВыгрузкиОбъекта(ПолноеИмяОбъекта, Узел);

	Если РежимВыгрузкиОбъекта = Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьВсегда Тогда

		Параметры.СсылкиПоФильтруПакетнойРегистрации = МассивСсылок;

	Иначе

		Правила = ПравилаРегистрацииОбъекта(ИмяПланаОбмена, ПолноеИмяОбъекта);

		Для Каждого ПРО Из Правила Цикл
			Если ПРО.ПакетноеВыполнениеОбработчиков Тогда

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

				Параметры.ЕстьПРО_СПакетнойРегистрацией = Истина;

			Иначе

				Параметры.ЕстьПРО_БезПакетнойРегистрации = Истина;

			КонецЕсли;
		КонецЦикла;

		Если Не Параметры.ЕстьПРО_СПакетнойРегистрацией Тогда

			Параметры.СсылкиНеПоФильтруПакетнойРегистрации = МассивСсылок;

		ИначеЕсли МассивСсылок.Количество() <> Параметры.СсылкиПоФильтруПакетнойРегистрации.Количество() Тогда

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

		КонецЕсли;

	КонецЕсли;

	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗащитаПерсональныхДанных") Тогда
		МодульЗащитаПерсональныхДанных = ОбщегоНазначения.ОбщийМодуль("ЗащитаПерсональныхДанных");

		Количество = Параметры.СсылкиПоФильтруПакетнойРегистрации.Количество();
		Для Сч = 1 По Количество Цикл

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

			Если ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать Тогда
				Параметры.СсылкиПоФильтруПакетнойРегистрации.Удалить(Индекс);
			КонецЕсли;

		КонецЦикла;

	КонецЕсли;

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

Процедура ВыполнитьПакетнуюРегистрациюДляУзлаПопыткаИсключение(ПРО, МассивСсылок, Узел)

	РежимВыгрузки = Узел[ПРО.ИмяРеквизитаФлага];

	Если РежимВыгрузки <> Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьПоУсловию
		И РежимВыгрузки <> Перечисления.РежимыВыгрузкиОбъектовОбмена.ВыгружатьВручную
		И РежимВыгрузки <> Перечисления.РежимыВыгрузкиОбъектовОбмена.ПустаяСсылка() Тогда

		МассивСсылок = Новый Массив;
		Возврат;

	КонецЕсли;

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

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

		ВызватьИсключение ПодробноеПредставлениеОшибкиВыполненияОбработчика(
			"ПакетнаяОбработка",
			ПРО.ИмяПланаОбмена,
			ПРО.ОбъектМетаданныхИмя,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;

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

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

#Область ВспомогательныеПроцедурыИФункции

Функция ПодробноеПредставлениеОшибкиВыполненияОбработчика(ИмяОбработчика, ИмяПланаОбмена, ИмяОбъектаМетаданных, ПредставлениеОшибки)

	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Ошибка при выполнении обработчика: ""%1"";
		|План обмена: %2;
		|Объект метаданных: %3;
		|Описание ошибки: %4.'"),
		ИмяОбработчика,
		ИмяПланаОбмена,
		ИмяОбъектаМетаданных,
		ПредставлениеОшибки);

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


Процедура НачальноеЗаполнениеТЧПредставления(ЗаполняемыйЭлемент, СтрокаТаблицы, ПараметрыЗаполнения) Экспорт

	Языки = СтандартныеПодсистемыСервер.ЯзыкиКонфигурации();
	ЛокализуемыеРеквизитыОбъекта = ПараметрыЗаполнения.ЛокализуемыеРеквизитыОбъекта;

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

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

Функция НаборПараметровДляЗаполненияОбъекта(МетаданныеОбъекта) Экспорт

	Результат = Новый Структура;

	ОбъектыСНачальнымЗаполнением = ОбъектыСНачальнымЗаполнением();
	ЕстьПредопределенныеДанные =  ОбъектыСНачальнымЗаполнением.Найти(МетаданныеОбъекта) <> Неопределено;

	ЛокализуемыеРеквизитыОбъекта = Новый Соответствие;
	МультиязычныеСтрокиВРеквизитах = Ложь;
	ОбъектСодержитТЧПредставления  = Ложь;

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

	МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(МетаданныеОбъекта.ПолноеИмя());

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

	ТабличныеЧасти = Новый Массив;
	ОбъектМетаданныхТабличныеЧасти = МетаданныеОбъекта.ТабличныеЧасти; // КоллекцияОбъектовМетаданных из ОбъектМетаданныхТабличнаяЧасть
	Для Каждого ТабличнаяЧасть Из ОбъектМетаданныхТабличныеЧасти Цикл
		Если ПредопределенныеДанные.Колонки.Найти(ТабличнаяЧасть.Имя) <> Неопределено Тогда
			ТабличныеЧасти.Добавить(ТабличнаяЧасть.Имя);
		КонецЕсли;
	КонецЦикла;

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

	ТЧПредставленияИспользуетсяДляГрупп = Ложь;
	Если ОбъектСодержитТЧПредставления И ПоддерживаетсяИерархия Тогда

		Если МетаданныеОбъекта.ТабличныеЧасти.Представления.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппыИЭлемента
			Или МетаданныеОбъекта.ТабличныеЧасти.Представления.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппы Тогда
			ТЧПредставленияИспользуетсяДляГрупп = Истина;
		КонецЕсли;

	КонецЕсли;

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

	Результат.Вставить("НастройкиПредопределенныхЭлементов", НастройкиПредопределенныхЭлементов);
	Результат.Вставить("ПредопределенныеДанные", ПредопределенныеДанные);
	Результат.Вставить("РеквизитыИсключения", РеквизитыИсключения);
	Результат.Вставить("ПоддерживаетсяИерархия", ПоддерживаетсяИерархия);
	Результат.Вставить("ТабличныеЧасти", ТабличныеЧасти);
	Результат.Вставить("ЛокализуемыеРеквизитыОбъекта", ЛокализуемыеРеквизитыОбъекта);
	Результат.Вставить("МультиязычныеСтрокиВРеквизитах", МультиязычныеСтрокиВРеквизитах);
	Результат.Вставить("ОбъектСодержитТЧПредставления", ОбъектСодержитТЧПредставления);
	Результат.Вставить("ТЧПредставленияИспользуетсяДляГрупп", ТЧПредставленияИспользуетсяДляГрупп);
	Результат.Вставить("МенеджерОбъекта", МенеджерОбъекта);
	Результат.Вставить("РеквизитыСЭлементами", РеквизитыСЭлементами);

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

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

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

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

Функция ОпределитьДанныеЗаполнения(Знач ПредопределенныеДанные, Знач СтрокаТаблицы, Знач ПоляИсключения)

	ДанныеЗаполнения = Новый Структура;
	Для Каждого Колонка Из ПредопределенныеДанные.Колонки Цикл

		ИмяПоля = Колонка.Имя;
		Если ПоляИсключения[ИмяПоля] = Истина Тогда
			Продолжить;
		КонецЕсли;

		Значение = СтрокаТаблицы[ИмяПоля];
		Если Колонка.ТипЗначения.Типы().Количество() > 1 Тогда
			Заполнено = Значение <> Неопределено;
		ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
			Заполнено = Значение;
		Иначе
			Заполнено = ЗначениеЗаполнено(Значение);
		КонецЕсли;

		Если Заполнено Тогда
			ДанныеЗаполнения.Вставить(ИмяПоля, Значение);
		КонецЕсли;
	КонецЦикла;

	Возврат ДанныеЗаполнения;

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


Функция ЗначениеРеквизитаОбъектов(МассивСсылок, ИмяРеквизита, ВыбратьРазрешенные = Ложь, Знач КодЯзыка = Неопределено) Экспорт

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

	ЗначенияРеквизитов = ЗначенияРеквизитовОбъектов(МассивСсылок, ИмяРеквизита, ВыбратьРазрешенные, КодЯзыка);
	Для каждого Элемент Из ЗначенияРеквизитов Цикл
		ЗначенияРеквизитов[Элемент.Ключ] = Элемент.Значение[ИмяРеквизита];
	КонецЦикла;

	Возврат ЗначенияРеквизитов;

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

// Добавляет или изменяет значение реквизита в объекте.
//
// Если передано имя несуществующего реквизита, то вызывается исключение.
//
// Параметры:
//  Объект - СправочникОбъект
//         - ДокументОбъект
//         - ПланВидовХарактеристикОбъект
//         - РегистрСведенийЗапись - заполняемый объект.
//  ИмяРеквизита - Строка - имя заполняемого реквизита. Например, "Комментарий"
//  Значение - Строка - значение помещаемое в реквизит.
//  КодЯзыка - Строка - код языка реквизита. Например, "ru".
//

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

// Добавляет или изменяет значения реквизитов в объекте.
//
// Если передано имя несуществующего реквизита, то вызывается исключение.
//
// Параметры:
//  Объект - СправочникОбъект
//         - ДокументОбъект
//         - ПланВидовХарактеристикОбъект
//         - РегистрСведенийЗапись - заполняемый объект.
//  Значения - Структура - где ключ это имя реквизита, а значение содержит строку помещаемую в реквизит.
//  КодЯзыка - Строка - код языка реквизита. Например, "ru".
//

Процедура УстановитьЗначенияРеквизитов(Объект, Значения, КодЯзыка = Неопределено) Экспорт

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

	Для Каждого ЗначениеРеквизита Из Значения Цикл
		Значение = ЗначениеРеквизита.Значение;
		Если ТипЗнч(Значение) = Тип("Строка") И СтрокаВВидеНСтр(Значение) Тогда
			Значение = НСтр(ЗначениеРеквизита.Значение);
		КонецЕсли;
		Объект[ЗначениеРеквизита.Ключ] = Значение;
	КонецЦикла;

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

// Возвращает код основного языка информационной базы, например "ru".
// На котором программно записываются автогенерируемые строки в информационную базу.
// Например, при начальном заполнении информационной базы данными из макета, автогенерации комментария
// к проводке или определении значения параметра ИмяСобытия метода ЗаписьЖурналаРегистрации.
//
// Возвращаемое значение:
//  Строка
//

Функция КодОсновногоЯзыка() Экспорт

	Если ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
		МодульМультиязычностьСервер = ОбщийМодуль("МультиязычностьСервер");
		Возврат МодульМультиязычностьСервер.КодОсновногоЯзыка();
	КонецЕсли;

	Возврат Метаданные.ОсновнойЯзык.КодЯзыка;

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

// Возвращает признак того, что для пользователя установлен язык интерфейса
// соответствующий основному языку информационной базы.
//
// Возвращаемое значение:
//  Булево
//

Функция ЭтоОсновнойЯзык() Экспорт

	Возврат СтрСравнить(КодОсновногоЯзыка(), ТекущийЯзык().КодЯзыка) = 0;

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

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

Функция ПредопределенныйЭлемент(ПолноеИмяПредопределенного) Экспорт

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

	Если СтандартнаяОбработка Тогда
		Возврат ПредопределенноеЗначение(ПолноеИмяПредопределенного);
	КонецЕсли;

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

	ПредопределенныеЗначения = СтандартныеПодсистемыПовтИсп.СсылкиПоИменамПредопределенных(
		ПоляПредопределенного.ПолноеИмяОбъектаМетаданных);

	Возврат ОбщегоНазначенияСлужебныйКлиентСервер.ПредопределенныйЭлемент(
		ПолноеИмяПредопределенного, ПоляПредопределенного, ПредопределенныеЗначения);

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

// Возвращает информацию о том, являются ли переданные элементы предопределенными.
// Если нет прав доступа на уровне записей, то элемент не включается в результат.
// Если нет прав доступа к таблице, то вызывается исключение.
//
// Параметры:
//  Элементы - Массив из ЛюбаяСсылка
//
// Возвращаемое значение:
//  Соответствие из КлючИЗначение - список объектов и значений их реквизитов:
//   * Ключ - ЛюбаяСсылка - ссылка на объект.
//   * Значение - Булево - Истина, если это ссылка на предопределенный элемент.
//

Функция ЭтоПредопределенныеЭлементы(Знач Элементы) Экспорт

	ИменаРеквизитов = Новый Массив;
	Для каждого ИмяРеквизита Из СтандартныеПодсистемыСервер.РеквизитыПредопределенныхДанных() Цикл
		ИменаРеквизитов.Добавить(ИмяРеквизита.Ключ);
	КонецЦикла;

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

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

// Проверяет статус проведения переданных документов и возвращает
// те из них, которые не проведены.
//
// Параметры:
//  Документы - Массив из ДокументСсылка - документы, статус проведения которых необходимо проверить.
//
// Возвращаемое значение:
//  Массив из ДокументСсылка - непроведенные документы.
//


Функция МенеджерОбъектаПоПолномуИмени(ПолноеИмя) Экспорт

	Перем КлассОМ, ИмяОМ, Менеджер;

	ЧастиИмени = СтрРазделить(ПолноеИмя, ".");

	Если ЧастиИмени.Количество() >= 2 Тогда
		КлассОМ = ЧастиИмени[0];
		ИмяОМ   = ЧастиИмени[1];
	Иначе
		Менеджер = Неопределено;
	КонецЕсли;

	Если      ВРег(КлассОМ) = "ПЛАНОБМЕНА" Тогда
		Менеджер = ПланыОбмена;

	ИначеЕсли ВРег(КлассОМ) = "СПРАВОЧНИК" Тогда
		Менеджер = Справочники;

	ИначеЕсли ВРег(КлассОМ) = "ДОКУМЕНТ" Тогда
		Менеджер = Документы;

	ИначеЕсли ВРег(КлассОМ) = "ЖУРНАЛДОКУМЕНТОВ" Тогда
		Менеджер = ЖурналыДокументов;

	ИначеЕсли ВРег(КлассОМ) = "ПЕРЕЧИСЛЕНИЕ" Тогда
		Менеджер = Перечисления;

	ИначеЕсли ВРег(КлассОМ) = "ОТЧЕТ" Тогда
		Менеджер = Отчеты;

	ИначеЕсли ВРег(КлассОМ) = "ОБРАБОТКА" Тогда
		Менеджер = Обработки;

	ИначеЕсли ВРег(КлассОМ) = "ПЛАНВИДОВХАРАКТЕРИСТИК" Тогда
		Менеджер = ПланыВидовХарактеристик;

	ИначеЕсли ВРег(КлассОМ) = "ПЛАНСЧЕТОВ" Тогда
		Менеджер = ПланыСчетов;

	ИначеЕсли ВРег(КлассОМ) = "ПЛАНВИДОВРАСЧЕТА" Тогда
		Менеджер = ПланыВидовРасчета;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРСВЕДЕНИЙ" Тогда
		Менеджер = РегистрыСведений;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРНАКОПЛЕНИЯ" Тогда
		Менеджер = РегистрыНакопления;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРБУХГАЛТЕРИИ" Тогда
		Менеджер = РегистрыБухгалтерии;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРРАСЧЕТА" Тогда

		Если      ЧастиИмени.Количество() = 2 Тогда
			Менеджер = РегистрыРасчета;

		ИначеЕсли ЧастиИмени.Количество() = 4 Тогда
			КлассПодчиненногоОМ = ЧастиИмени[2];
			ИмяПодчиненногоОМ = ЧастиИмени[3];

			Если ВРег(КлассПодчиненногоОМ) = "ПЕРЕРАСЧЕТ" Тогда
				Менеджер = РегистрыРасчета[ИмяОМ].Перерасчеты;
				ИмяОм = ИмяПодчиненногоОМ;

			Иначе
				Менеджер = Неопределено;
			КонецЕсли;

		Иначе
			Менеджер = Неопределено;
		КонецЕсли;

	ИначеЕсли ВРег(КлассОМ) = "БИЗНЕСПРОЦЕСС" Тогда
		Менеджер = БизнесПроцессы;

	ИначеЕсли ВРег(КлассОМ) = "ЗАДАЧА" Тогда
		Менеджер = Задачи;

	ИначеЕсли ВРег(КлассОМ) = "КОНСТАНТА" Тогда
		Менеджер = Константы;

	ИначеЕсли ВРег(КлассОМ) = "ПОСЛЕДОВАТЕЛЬНОСТЬ" Тогда
		Менеджер = Последовательности;

	Иначе
		Менеджер = Неопределено;
	КонецЕсли;

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

	Попытка
		Возврат Менеджер[ИмяОМ];
	Исключение
		ПроверитьОбъектМетаданныхСуществует(ПолноеИмя);
		ВызватьИсключение;
	КонецПопытки;

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

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

Функция МенеджерОбъектаПоСсылке(Ссылка) Экспорт

	ИмяОбъекта = Ссылка.Метаданные().Имя;
	ТипСсылки = ТипЗнч(Ссылка);

	Если Справочники.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Справочники[ИмяОбъекта];

	ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Документы[ИмяОбъекта];

	ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат БизнесПроцессы[ИмяОбъекта];

	ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыВидовХарактеристик[ИмяОбъекта];

	ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыСчетов[ИмяОбъекта];

	ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыВидовРасчета[ИмяОбъекта];

	ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Задачи[ИмяОбъекта];

	ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыОбмена[ИмяОбъекта];

	ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Перечисления[ИмяОбъекта];
	Иначе
		Возврат Неопределено;
	КонецЕсли;

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

// Проверка того, что переданный тип является ссылочным типом данных.
// Для типа Неопределено возвращается Ложь.
//
// Параметры:
//  ПроверяемыйТип - Тип - для проверки на ссылочный тип данных.
//
// Возвращаемое значение:
//  Булево - Истина, если это ссылка.
//

Функция ЭтоСсылка(ПроверяемыйТип) Экспорт

	Возврат ПроверяемыйТип <> Тип("Неопределено") И ОписаниеТипаВсеСсылки().СодержитТип(ПроверяемыйТип);

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

// Проверяет физическое наличие записи в информационной базе данных о переданном значении ссылки.
//
// Параметры:
//  ПроверяемаяСсылка - ЛюбаяСсылка - значение любой ссылки информационной базы данных.
//
// Возвращаемое значение:
//  Булево - Истина, если существует.
//

Функция СсылкаСуществует(ПроверяемаяСсылка) Экспорт

	ТекстЗапроса =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	1 КАК Поле1
		|ИЗ
		|	&ИмяТаблицы КАК Таблица
		|ГДЕ
		|	Таблица.Ссылка = &Ссылка";

	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицы", ИмяТаблицыПоСсылке(ПроверяемаяСсылка));

	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);

	УстановитьПривилегированныйРежим(Истина);
	Возврат НЕ Запрос.Выполнить().Пустой();

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

// Возвращает имя вида объектов метаданных по ссылке на объект.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
// См. так же ВидОбъектаПоТипу.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - объект, вид которого требуется получить.
//
// Возвращаемое значение:
//  Строка - имя вида объектов метаданных. Например: "Справочник", "Документ".
//

Функция ВидОбъектаПоСсылке(Ссылка) Экспорт

	Возврат ВидОбъектаПоТипу(ТипЗнч(Ссылка));

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

// Возвращает имя вида объектов метаданных по типу объекта.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
// См. так же ВидОбъектаПоСсылке.
//
// Параметры:
//  ТипОбъекта - Тип - тип прикладного объекта, определенный в конфигурации.
//
// Возвращаемое значение:
//  Строка - имя вида объектов метаданных. Например: "Справочник", "Документ".
//

Функция ВидОбъектаПоТипу(ТипОбъекта) Экспорт

	Если Справочники.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Справочник";

	ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Документ";

	ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "БизнесПроцесс";

	ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланВидовХарактеристик";

	ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланСчетов";

	ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланВидовРасчета";

	ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Задача";

	ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланОбмена";

	ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Перечисление";

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

	КонецЕсли;

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

// Возвращает полное имя объекта метаданных по переданному значению ссылки.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - объект, для которого необходимо получить имя таблицы ИБ.
//
// Возвращаемое значение:
//  Строка - полное имя объекта метаданных для указанного объекта. Например: "Справочник.Номенклатура".
//

Функция ИмяТаблицыПоСсылке(Ссылка) Экспорт

	Возврат Ссылка.Метаданные().ПолноеИмя();

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

// Проверяет, что переданное значение имеет ссылочный тип данных.
//
// Параметры:
//  Значение - Произвольный - проверяемое значение.
//
// Возвращаемое значение:
//  Булево - Истина, если тип значения ссылочный.
//


Функция СтрокаВВидеНСтр(Знач ПроверяемаяСтрока) Экспорт

	ПроверяемаяСтрока = СтрЗаменить(ПроверяемаяСтрока, " ", "");

	ВариантыСовпадений = Новый Массив;
	Для каждого Язык Из Метаданные.Языки Цикл
		ВариантыСовпадений.Добавить(Язык.КодЯзыка + "=");
	КонецЦикла;

	Для каждого ВариантСовпадения Из ВариантыСовпадений Цикл
		Если СтрНайти(ПроверяемаяСтрока, ВариантСовпадения) > 0 Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;

	Возврат Ложь;

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

// Устанавливает условное оформление списка выбора
//
// Параметры:
//  Форма - ФормаКлиентскогоПриложения - форма, для которой устанавливается оформление.
//  ИмяЭлемента - Строка - имя элемента, для которого устанавливается оформление.
//  ИмяПоляКомпоновкиДанных - Строка - имя поля компоновки данных.
//

Процедура УстановитьУсловноеОформлениеСпискаВыбора(Форма, ИмяЭлемента, ИмяПоляКомпоновкиДанных) Экспорт

	Элементы           = Форма.Элементы;
	УсловноеОформление = Форма.УсловноеОформление;

	Для каждого ЭлементВыбора Из Элементы[ИмяЭлемента].СписокВыбора Цикл

		Элемент = УсловноеОформление.Элементы.Добавить();

		ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
		ЭлементФормы = Элементы[ИмяЭлемента]; // ПолеФормы
		ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(ЭлементФормы.Имя);

		ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
		ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоляКомпоновкиДанных);
		ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
		ОтборЭлемента.ПравоеЗначение = ЭлементВыбора.Значение;

		Элемент.Оформление.УстановитьЗначениеПараметра("Текст", ЭлементВыбора.Представление);

	КонецЦикла;

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

// Возвращает суффикс текущего языка для мультиязычных реквизитов.
//
// Возвращаемое значение:
//  Строка - "Язык1" или "Язык2", если язык пользователя является дополнительным
//           Пустая строка, если язык пользователя является основным.
//  Неопределено - мультиязычное хранение данных не используется.
//

Функция СуффиксЯзыкаТекущегоПользователя() Экспорт

	Результат = Новый Структура();
	Результат.Вставить("СуффиксТекущегоЯзыка", "");
	Результат.Вставить("ЭтоОсновнойЯзык", "");

	Если ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
		МодульМультиязычностьСервер = ОбщийМодуль("МультиязычностьСервер");
		СуффиксТекущегоЯзыка = МодульМультиязычностьСервер.СуффиксТекущегоЯзыка();

		Если ЗначениеЗаполнено(СуффиксТекущегоЯзыка) Тогда
			Возврат СуффиксТекущегоЯзыка;
		КонецЕсли;
	Иначе
		СуффиксТекущегоЯзыка  = "";
	КонецЕсли;

	Если ЭтоОсновнойЯзык() Тогда
		Возврат СуффиксТекущегоЯзыка;
	КонецЕсли;

	Возврат Неопределено;

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

// Сокращает имя файла с расширением.
// Сокращение имени, производится, когда имя файла с расширением превышает размер 255 байт.
// Сокращение ими файла достигая за счет сокращения имени файла без расширения и
// добавления значения хеш функции сокращенной строки.
//
// Параметры:
//  ИмяФайла - Строка - имя файла с расширением
//

Процедура СократитьИмяФайла(ИмяФайла) Экспорт
	ОграничениеВБайтах =  255;
	Если РазмерСтрокиВБайтах(ИмяФайла) <= ОграничениеВБайтах Тогда
		Возврат;
	КонецЕсли;

	Файл = Новый Файл(ИмяФайла);
	ИмяБезРасширения = Файл.ИмяБезРасширения;

	ОграничениеВБайтах = ОграничениеВБайтах - РазмерСтрокиВБайтах(Файл.Расширение);

	ДлинаСтроки = СтрДлина(ИмяБезРасширения);
	ИспользуемоеКоличествоСимволов = ОграничениеВБайтах - 32;
	БольшееКоличествоСимволов = Мин(ДлинаСтроки, ОграничениеВБайтах);
	МеньшееКоличествоСимволов = Цел((ОграничениеВБайтах - 32)/4);
	Уменьшить = Истина;
	Пока Истина Цикл
		Если Уменьшить Тогда
			ИспользуемоеКоличествоСимволов = МеньшееКоличествоСимволов + Цел((ИспользуемоеКоличествоСимволов-МеньшееКоличествоСимволов)/2);
		Иначе
			ИспользуемоеКоличествоСимволов = ИспользуемоеКоличествоСимволов + Цел((БольшееКоличествоСимволов - ИспользуемоеКоличествоСимволов)/2);
		КонецЕсли;

		РазмерСтрокиВБайтах = РазмерСтрокиВБайтах(ИмяБезРасширения)+32;

		Если РазмерСтрокиВБайтах = ОграничениеВБайтах Или БольшееКоличествоСимволов - МеньшееКоличествоСимволов = 1 Тогда
			Прервать;
		КонецЕсли;

		Если РазмерСтрокиВБайтах > ОграничениеВБайтах Тогда
			Уменьшить = Истина;
			БольшееКоличествоСимволов = ИспользуемоеКоличествоСимволов;
		Иначе
			Уменьшить = Ложь;
			МеньшееКоличествоСимволов = ИспользуемоеКоличествоСимволов;
		КонецЕсли;

	КонецЦикла;

	СокращеннаяСтрока = СократитьСтрокуКонтрольнойСуммой(ИмяБезРасширения, ИспользуемоеКоличествоСимволов+32);

	ИмяФайла = СокращеннаяСтрока+Файл.Расширение;

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

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

Процедура ОтключитьКонтрольЗаписи(Объект, ЭтоУзелПланаОбмена = Ложь) Экспорт

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

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

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

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

#Область ДанныеВБазе

#Область ЗначенияРеквизитов

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


Функция КонтактнаяИнформацияОрганизации(Знач Организация, Знач Поля = "", Знач Дата = Неопределено, Знач КодЯзыка = Неопределено) Экспорт

	КонтактнаяИнформация = Новый Структура();
	ОрганизацииПереопределяемый.ПриОпределенииКонтактнойИнформацииОрганизации(Организация, Поля, Дата, КонтактнаяИнформация, КодЯзыка);

	Возврат КонтактнаяИнформация;

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

// Возвращает структуру, содержащую сведения о банковском счете организации.
//
// Параметры:
//  Организация - ОпределяемыйТип.Организация - организация, сведения по которой необходимо получить.
//  Поля - Строка - имена полей, перечисленные через запятую, в формате требований к свойствам структуры.
//                  Список допустимых имен полей см. в описании возвращаемого значения (это максимально возможный список
//                  полей, конечный состав определяется в ОрганизацииПереопределяемый.ПриОпределенииБанковскогоСчетаОрганизации).
//                  Если указана пустая строка, то возвращаются значения всех полей.
//  Дата - Дата
//       - Неопределено - дата, на которую требуется получить данные. Если значение не указано,
//                  то возвращается значение на текущую дату.
//  КодЯзыка - см. СведенияОбОрганизации.КодЯзыка
//
// Возвращаемое значение:
//   Структура - содержит значения затребованных полей:
//            * БанковскийСчетБанк - Строка - банк.
//            * БанковскийСчетБИК - Строка - БИК.
//            * БанковскийСчетКоррСчет - Строка - корреспондентский счет.
//            * БанковскийСчетНомерСчета - Строка - номер счета.
//

Функция БанковскийСчетОрганизации(Знач Организация, Знач Поля = "", Знач Дата = Неопределено, Знач КодЯзыка = Неопределено) Экспорт

	БанковскийСчет = Новый Структура();
	ОрганизацииПереопределяемый.ПриОпределенииБанковскогоСчетаОрганизации(Организация, Поля, Дата, БанковскийСчет, КодЯзыка);

	Возврат БанковскийСчет;

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

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

#Область СведенияОбОбособленномПодразделении

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

Функция РегистрационныеДанныеОбособленногоПодразделения(Знач Организация, Знач Поля = "", Знач Дата = Неопределено, Знач КодЯзыка = Неопределено) Экспорт

	РегистрационныеДанные = Новый Структура();
	ОрганизацииПереопределяемый.ПриОпределенииРегистрационныхДанныхОбособленногоПодразделения(Организация, Поля, Дата, РегистрационныеДанные, КодЯзыка);

	Возврат РегистрационныеДанные;

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

// Возвращает структуру, содержащую сведения о контактной информации обособленного подразделения.
//
// Параметры:
//  Организация - ОпределяемыйТип.Организация - организация, сведения по которой необходимо получить.
//  Поля - Строка - имена полей, перечисленные через запятую, в формате требований к свойствам структуры.
//                  Список допустимых имен полей см. в описании возвращаемого значения (это максимально возможный список
//                  полей, конечный состав определяется в ОрганизацииПереопределяемый.ПриОпределенииКонтактнойИнформацииОбособленногоПодразделения).
//                  Если указана пустая строка, то возвращаются значения всех полей.
//  Дата - Дата
//       - Неопределено - дата, на которую требуется получить данные. Если значение не указано,
//                  то возвращается значение на текущую дату.
//  КодЯзыка - см. СведенияОбОрганизации.КодЯзыка
//
// Возвращаемое значение:
//   Структура - содержит имена (ключи) и значения затребованных полей:
//            * АдресОбособленногоПодразделения - Строка - адрес обособленного подразделения.
//            * АдресОбособленногоПодразделенияXML - Строка - адрес обособленного подразделения в xml.
//            * АдресОбособленногоПодразделенияJSON - Строка - адрес обособленного подразделения в json.
//            * АдресОбособленногоПодразделенияГород - Строка - город.
//            * АдресОбособленногоПодразделенияДом - Строка - дом.
//            * АдресОбособленногоПодразделенияИндекс - Строка - индекс.
//            * АдресОбособленногоПодразделенияКвартира - Строка - квартира.
//            * АдресОбособленногоПодразделенияКодРегиона - Строка - регион.
//            * АдресОбособленногоПодразделенияКорпус - Строка - корпус.
//            * АдресОбособленногоПодразделенияНаселенныйПункт - Строка - населенный пункт.
//            * АдресОбособленногоПодразделенияРайон - Строка - район.
//            * АдресОбособленногоПодразделенияРегион - Строка - регион.
//            * АдресОбособленногоПодразделенияУлица - Строка - улица.
//

Функция КонтактнаяИнформацияОбособленногоПодразделения(Знач Организация, Знач Поля = "", Знач Дата = Неопределено, Знач КодЯзыка = Неопределено) Экспорт

	КонтактнаяИнформация = Новый Структура();
	ОрганизацииПереопределяемый.ПриОпределенииКонтактнойИнформацииОбособленногоПодразделения(Организация, Поля, Дата, КонтактнаяИнформация, КодЯзыка);

	Возврат КонтактнаяИнформация;

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

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

#Область СведенияОбИностраннойОрганизации

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


Процедура ПолучитьСведенияОСвойствахЭлементаНастроек(ЭлементНастроек, Сведения, ДополнительныеСвойства)
	ИдентификаторыСвойств = ИдентификаторыСвойствНастроек(ДополнительныеСвойства);
	ДополнительныеИдентификаторы = Новый Массив;

	ДоступныеСвойства = Новый Структура("Выбор, Отбор, Порядок, УсловноеОформление, Структура");

	ТипЭлементаНастроек = ТипЗнч(ЭлементНастроек);
	Если ТипЭлементаНастроек <> Тип("ТаблицаКомпоновкиДанных")
		И ТипЭлементаНастроек <> Тип("ДиаграммаКомпоновкиДанных") Тогда

		ДополнительныеИдентификаторы.Добавить("Отбор");
		ДополнительныеИдентификаторы.Добавить("Порядок");
		ДополнительныеИдентификаторы.Добавить("Структура");

		Если ТипЭлементаНастроек = Тип("НастройкиКомпоновкиДанных") Тогда
			ДополнительныеИдентификаторы.Добавить("ПараметрыДанных");
		КонецЕсли;
	КонецЕсли;

	ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИдентификаторыСвойств, ДополнительныеИдентификаторы, Истина);

	Для Каждого Идентификатор Из ИдентификаторыСвойств Цикл
		Свойство = ЭлементНастроек[Идентификатор];

		Если ДоступныеСвойства.Свойство(Идентификатор)
			И ЗначениеЗаполнено(Свойство.ИдентификаторПользовательскойНастройки) Тогда

			ВидыСведений = ВидыСведений();
			ВидыСведений.Настройки = ЭлементНастроек;
			ВидыСведений.ЭлементНастройки = Свойство;

			Сведения.Вставить(Свойство.ИдентификаторПользовательскойНастройки, ВидыСведений);
		КонецЕсли;

		ПолучитьСведенияОЭлементахСвойстваНастроек(ЭлементНастроек, Свойство, Идентификатор, Сведения, ДополнительныеСвойства);
		ПолучитьСведенияОКоллекции(ЭлементНастроек, Свойство, Сведения, ДополнительныеСвойства);
	КонецЦикла;
КонецПроцедуры

// Добавляет сведения о элементах отборов, значениях параметров и т.д.
//
// Параметры:
//   Настройки - НастройкиКомпоновкиДанных
//   Свойство - ОтборКомпоновкиДанных
//            - ЗначенияПараметровДанныхКомпоновкиДанных
//            - ЗначенияПараметровВыводаКомпоновкиДанных
//            - УсловноеОформлениеКомпоновкиДанных
//   ИдентификаторСвойства - Строка
//   Сведения - см. ВидыСведений
//   ДополнительныеСвойства - Структура
//

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

	Для Каждого Элемент Из Свойство.Элементы Цикл
		ТипЭлемента = ТипЗнч(Элемент);

		Если ЗначениеЗаполнено(Элемент.ИдентификаторПользовательскойНастройки) Тогда
			Описание = Неопределено;
			Если ТипЭлемента = Тип("ЭлементОтбораКомпоновкиДанных") Тогда

				ДоступныеПоля = Настройки[ИдентификаторСвойства].ДоступныеПоляОтбора;
				Если ДоступныеПоля <> Неопределено Тогда
					Описание = ДоступныеПоля.НайтиПоле(Элемент.ЛевоеЗначение);
				КонецЕсли;

			ИначеЕсли ТипЭлемента = Тип("ЗначениеПараметраКомпоновкиДанных")
				Или ТипЭлемента = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда

				ДоступныеПараметры = Настройки[ИдентификаторСвойства].ДоступныеПараметры;
				Если ДоступныеПараметры <> Неопределено Тогда
					Описание = ДоступныеПараметры.НайтиПараметр(Элемент.Параметр);
				КонецЕсли;
			КонецЕсли;

			ВидыСведений = ВидыСведений();
			ВидыСведений.Настройки = Настройки;
			ВидыСведений.ЭлементНастройки = Элемент;
			ВидыСведений.ОписаниеНастройки = Описание;

			Сведения.Вставить(Элемент.ИдентификаторПользовательскойНастройки, ВидыСведений);
		КонецЕсли;

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

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

			Сведения.Вставить(ЗначениеПараметра.ИдентификаторПользовательскойНастройки, ВидыСведений);
		КонецЕсли;

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

Функция ИдентификаторыСвойствНастроек(ДополнительныеСвойства)
	ИдентификаторыСвойствПоУмолчанию = СтрРазделить("Выбор, ПараметрыВывода, УсловноеОформление", ", ", Ложь);

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

	Возврат ОбщегоНазначения.СкопироватьРекурсивно(ИдентификаторыСвойств);
КонецФункции

// Конструктор индекса свойств пользовательских настроек.
//
// Возвращаемое значение:
//   Структура:
//   * Настройки - НастройкиКомпоновкиДанных
//   * ЭлементНастройки - ЭлементОтбораКомпоновкиДанных
//                    - ЗначениеПараметраКомпоновкиДанных
//                    - ВыбранноеПолеКомпоновкиДанных
//   * ОписаниеНастройки - ДоступноеПолеОтбораКомпоновкиДанных
//                     - ДоступныйПараметрКомпоновкиДанных
//

Функция ВидыСведений()
	Возврат Новый Структура("Настройки, ЭлементНастройки, ОписаниеНастройки");
КонецФункции

// Перегруппировка элементов формы, связанных с пользовательскими настройками.

// Формирует коллекции имен реквизитов, сгруппированных по стилям: Период, Флажок, Список.
//
// Параметры:
//   Форма - ФормаКлиентскогоПриложения
//         - РасширениеУправляемойФормыДляОтчета
//   ВидыЭлементов - Массив из Строка
//
// Возвращаемое значение:
//   Структура:
//     * Сгенерированных - Структура
//     * Предопределенных - Структура
//

Функция ИменаРеквизитовЭлементовНастроек(Форма, ВидыЭлементов)
	ИменаРеквизитовПредопределенных = Новый Структура;
	ИменаРеквизитовСгенерированных = Новый Структура;

	Для Каждого ВидЭлемента Из ВидыЭлементов Цикл
		ИменаРеквизитовПредопределенных.Вставить(ВидЭлемента, Новый Массив);
		ИменаРеквизитовСгенерированных.Вставить(ВидЭлемента, Новый Массив);
	КонецЦикла;

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

				ИменаРеквизитовПоВидам = ИменаРеквизитовПредопределенных[ВидЭлемента]; // Массив из Строка
				ИменаРеквизитовПоВидам.Добавить(Реквизит.Имя);
			КонецЕсли;

			Если СтрНачинаетсяС(Реквизит.Имя, "КомпоновщикНастроекПользовательскиеНастройкиЭлемент")
				И СтрЗаканчиваетсяНа(Реквизит.Имя, ВидЭлемента) Тогда

				ИменаРеквизитовПоВидам = ИменаРеквизитовСгенерированных[ВидЭлемента]; // Массив из Строка
				ИменаРеквизитовПоВидам.Добавить(Реквизит.Имя);
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;

	ИменаРеквизитов = Новый Структура;
	ИменаРеквизитов.Вставить("Предопределенных", ИменаРеквизитовПредопределенных);
	ИменаРеквизитов.Вставить("Сгенерированных", ИменаРеквизитовСгенерированных);

	Возврат ИменаРеквизитов;
КонецФункции