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

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

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

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

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

// Формирует шаблон сведений о внешнем отчете или обработке для последующего заполнения.
//
// Параметры:
//   ВерсияБСП - см. СтандартныеПодсистемыСервер.ВерсияБиблиотеки.
//
// Возвращаемое значение:
//   Структура - параметры внешнего отчета или обработки:
//       * Вид - ПеречислениеСсылка.ВидыДополнительныхОтчетовИОбработок 
//             - Строка - вид внешнего отчета или обработки. Для указания вида рекомендуется использовать функции
//           ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработки<ИмяВида>.
//           Также вид можно указать явно:
//           "ПечатнаяФорма",
//           "ЗаполнениеОбъекта",
//           "СозданиеСвязанныхОбъектов",
//           "Отчет",
//           "ШаблонСообщения",
//           "ДополнительнаяОбработка",
//           "ДополнительныйОтчет".
//       
//       * Версия - Строка - версия отчета или обработки (далее - обработки).
//           Задается в формате: "<Старший номер>.<Младший номер>".
//       
//       * Назначение - Массив - полные имена объектов конфигурации (Строка), для которых предназначен эта обработка.
//                               Необязательное свойство.
//       
//       * Наименование - Строка - представление для администратора (наименование элемента справочника).
//                                 Если не заполнено, то берется представление объекта метаданных внешней обработки.
//                                 Необязательное свойство. 
//       
//       * БезопасныйРежим - Булево - признак подключения внешней обработки в безопасном режиме.
//                                    Значение по умолчанию Истина (обработка будет выполняться безопасно).
//                                    В безопасном режиме:
//                                     Игнорируется привилегированный режим.
//                                     Запрещены внешние по отношению к платформе 1С:Предприятия действия:
//                                      COM;
//                                      загрузка внешних компонент;
//                                      запуск внешних приложений и команд операционной системы;
//                                      доступ к файловой системе, кроме временных файлов;
//                                      доступ к Интернету.
//                                    Необязательное свойство.
//       
//       * Разрешения - Массив из ОбъектXDTO - дополнительные разрешения, необходимые внешней обработке при работе в
//                               безопасном режиме. Элемент массива - ОбъектXDTO - разрешение типа
//                               {http://www.1c.ru/1cFresh/ApplicationExtensions/Permissions/a.b.c.d}PermissionBase.
//                               Для формирования описания разрешения рекомендуется использовать функции
//                               РаботаВБезопасномРежиме.Разрешение<ВидРазрешения>(<ПараметрыРазрешения>).
//                               Необязательное свойство.
//       
//       * Информация - Строка - краткая информация о внешней обработке.
//                               В этом параметре для администратора рекомендуется дать описание ее возможностей.
//                               Если не заполнено, то берется комментарий объекта метаданных внешней обработки.
//       
//       * ВерсияБСП - см. СтандартныеПодсистемыСервер.ВерсияБиблиотеки.
//       
//       * ОпределитьНастройкиФормы - Булево - только для дополнительных отчетов, подключенных к общей форме ФормаОтчета.
//                                             Позволяет переопределять некоторые настройки общей формы отчета и 
//                                             подписываться на ее события.
//                                             Если Истина, то в модуле объекта отчета следует определить процедуру по шаблону:
//       
//       * НазначениеВариантаОтчета - ПеречислениеСсылка.НазначенияВариантовОтчетов - назначение варианта отчета
//										(ДляКомпьютеровИПланшетов, ДляСмартфонов, ДляЛюбыхУстройств).
//           
//           // Задать настройки формы отчета.
//           //
//           // Параметры:
//           //   Форма - ФормаКлиентскогоПриложения, Неопределено
//           //   КлючВарианта - Строка, Неопределено
//           //   Настройки - см. ОтчетыКлиентСервер.НастройкиОтчетаПоУмолчанию
//           //
//           Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт
//           	// Код процедуры.
//           КонецПроцедуры
//           
//           Подробнее см. в документации к подсистемам "Дополнительные отчеты и обработки" и "Варианты отчетов".
//           Необязательное свойство.
//       
//       * Команды - ТаблицаЗначений - настройки команд, поставляемых внешней обработкой (необязательно для отчетов):
//           ** Идентификатор - Строка - внутреннее имя команды. Для внешних печатных форм (когда Вид = "ПечатнаяФорма"):
//                 Идентификатор может содержать имена одной или нескольких команд печати,
//                 разделенные запятыми. Подробнее см. описание колонки Идентификатор
//                 в функции УправлениеПечатью.СоздатьКоллекциюКомандПечати.
//           ** Представление - Строка - пользовательское представление команды.
//           ** Использование - Строка - тип команды:
//               "ВызовКлиентскогоМетода",
//               "ВызовСерверногоМетода",
//               "ЗаполнениеФормы",
//               "ОткрытиеФормы" или
//               "СценарийВБезопасномРежиме".
//               Для получения типов команд рекомендуется использовать функции
//               ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКоманды<ИмяТипа>.
//               В комментариях к этим функциям также даны шаблоны процедур-обработчиков команд.
//           ** ПоказыватьОповещение - Булево - если Истина, то при запуске команды выводится оповещение "Команда выполняется...".
//              Действует для всех типов команд, кроме команд по открытию формы (Использование = "ОткрытиеФормы").
//           ** Модификатор - Строка - дополнительная классификация команды.
//               Для внешних печатных форм (когда Вид = "ПечатнаяФорма"):
//                 "ПечатьMXL" - для печатных форм на основе табличных макетов.
//               Для загрузки данных из файла (когда Вид = "ПечатнаяФорма" и Использование = "ЗагрузкаДанныхИзФайла"):
//                 Модификатор является обязательным для заполнения
//                 и должен содержать полное имя объекта метаданных (справочника),
//                 для которого выполняется загрузка данных.
//           ** Скрыть - Булево - необязательный. Признак того, что это служебная команда.
//               Если установить в значение Истина, то команда скрывается в карточке дополнительного объекта.
//
Функция СведенияОВнешнейОбработке(ВерсияБСП = "") Экспорт
	ПараметрыРегистрации = Новый Структура;
	
	ПараметрыРегистрации.Вставить("Вид", "");
	ПараметрыРегистрации.Вставить("Версия", "0.0");
	ПараметрыРегистрации.Вставить("Назначение", Новый Массив);
	ПараметрыРегистрации.Вставить("Наименование", Неопределено);
	ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
	ПараметрыРегистрации.Вставить("Информация", Неопределено);
	ПараметрыРегистрации.Вставить("ВерсияБСП", ВерсияБСП);
	ПараметрыРегистрации.Вставить("ОпределитьНастройкиФормы", Ложь);
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ВариантыОтчетов") Тогда
		МодульВариантыОтчетовСлужебный = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетовСлужебный");
		ПараметрыРегистрации.Вставить("НазначениеВариантаОтчета",
			МодульВариантыОтчетовСлужебный.ПустоеНазначениеВариантаОтчета());
	КонецЕсли;
	
	РеквизитыТабличнойЧасти = Метаданные.Справочники.ДополнительныеОтчетыИОбработки.ТабличныеЧасти.Команды.Реквизиты;
	
	ТаблицаКоманд = Новый ТаблицаЗначений;
	ТаблицаКоманд.Колонки.Добавить("Представление", РеквизитыТабличнойЧасти.Представление.Тип);
	ТаблицаКоманд.Колонки.Добавить("Идентификатор", РеквизитыТабличнойЧасти.Идентификатор.Тип);
	ТаблицаКоманд.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
	ТаблицаКоманд.Колонки.Добавить("ПоказыватьОповещение", РеквизитыТабличнойЧасти.ПоказыватьОповещение.Тип);
	ТаблицаКоманд.Колонки.Добавить("Модификатор", РеквизитыТабличнойЧасти.Модификатор.Тип);
	ТаблицаКоманд.Колонки.Добавить("Скрыть",      РеквизитыТабличнойЧасти.Скрыть.Тип);
	ТаблицаКоманд.Колонки.Добавить("ЗаменяемыеКоманды", РеквизитыТабличнойЧасти.ЗаменяемыеКоманды.Тип);
	
	ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
	ПараметрыРегистрации.Вставить("Разрешения", Новый Массив);
	
	Возврат ПараметрыРегистрации;
