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

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

// Обработчики условных вызовов из БСП

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Для внутреннего использования
// 
// Возвращаемое значение:
//  Строка
//
Функция ИмяФайлаПакетаУстановки() Экспорт
	
	Возврат НСтр("ru = 'Автономная работа.zip'");
	
КонецФункции

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

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

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

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

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

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

#Область СлужебныеПроцедурыИФункцииИспользуемыеНаСторонеАвтономногоРабочегоМеста

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

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

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

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

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

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

// Для внутреннего использования
// 
// Возвращаемое значение:
//  РасписаниеРегламентногоЗадания:
//    *Месяцы - Массив из Число 
//    *ДниНедели - Массив из Число
//    *ПериодПовтораВТечениеДня - Число - 60 минут.
//    *ПериодПовтораДней - Число
//
Функция РасписаниеСинхронизацииДанныхПоУмолчанию() Экспорт // Каждый час
	
	Месяцы = Новый Массив;
	Для Сч = 1 По 12 Цикл
		Месяцы.Добавить(Сч);
	КонецЦикла;
	
	ДниНедели = Новый Массив;
	Для Сч = 1 По 7 Цикл
		ДниНедели.Добавить(Сч);
	КонецЦикла;
	
	Расписание = Новый РасписаниеРегламентногоЗадания;
	Расписание.Месяцы                   = Месяцы;
	Расписание.ДниНедели                = ДниНедели;
	Расписание.ПериодПовтораВТечениеДня = 60*60; // 60 минут
	Расписание.ПериодПовтораДней        = 1; // каждый день
	
	Возврат Расписание;
КонецФункции

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

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

// Для внутреннего использования
// 
// Параметры:
//  Интервал - Число - по умолчанию - 1 час.
// 
// Возвращаемое значение:
//  Булево 
// 
Функция СинхронизацияССервисомДавноНеВыполнялась(Знач Интервал = 3600) Экспорт // 1 час по умолчанию
	
	Возврат Истина;
	
КонецФункции

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

Функция ПоддерживаетсяПередачаБольшихФайлов() Экспорт
	
	МодульТехнологияСервиса = ОбщегоНазначения.ОбщийМодуль("ТехнологияСервиса");
	ВерсияБТС = МодульТехнологияСервиса.ВерсияБиблиотеки();
	
	Возврат ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияБТС, "1.2.2.24") >= 0;
	
КонецФункции

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

Функция ИспользоватьОптимизированнуюЗаписьСозданияАвтономногоРабочегоМеста() Экспорт 
	
	Возврат ПолучитьФункциональнуюОпцию("ИспользоватьОптимизированнуюЗаписьСозданияАвтономногоРабочегоМеста");
	
КонецФункции

Процедура ОткрытьЗаписьДанныхНачальногоОбраза(Получатель) Экспорт 
	
	ПараметрыВыгрузки = Получатель.ДополнительныеСвойства.ПараметрыВыгрузки;
	
	Если ПараметрыВыгрузки.ВыгруженныеДанные <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ПараметрыВыгрузки.ИспользоватьОптимизированнуюЗапись Тогда
		ПараметрыВыгрузки.НомерФайла = ПараметрыВыгрузки.НомерФайла + 1;
		ИмяФайлаДанных = СтрШаблон("data_%1.xml", Формат(ПараметрыВыгрузки.НомерФайла, "ЧГ=0"));
	Иначе 
		ИмяФайлаДанных = "data.xml";
	КонецЕсли;
	
	ПолноеИмяФайлаДанных = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
		ПараметрыВыгрузки.КаталогАрхива, ИмяФайлаДанных);
	
	ПотокПриемник = ФайловыеПотоки.Создать(ПолноеИмяФайлаДанных);

	ВыгруженныеДанные = Новый ЗаписьXML;
	ВыгруженныеДанные.ОткрытьПоток(ПотокПриемник);
	
	ВыгруженныеДанные.ЗаписатьОбъявлениеXML();
	ВыгруженныеДанные.ЗаписатьНачалоЭлемента("Data");
	ВыгруженныеДанные.ЗаписатьСоответствиеПространстваИмен("xsd", "http://www.w3.org/2001/XMLSchema");
	ВыгруженныеДанные.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
	ВыгруженныеДанные.ЗаписатьСоответствиеПространстваИмен("v8",  "http://v8.1c.ru/data");
	
	ПараметрыВыгрузки.ВыгруженныеДанные = ВыгруженныеДанные;
	ПараметрыВыгрузки.ПотокПриемник = ПотокПриемник;
	ПараметрыВыгрузки.ИмяФайлаДанных = ПолноеИмяФайлаДанных;
	