КонецФункции

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	Возврат ДополнительныеКоманды(Перечисления.ВидыДополнительныхОтчетовИОбработок.ПечатнаяФорма, Размещение, 
		ЭтоФормаОбъекта);

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

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

Функция ИспользуютсяДополнительныеОтчетыИОбработки() Экспорт
	Возврат ПолучитьФункциональнуюОпцию("ИспользоватьДополнительныеОтчетыИОбработки");
КонецФункции

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

Функция ЭтоТипДополнительныйОтчетИлиОбработка(Тип) Экспорт
	Возврат (Тип = Тип("СправочникСсылка.ДополнительныеОтчетыИОбработки"));
КонецФункции

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// См. ГрупповоеИзменениеОбъектовПереопределяемый.ПриОпределенииОбъектовСРедактируемымиРеквизитами.
Процедура ПриОпределенииОбъектовСРедактируемымиРеквизитами(Объекты) Экспорт
	Объекты.Вставить(Метаданные.Справочники.ДополнительныеОтчетыИОбработки.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
КонецПроцедуры

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

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

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

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

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

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

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

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

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

// См. УправлениеСвойствамиПереопределяемый.ПриПолученииПредопределенныхНаборовСвойств.
Процедура ПриПолученииПредопределенныхНаборовСвойств(Наборы) Экспорт
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Справочник_ДополнительныеОтчетыИОбработки";
	Набор.Идентификатор = Новый УникальныйИдентификатор("82cbc0a7-224e-48bc-a4a5-a108c3ac3bd0");
КонецПроцедуры

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

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

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

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

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

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

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

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

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

Функция ЭтоВидОбработкиДляШаблоновСообщений(ВидОбработки) Экспорт

	Если ВидОбработки = ПолучитьВидОбработкиПоСтроковомуПредставлениюВида(
		ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиШаблонСообщения()) Тогда
		Возврат Истина;
	КонецЕсли;

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

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

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

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

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

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

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

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


#Область РегламентныеЗадания

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

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

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

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

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

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

// Возвращаемое значение:
//  Строка
//
Функция ПредставлениеОбъектаМетаданных(Объект) Экспорт

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

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

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

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

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

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

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

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

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

// Запись информации в журнал регистрации по дополнительному отчету или обработке.
Процедура ЗаписатьИнформацию(Ссылка, ТекстСообщения)
	ЗаписатьВЖурнал(УровеньЖурналаРегистрации.Информация, Ссылка, ТекстСообщения);
КонецПроцедуры

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

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

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

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

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

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

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

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

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

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

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

#Область ПроцедурыИспользуемыеПриОбменеДанными

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

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

#Область СопоставлениеЭлементовСправочникаОбъектамМетаданныхКонфигурации

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

// Возвращаемое значение:
//   ТаблицаЗначений:
//   * Ссылка - СправочникСсылка.ДополнительныеОтчетыИОбработки
//   * Версия - Строка
//   * ИмяОбъекта - Строка
//   * ИмяФайла - Строка
//
Функция ОбработкиИзКонфигурации()

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

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

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

#Область ВыгрузкаОтчетовИОбработокКонфигурацииВФайлыВнешнихОтчетовИОбработок

// Параметры:
//  ОтчетыИОбработки - см. ЗагрузитьДополнительныеОтчетыИОбработкиИзМетаданных.ОтчетыИОбработки
//
Процедура ВыгрузитьОтчетыИОбработкиВФайлы(ОтчетыИОбработки)
	
	ОтчетыИОбработки.Колонки.Добавить("ДвоичныеДанные");
	Параметры = Новый Структура;
	Параметры.Вставить("РабочийКаталог", ФайловаяСистема.СоздатьВременныйКаталог("ARADP"));
	КомандаЗапуска = Новый Массив;
	КомандаЗапуска.Добавить("/DumpConfigToFiles");
	КомандаЗапуска.Добавить(Параметры.РабочийКаталог);
	Выгрузка = ПакетныйЗапускКонфигуратора(Параметры, КомандаЗапуска);
	Если Не Выгрузка.Успех Тогда
		ТекстОшибки = СокрЛП(
			НСтр("ru = 'Не удалось выгрузить отчеты и обработки конфигурации во внешние файлы:'")
			+ Символы.ПС + Выгрузка.Кратко
			+ Символы.ПС + Выгрузка.Подробно);
		ЗаписатьПредупреждение(Неопределено, ТекстОшибки);
		ОтчетыИОбработки.Очистить();
	КонецЕсли;
	
	ОбратныйИндекс = ОтчетыИОбработки.Количество();
	Пока ОбратныйИндекс > 0 Цикл
		ОбратныйИндекс = ОбратныйИндекс - 1;
		СтрокаТаблицы = ОтчетыИОбработки.Получить(ОбратныйИндекс);
		
		Если СтрокаТаблицы.Вид = "ОТЧЕТ" Тогда
			КаталогВида = Параметры.РабочийКаталог + "Reports" + ПолучитьРазделительПути();
		ИначеЕсли СтрокаТаблицы.Вид = "ОБРАБОТКА" Тогда
			КаталогВида = Параметры.РабочийКаталог + "DataProcessors" + ПолучитьРазделительПути();
		Иначе
			ЗаписатьОшибку(СтрокаТаблицы.Ссылка, 
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Неподдерживаемый вид объектов метаданных: ""1""'"), СтрокаТаблицы.Вид));
			ОтчетыИОбработки.Удалить(ОбратныйИндекс);
			Продолжить;
		КонецЕсли;
		
		ПолноеИмяСхемыОбъекта = КаталогВида + СтрокаТаблицы.Имя + ".xml";
		ТекстСхемы = ПрочитатьТекстовыйФайл(ПолноеИмяСхемыОбъекта);
		Если ТекстСхемы = Неопределено Тогда
			ЗаписатьОшибку(СтрокаТаблицы.Ссылка, 
				СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Не обнаружен файл ""%1"".'"), 
					ПолноеИмяСхемыОбъекта));
			ОтчетыИОбработки.Удалить(ОбратныйИндекс);
			Продолжить;
		КонецЕсли;
		Если СтрокаТаблицы.Вид = "ОТЧЕТ" Тогда
			ТекстСхемы = СтрЗаменить(ТекстСхемы, "Report", "ExternalReport");
			ТекстСхемы = СтрЗаменить(ТекстСхемы, "ExternalReportTabularSection", "ReportTabularSection");
		ИначеЕсли СтрокаТаблицы.Вид = "ОБРАБОТКА" Тогда
			ТекстСхемы = СтрЗаменить(ТекстСхемы, "DataProcessor", "ExternalDataProcessor");
		КонецЕсли;
		ЗаписатьТекстовыйФайл(ПолноеИмяСхемыОбъекта, ТекстСхемы);
		
		Если СтрокаТаблицы.Вид = "ОБРАБОТКА" Тогда
			ДокументDOM = ПрочитатьДокументDOM(ПолноеИмяСхемыОбъекта);
			Разыменователь = Новый РазыменовательПространствИменDOM(ДокументDOM);
			XMLИзменен = Ложь;
			
			ВыраженияПоискаУдаляемыхУзлов = Новый Массив;
			ВыраженияПоискаУдаляемыхУзлов.Добавить("//xmlns:Command");
			ВыраженияПоискаУдаляемыхУзлов.Добавить("//*[contains(@name, 'ExternalDataProcessorManager.')]");
			ВыраженияПоискаУдаляемыхУзлов.Добавить("//xmlns:UseStandardCommands");
			ВыраженияПоискаУдаляемыхУзлов.Добавить("//xmlns:IncludeHelpInContents");
			ВыраженияПоискаУдаляемыхУзлов.Добавить("//xmlns:ExtendedPresentation");
			ВыраженияПоискаУдаляемыхУзлов.Добавить("//xmlns:Explanation");
			
			Для Каждого Выражение Из ВыраженияПоискаУдаляемыхУзлов Цикл
				РезультатXPath = ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь);
				ЭлементDOM = РезультатXPath.ПолучитьСледующий();
				Пока ЭлементDOM <> Неопределено Цикл
					ЭлементDOM.РодительскийУзел.УдалитьДочерний(ЭлементDOM);
					XMLИзменен = Истина;
					ЭлементDOM = РезультатXPath.ПолучитьСледующий();
				КонецЦикла;
			КонецЦикла;
			
			Если XMLИзменен Тогда
				ЗаписатьДокументDOM(ДокументDOM, ПолноеИмяСхемыОбъекта);
			КонецЕсли;
		КонецЕсли;
		
		ПолноеИмяФайла = Параметры.РабочийКаталог + СтрокаТаблицы.ИмяФайла;
		КомандаЗапуска = Новый Массив;
		КомандаЗапуска.Добавить("/LoadExternalDataProcessorOrReportFromFiles");
		КомандаЗапуска.Добавить(ПолноеИмяСхемыОбъекта);
		КомандаЗапуска.Добавить(ПолноеИмяФайла);
		СозданиеОбработки = ПакетныйЗапускКонфигуратора(Параметры, КомандаЗапуска);
		Если Не СозданиеОбработки.Успех Тогда
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Не удалось создать ""%1"" из внешнего файла ""%2"":
					|%3
					|%4'"),
				СтрокаТаблицы.ПолноеИмя, ПолноеИмяСхемыОбъекта, 
				СозданиеОбработки.Кратко, СозданиеОбработки.Подробно);
			ЗаписатьПредупреждение(Неопределено, ТекстОшибки);
			ОтчетыИОбработки.Удалить(ОбратныйИндекс);
			Продолжить;
		КонецЕсли;
		СтрокаТаблицы.ДвоичныеДанные = Новый ДвоичныеДанные(ПолноеИмяФайла);
	КонецЦикла;
	
	Если Параметры.КаталогКопии1CD <> Неопределено Тогда
		ФайловаяСистема.УдалитьВременныйКаталог(Параметры.КаталогКопии1CD);
	КонецЕсли;
	ФайловаяСистема.УдалитьВременныйКаталог(Параметры.РабочийКаталог);
	