КонецПроцедуры

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

Процедура ЗакрытьЗаписьДанныхНачальногоОбраза(Получатель, НачальныйОбразСформирован = Ложь) Экспорт 
	
	ПараметрыВыгрузки = Получатель.ДополнительныеСвойства.ПараметрыВыгрузки;
	ЗакрытьЗапись = Ложь;
	
	Если НачальныйОбразСформирован Тогда
		ЗакрытьЗапись = Истина;
	ИначеЕсли ПараметрыВыгрузки.ИспользоватьОптимизированнуюЗапись Тогда
		
		Если ПараметрыВыгрузки.ЗаписаноЭлементов >= ПараметрыВыгрузки.МаксимальноеКоличествоЭлементов Тогда
			ЗакрытьЗапись = Истина;
		ИначеЕсли ПараметрыВыгрузки.ЗаписаноЭлементовПослеПроверкиРазмераФайла >= ПараметрыВыгрузки.КоличествоЭлементовПроверкиРазмераФайла Тогда
			
			ФайлДанных = Новый Файл(ПараметрыВыгрузки.ИмяФайлаДанных);
			Если ФайлДанных.Существует() И ФайлДанных.Размер() >= ПараметрыВыгрузки.МаксимальныйРазмерФайла Тогда
				ЗакрытьЗапись = Истина;
			КонецЕсли;
			
			ПараметрыВыгрузки.ЗаписаноЭлементовПослеПроверкиРазмераФайла = 0;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если Не ЗакрытьЗапись Тогда
		Возврат;
	КонецЕсли;
	
	Если ПараметрыВыгрузки.ВыгруженныеДанные <> Неопределено Тогда
		
		ПараметрыВыгрузки.ВыгруженныеДанные.ЗаписатьКонецЭлемента(); // Data
		ПараметрыВыгрузки.ВыгруженныеДанные.Закрыть();
		
		ПараметрыВыгрузки.ВыгруженныеДанные = Неопределено;
		
	КонецЕсли;
	
	Если ПараметрыВыгрузки.ПотокПриемник <> Неопределено Тогда
		
		ПараметрыВыгрузки.ПотокПриемник.Закрыть();
		
		ПараметрыВыгрузки.ПотокПриемник = Неопределено;
		
	КонецЕсли;
	
	Если ПараметрыВыгрузки.ИспользоватьОптимизированнуюЗапись И ПараметрыВыгрузки.ЗаписаноЭлементов > 0 Тогда
		
		ПараметрыВыгрузки.ЗаписаноЭлементов = 0;
		ПараметрыВыгрузки.ЗаписаноЭлементовПослеПроверкиРазмераФайла = 0;
		
		ИмяФайлаАрхива = СтрШаблон("data_%1.zip", Формат(ПараметрыВыгрузки.НомерФайла, "ЧГ=0"));
		ПолноеИмяФайлаАрхива = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
			ПараметрыВыгрузки.КаталогАрхива, ИмяФайлаАрхива);
			
		Архиватор = Новый ЗаписьZipФайла(ПолноеИмяФайлаАрхива,,,, УровеньСжатияZIP.Максимальный);
		Архиватор.Добавить(ПараметрыВыгрузки.ИмяФайлаДанных);
		Архиватор.Записать();
		
		Попытка
			УдалитьФайлы(ПараметрыВыгрузки.ИмяФайлаДанных);
		Исключение
			ЗаписьЖурналаРегистрации(
				СобытиеЖурналаРегистрацииСозданиеАвтономногоРабочегоМеста(),
				УровеньЖурналаРегистрации.Ошибка,
				,
				,
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
	КонецЕсли;
	
КонецПроцедуры

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

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

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

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

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

// Для внутреннего использования
// 
Функция НаименованиеАвтономногоРабочегоМестаПоУмолчанию()
	
	Результат = НСтр("ru = 'Автономная работа - %1'");
	
	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Результат, ПолноеИмяПользователя());
	