КонецПроцедуры

Функция ПакетныйЗапускКонфигуратора(Параметры, ПереданныеКомандыЗапуска)
	Результат = Новый Структура("Успех, Кратко, Подробно", Ложь, "", "");
	ОбразецПараметров = Новый Структура("РабочийКаталог, Пользователь, Пароль, КаталогBIN, ПутьККонфигурации, КаталогКопии1CD");
	ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(Параметры, ОбразецПараметров, Ложь);
	Если Не ЗначениеЗаполнено(Параметры.Пользователь) Тогда
		Параметры.Пользователь = ИмяПользователя();
	КонецЕсли;
	Если Не ФайлСуществует(Параметры.РабочийКаталог) Тогда
		СоздатьКаталог(Параметры.РабочийКаталог);
	КонецЕсли;
	Если Не ЗначениеЗаполнено(Параметры.КаталогBIN) Тогда
		Параметры.КаталогBIN = КаталогПрограммы();
	КонецЕсли;
	Если Не ЗначениеЗаполнено(Параметры.ПутьККонфигурации) Тогда
		Параметры.ПутьККонфигурации = СтрокаСоединенияИнформационнойБазы();
		Если ОткрытКонфигуратор() Тогда
			Если ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
				КаталогИнформационнойБазы = СтроковыеФункцииКлиентСервер.ПараметрыИзСтроки(Параметры.ПутьККонфигурации).file;
				Параметры.КаталогКопии1CD = Параметры.РабочийКаталог + "BaseCopy" + ПолучитьРазделительПути();
				СоздатьКаталог(Параметры.КаталогКопии1CD);
				КопироватьФайл(КаталогИнформационнойБазы + "\1Cv8.1CD", Параметры.КаталогКопии1CD + "1Cv8.1CD");
				Параметры.ПутьККонфигурации = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					"File=""%1"";", Параметры.КаталогКопии1CD);
			Иначе
				Результат.Кратко = НСтр("ru = 'Для выгрузки модулей закройте конфигуратор.'");
				Возврат Результат;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	ИмяФайлаСообщений = Параметры.РабочийКаталог + "Выгрузка.log";
	
	КомандаЗапуска = Новый Массив;
	КомандаЗапуска.Добавить(Параметры.КаталогBIN + "1cv8.exe");
	КомандаЗапуска.Добавить("DESIGNER");
	КомандаЗапуска.Добавить("/IBConnectionString");
	КомандаЗапуска.Добавить(Параметры.ПутьККонфигурации);
	КомандаЗапуска.Добавить("/N");
	КомандаЗапуска.Добавить(Параметры.Пользователь);
	КомандаЗапуска.Добавить("/P");
	КомандаЗапуска.Добавить(Параметры.Пароль);
	ОбщегоНазначенияКлиентСервер.ДополнитьМассив(КомандаЗапуска, ПереданныеКомандыЗапуска);
	КомандаЗапуска.Добавить("/Out");
	КомандаЗапуска.Добавить(ИмяФайлаСообщений);
	КомандаЗапуска.Добавить("/DisableStartupMessages");
	КомандаЗапуска.Добавить("/DisableStartupDialogs");
	
	ПараметрыЗапускаКоманды = ФайловаяСистема.ПараметрыЗапускаПрограммы();
	ПараметрыЗапускаКоманды.ДождатьсяЗавершения = Истина;
	
	РезультатЗапуска = ФайловаяСистема.ЗапуститьПрограмму(КомандаЗапуска, ПараметрыЗапускаКоманды);
	
	КодВозврата = РезультатЗапуска.КодВозврата;
	Если КодВозврата = 0 Тогда
		Результат.Успех = Истина;
		Возврат Результат;
	КонецЕсли;
	
	Результат.Кратко = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Не удалось выгрузить конфигурацию в XML (код ошибки ""%1"")'"),
		КодВозврата);
	Если ФайлСуществует(ИмяФайлаСообщений) Тогда
		ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаСообщений, , , , Ложь);
		Сообщения = СокрЛП(ЧтениеТекста.Прочитать());
		ЧтениеТекста.Закрыть();
		Если Сообщения <> "" Тогда
			Результат.Подробно = СтрЗаменить(Символы.ПС + Сообщения, Символы.ПС, Символы.ПС + Символы.Таб);
		КонецЕсли;
	КонецЕсли;
	Возврат Результат;
	
КонецФункции

Функция ФайлСуществует(ПолноеИмяФайла)
	Файл = Новый Файл(ПолноеИмяФайла);
	Возврат Файл.Существует();
КонецФункции

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

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

Процедура ЗаписатьТекстовыйФайл(ПолноеИмяФайла, Текст)
	ЗаписьТекста = Новый ЗаписьТекста(ПолноеИмяФайла, КодировкаТекста.UTF8);
	ЗаписьТекста.Записать(Текст);
	ЗаписьТекста.Закрыть();
КонецПроцедуры

Функция ПрочитатьДокументDOM(ПутьКФайлу)
	ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
	ПостроительDOM = Новый ПостроительDOM;
	ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
	ЧтениеXML.Закрыть();
	
	Возврат ДокументDOM;
КонецФункции

Функция ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь)
	Возврат ДокументDOM.ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь);
КонецФункции

Процедура ЗаписатьДокументDOM(ДокументDOM, ИмяФайла)
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.ОткрытьФайл(ИмяФайла);
	ЗаписьDOM = Новый ЗаписьDOM;
	ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML);
КонецПроцедуры

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

#Область ПакетнаяРегистрацияВнешнихОтчетовИОбработокВСправочнике

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

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

#Область Другие

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

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

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

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

// Для внутреннего использования.
//
// Возвращаемое значение:
//   см. СведенияОВнешнейОбработке 
//
Функция ПолучитьРегистрационныеДанные(Знач Объект, Знач ПараметрыРегистрации, Знач РезультатРегистрации)

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

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

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

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

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

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