КонецФункции

// Для внутреннего использования
// 
Функция ДопустимыеСимволыПрефиксаАвтономногоРабочегоМеста()
	
	Возврат НСтр("ru = 'АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЭЮЯабвгдежзиклмнопрстуфхцчшэюя'"); // 54 символа
	
КонецФункции

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

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

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

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

Функция ПолучитьУпорядоченныйСписокФайловДанных(КаталогИнформационнойБазы)
	
	НайденныеФайлыАрхиваДанных = НайтиФайлы(КаталогИнформационнойБазы, "data_*.zip", Ложь);
	
	Если НайденныеФайлыАрхиваДанных.Количество() = 0 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ТипЧисло = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Неотрицательный));
	
	ТаблицаФайлов = Новый ТаблицаЗначений;
	ТаблицаФайлов.Колонки.Добавить("ИмяФайла");
	ТаблицаФайлов.Колонки.Добавить("НомерФайла", ТипЧисло);
	
	Для Каждого ФайлАрхиваДанных Из НайденныеФайлыАрхиваДанных Цикл
		
		ЧастиИмениФайла = СтрРазделить(ФайлАрхиваДанных.ИмяБезРасширения, "_", Ложь);
		Если ЧастиИмениФайла.Количество() <> 2 Тогда
			ВызватьИсключение НСтр("ru = 'Неверный формат имени файла данных'");
		КонецЕсли;
		
		НомерФайла = ТипЧисло.ПривестиЗначение(ЧастиИмениФайла[1]);
		Если НомерФайла = 0 Тогда
			ВызватьИсключение НСтр("ru = 'Неверный формат имени файла данных'");
		КонецЕсли;
		
		ЧтениеАрхива = Новый ЧтениеZipФайла(ФайлАрхиваДанных.ПолноеИмя);
		ЧтениеАрхива.ИзвлечьВсе(КаталогИнформационнойБазы);
		ЧтениеАрхива.Закрыть();
		
		СтрокаТаблицы = ТаблицаФайлов.Добавить();
		СтрокаТаблицы.ИмяФайла = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
			КаталогИнформационнойБазы, ФайлАрхиваДанных.ИмяБезРасширения + ".xml");
		СтрокаТаблицы.НомерФайла = НомерФайла;
		
		Попытка
			УдалитьФайлы(ФайлАрхиваДанных.ПолноеИмя);
		Исключение
			ЗаписьЖурналаРегистрации(
				СобытиеЖурналаРегистрацииСозданиеАвтономногоРабочегоМеста(),
				УровеньЖурналаРегистрации.Ошибка,
				,
				,
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
	КонецЦикла;
	
	ТаблицаФайлов.Сортировать("НомерФайла");
	
	СписокФайлов = Новый Массив();
	Для Каждого СтрокаТаблицы Из ТаблицаФайлов Цикл
		СписокФайлов.Добавить(СтрокаТаблицы.ИмяФайла);
	КонецЦикла;
	
	Возврат СписокФайлов;
	
КонецФункции

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

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

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

#Область ОбработчикиУсловныхВызововВДругиеПодсистемы

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

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

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