// Преобразует строковое представление версии в числовое.
//
Функция ВерсияЧислом(ВерсияСтрокой)
	Если ПустаяСтрока(ВерсияСтрокой) Или ВерсияСтрокой = "0.0.0.0" Тогда
		Возврат 0;
	КонецЕсли;
	
	Разряд = 0;
	
	Результат = 0;
	
	ОписаниеТипаЧисло = Новый ОписаниеТипов("Число");
	Остаток = ВерсияСтрокой;
	ПозицияТочки = СтрНайти(Остаток, ".");
	Пока ПозицияТочки > 0 Цикл
		ЧислоСтрокой = Лев(Остаток, ПозицияТочки - 1);
		Число = ОписаниеТипаЧисло.ПривестиЗначение(ЧислоСтрокой);
		Результат = Результат * 1000 + Число;
		Остаток = Сред(Остаток, ПозицияТочки + 1);
		ПозицияТочки = СтрНайти(Остаток, ".");
		Разряд = Разряд + 1;
	КонецЦикла;
	
	Число = ОписаниеТипаЧисло.ПривестиЗначение(Остаток);
	Результат = Результат * 1000 + Число;
	Разряд = Разряд + 1;
	
	// Номера версии после 4 точки возвращает после запятой.
	// Например, для версии "1.2.3.4.5.6.7" вернет 1002003004,005006007.
	Если Разряд > 4 Тогда
		Результат = Результат / Pow(1000, Разряд - 4);
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

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

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