[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Процедура ИмяФункции(АнализируемоеЗначение, ОбъектыВыгруженныеСОшибками, массивДанных)

	Если Не ЗначениеЗаполнено(АнализируемоеЗначение) Тогда
		Возврат;
	КонецЕсли;

	ОбъектМД = СсылочныеТипы.Получить(ТипЗнч(АнализируемоеЗначение));

	Если ОбъектМД = Неопределено Тогда
		Возврат; // это не ссылка
	КонецЕсли;

	Если СсылкаВыгружена(АнализируемоеЗначение) Тогда
		Возврат; // объект уже был выгружен
	КонецЕсли;

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

	СтрокаТаблицы = СоставВспомогательнойВыгрузки.Найти(ОбъектМД, "ОбъектМД");
	Если СтрокаТаблицы <> Неопределено Тогда

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

	КонецЕсли;

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

Функция ПолучитьМассивКолонокДвижения(ТаблицаДвижений, РегистрБухгалтерии = Ложь)

	МассивКолонок = Новый Массив();
	Для Каждого КолонкаТаблицы Из ТаблицаДвижений.Колонки Цикл

		Если КолонкаТаблицы.Имя = "МоментВремени"
			ИЛИ Найти(КолонкаТаблицы.Имя, "ВидСубконтоДт") = 1
			ИЛИ Найти(КолонкаТаблицы.Имя, "ВидСубконтоКт") = 1 Тогда

			Продолжить;

		КонецЕсли;

		Если Найти(КолонкаТаблицы.Имя, "СубконтоДт") = 1 И РегистрБухгалтерии Тогда

			Если МассивКолонок.Найти("СубконтоДт") = Неопределено Тогда
				МассивКолонок.Добавить("СубконтоДт");
			Конецесли;

			Продолжить;

		КонецЕсли;

		Если Найти(КолонкаТаблицы.Имя, "СубконтоКт") = 1 И РегистрБухгалтерии Тогда

			Если МассивКолонок.Найти("СубконтоКт") = Неопределено Тогда
				МассивКолонок.Добавить("СубконтоКт");
			КонецЕсли;

			Продолжить;

		КонецЕсли;

		МассивКолонок.Добавить(КолонкаТаблицы.Имя);

	КонецЦикла;

	Возврат МассивКолонок;

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

Процедура ВыгрузитьПодчиненныеЗначенияНабора(Движение, МассивКолонок, ОбъектыВыгруженныеСОшибками, массивДанных)

	Для Каждого ЗаписьИзНабора Из Движение Цикл

		Для Каждого Колонка Из МассивКолонок Цикл

			Если Колонка = "СубконтоДт"
				ИЛИ Колонка = "СубконтоКт" Тогда

				Значение = ЗаписьИзНабора[Колонка];
				Для Каждого КлючИЗначение Из Значение Цикл

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

				КонецЦикла;

			Иначе

				СохраненноеЗначение = ЗаписьИзНабора[Колонка];
				ЗаписатьЗначениеПриНеобходимости(СохраненноеЗначение, ОбъектыВыгруженныеСОшибками, массивДанных);

			КонецЕсли;

		КонецЦикла;

	КонецЦикла;

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

// Процедура записывает наборы записей регистра (накопления, бухгалтерии...)
//
// Параметры
//   ЗаписьXML - объект, через которых происходит запись объектов ИБ
//   СтрокаДереваМетаданных - строка дерева метаданных, соответствующая регистру
//

Процедура ЗаписьРегистра(СтрокаДереваМетаданных, ОбъектыВыгруженныеСОшибками, РегистрБухгалтерии = Ложь, массивДанных)

	ПодзаголовокОкнаИсполнения = СтрокаДереваМетаданных.ОбъектМД.ПолноеИмя();
	ОкноИсполненияОбщееКоличество = 1;
	//ОкноИсполненияОбработано = 0;

	МенеджерНабораЗаписей = СтрокаДереваМетаданных.ЭлементОписания.Менеджер[СтрокаДереваМетаданных.ОбъектМД.Имя];

	ИмяТаблицыДляЗапроса = СтрокаДереваМетаданных.ЭлементОписания.ДляЗапроса;

	ЗаписьЧерезНаборЗаписей(МенеджерНабораЗаписей, ИмяТаблицыДляЗапроса,
		СтрокаДереваМетаданных.ОбъектМД.Имя, СтрокаДереваМетаданных, ОбъектыВыгруженныеСОшибками, РегистрБухгалтерии, массивДанных);

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

// Процедура записывает данные, доступ к которым осуществляется через набор записей
//
// Параметры
//   ЗаписьXML - объект, через которых происходит запись объектов ИБ
//   СтрокаДереваМетаданных - строка дерева метаданных, соответствующая регистру
//

[Assistant] Процедура ЗаписатьЗначениеПриНеобходимости(АнализируемоеЗначение, ОбъектыВыгруженныеСОшибками, массивДанных)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Процедура ИмяФункции(МенеджерНабораЗаписей, ДляЗапроса, ИмяОбъекта,
	СтрокаДереваМетаданных = Неопределено, ОбъектыВыгруженныеСОшибками, РегистрБухгалтерии = Ложь, массивДанных)

	// получить состав колонок записи регистра и проверить наличие хотя бы одной записи
	Если ДляЗапроса = "РегистрБухгалтерии." Тогда
		ИмяТаблицыДляЗапроса = ДляЗапроса + ИмяОбъекта + ".ДвиженияССубконто";
	Иначе
		ИмяТаблицыДляЗапроса = ДляЗапроса + ИмяОбъекта;
	КонецЕсли;

	Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 1 * ИЗ " + ИмяТаблицыДляЗапроса + " КАК ТаблицаОбъекта_" + ИмяОбъекта);
	РезультатЗапросаПоСоставу = Запрос.Выполнить();
	Если РезультатЗапросаПоСоставу.Пустой() Тогда
		Возврат;
	КонецЕсли;

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

	// выгрузка регистров осуществляется через его набор записей
	НаборЗаписей = МенеджерНабораЗаписей.СоздатьНаборЗаписей();

	СтрокаПолейОтбора = ПолучитьСтрокуПолейОтбораРегистра(МенеджерНабораЗаписей);

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

	ОкноИсполненияОбщееКоличество = ВыборкаИзРезультата.Количество();
	//ОкноИсполненияОбработано = 0;
	//ОкноИсполнения.ОбновитьВерхнююГраницу();

	КоличествоПолейОтбора = НаборЗаписей.Отбор.Количество();

	// читаем наборы записей с различным составом отбора и записываем их
	Пока ВыборкаИзРезультата.Следующий() Цикл

		// Пересоздание набора, чтоб чтоб разные экземпляры объекта в МассивДанных попали
		НаборЗаписей = МенеджерНабораЗаписей.СоздатьНаборЗаписей();
		Отбор = НаборЗаписей.Отбор;

		// Отбор устанавливаем для регистров, у которых есть хотя бы один отбор (измерение)
		Если КоличествоПолейОтбора <> 0 Тогда

			Для Каждого Колонка Из РезультатЗапросаПоЗначениямОтбора.Колонки Цикл
				Отбор[Колонка.Имя].Значение = ВыборкаИзРезультата[Колонка.Имя];
				Отбор[Колонка.Имя].ВидСравнения = ВидСравнения.Равно;
				Отбор[Колонка.Имя].Использование = Истина;
			КонецЦикла;

		КонецЕсли;

		НаборЗаписей.Прочитать();

		Если мНаличиеВыгрузкиПодчиненныхОбъектов Тогда

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

		КонецЕсли;

		ВсегоОбработаноОбъектов = ВсегоОбработанныхЗаписей();
		Попытка

			//ВыполнитьВспомогательныеДействияДляЗаписиXML(ВсегоОбработаноОбъектов, ЗаписьXML, ТолькоПроверкаНедопустимыхСимволов);

			//ЗаписатьXML(ЗаписьXML, НаборЗаписей);

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

		Исключение

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

				ИтоговаяСтрокаСообщения = "Ошибка при выгрузке набора записей регистра: " + ДляЗапроса + ИмяОбъекта + "
				|" + СтрокаОписанияОшибки;

				Сообщить(ИтоговаяСтрокаСообщения);

				ВызватьИсключение ИтоговаяСтрокаСообщения;

			//КонецЕсли;

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

		ОбработанныхНаборовЗаписей = ОбработанныхНаборовЗаписей + 1;
		//ОкноИсполненияОбработано = ОкноИсполненияОбработано + 1;

		ПоказатьПользователюИнформациюОСостоянииВыгрузки(ВсегоОбработаноОбъектов, ОбъектыВыгруженныеСОшибками);

	КонецЦикла;

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

Процедура ПоказатьПользователюИнформациюОСостоянииВыгрузки(ВсегоОбработаноОбъектов, ОбъектыВыгруженныеСОшибками)

	#Если Клиент Тогда

		Если ВсегоОбработаноОбъектов %100 = 0 Тогда

			Если ОбъектыВыгруженныеСОшибками <> Неопределено
				И ОбъектыВыгруженныеСОшибками.Количество() > 0 Тогда

				Состояние("Выгруженных объектов - " + ВсегоОбработаноОбъектов + ", ошибок при выгрузке - " + ОбъектыВыгруженныеСОшибками.Количество());

			Иначе
				Состояние("Выгруженных объектов - " + ВсегоОбработаноОбъектов);
			КонецЕсли;

		КонецЕсли;

	#КонецЕсли

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

Функция ПолучитьРезультатЗапросаСКД(СКД)

	Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
	Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СКД));
	Компоновщик.ЗагрузитьНастройки(СКД.НастройкиПоУмолчанию);

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

	КонецЦикла;

	ПолеГруппировки = Компоновщик.Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
	ПолеГруппировки.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));

	//#Если Клиент Тогда
	//
	//НастройкиКомпоновщикаXDTO = СериализаторXDTO.ЗаписатьXDTO(Компоновщик.Настройки);
	//СКДXDTO = СериализаторXDTO.ЗаписатьXDTO(СКД);
	//СКДXDTO.defaultSettings = НастройкиКомпоновщикаXDTO;
	//СКД = СериализаторXDTO.ПрочитатьXDTO(СКДXDTO);
	//
	//КонструкторСКД = Новый КонструкторСхемыКомпоновкиДанных(СКД);
	//КонструкторСКД.Редактировать(ПолучитьФорму("Форма"));
	//#КонецЕсли

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

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

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

[Assistant]
Процедура ЗаписьЧерезНаборЗаписей(МенеджерНабораЗаписей, ДляЗапроса, ИмяОбъекта,
	СтрокаДереваМетаданных = Неопределено, ОбъектыВыгруженныеСОшибками, РегистрБухгалтерии = Ложь, массивДанных)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(Знач КонтейнерРезультатовТестирования, Знач ИдентификаторТеста, Знач ВключатьПодчиненные = Ложь) Экспорт
	Перем Результат;

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

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

Функция ПараметрыМетода(Знач Парам1, Знач Парам2 = Неопределено, Знач Парам3 = Неопределено, Знач Парам4 = Неопределено, Знач Парам5 = Неопределено, Знач Парам6 = Неопределено, Знач Парам7 = Неопределено, Знач Парам8 = Неопределено, Знач Парам9 = Неопределено) Экспорт
	ВсеПараметры = Новый Массив;
	ВсеПараметры.Добавить(Парам1);
	ВсеПараметры.Добавить(Парам2);
	ВсеПараметры.Добавить(Парам3);
	ВсеПараметры.Добавить(Парам4);
	ВсеПараметры.Добавить(Парам5);
	ВсеПараметры.Добавить(Парам6);
	ВсеПараметры.Добавить(Парам7);
	ВсеПараметры.Добавить(Парам8);
	ВсеПараметры.Добавить(Парам9);

	ИндексСПоследнимПараметром = 0;
	Для Сч = 0 По ВсеПараметры.ВГраница() Цикл
		Индекс = ВсеПараметры.ВГраница() - Сч;
		Если ВсеПараметры[Индекс] <> Неопределено Тогда
			ИндексСПоследнимПараметром = Индекс;
			Прервать;
		КонецЕсли;
	КонецЦикла;

	ПараметрыМетода = Новый Массив;
	Для Сч = 0 По ИндексСПоследнимПараметром Цикл
		ПараметрыМетода.Добавить(ВсеПараметры[Сч]);
	КонецЦикла;

	Возврат ПараметрыМетода;
КонецФункции
// } Helpers

// { Подсистема конфигурации xUnitFor1C

Функция ПолучитьГлавнуюПодсистему() Экспорт

	КоллекцияПодсистем = Метаданные.Подсистемы;

	ГлавнаяПодсистема = Неопределено;

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

	Если ГлавнаяПодсистема = Неопределено Тогда
		ВызватьИсключение "Не удалось главную подсистему """ + ИмяГлавнойПодсистемы + """!";
	КонецЕсли;

	Возврат ГлавнаяПодсистема;

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

Функция НайтиПодсистемуПоИмени(КоллекцияПодсистем, ИмяПодсистемыДляПоиска)

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

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

Функция ПолучитьПлагины() Экспорт

	ГлавнаяПодсистема = ПолучитьГлавнуюПодсистему();

	СтруктураПлагинов = Новый Структура;

	ДлинаПрефикса = СтрДлина(ИспользуемыйПрефиксПодсистемы);
	РезультатПоиска = ГлавнаяПодсистема.Подсистемы.Найти("Plugins");
	Если РезультатПоиска = Неопределено Тогда
		ВызватьИсключение НСтр(
			"ru = 'Подсистему ""Plugins"" не удалось найти или она не подчинена подсистеме ""xUnitFor1C""'");
	КонецЕсли;

	КоллекцияПлагинов = РезультатПоиска.Состав;
	Для Каждого Плагин Из КоллекцияПлагинов Цикл
		ИмяПлагина = Прав(Плагин.Имя, СтрДлина(Плагин.Имя) - ДлинаПрефикса);
		СтруктураПлагинов.Вставить(ИмяПлагина, Плагин.Имя);
	КонецЦикла;

	Возврат СтруктураПлагинов;

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

Функция ПолучитьУтилиты() Экспорт

	ГлавнаяПодсистема = ПолучитьГлавнуюПодсистему();

	СтруктураПлагинов = Новый Структура;

	ДлинаПрефикса = СтрДлина(ИспользуемыйПрефиксПодсистемы);

	КоллекцияПлагинов = ГлавнаяПодсистема.Подсистемы.Utils.Состав;
	Для Каждого Плагин Из КоллекцияПлагинов Цикл
		ИмяПлагина = Прав(Плагин.Имя, СтрДлина(Плагин.Имя) - ДлинаПрефикса);
		СтруктураПлагинов.Вставить(ИмяПлагина, Плагин.Имя);
	КонецЦикла;

	Возврат СтруктураПлагинов;

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

Функция ОбработкаЯвляетсяВстроеннойВКонфигурацию() Экспорт

	ПолноеИмяТекущейОбработки = ЭтотОбъект.Метаданные().ПолноеИмя();
	ВстроеннаяВКонфигурациюОбработка = Метаданные.НайтиПоПолномуИмени(ПолноеИмяТекущейОбработки);

	ОбработкаВстроенаяВСоставКонфигурации = НЕ (ВстроеннаяВКонфигурациюОбработка = Неопределено);

	Возврат ОбработкаВстроенаяВСоставКонфигурации;

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

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

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

	Возврат СтруктураПараметров;

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

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

Функция ПеременнаяСодержитСвойство(Переменная, ИмяСвойства)
     // Инициализируем структуру для теста
     // с ключом (значение переменной "ИмяСвойства")
     // и значением произвольного GUID'а
     GUIDПроверка = Новый УникальныйИдентификатор;
     СтруктураПроверка = Новый Структура;
     СтруктураПроверка.Вставить(ИмяСвойства, GUIDПроверка);
     // Заполняем созданную структуру из переданного
     // значения переменной
     ЗаполнитьЗначенияСвойств(СтруктураПроверка, Переменная);
     // Если значение для свойства структуры осталось
     // NULL, то искомое свойство не найдено,
     // и наоборот.
     Если СтруктураПроверка[ИмяСвойства] = GUIDПроверка Тогда
          Возврат Ложь;
     Иначе
          Возврат Истина;
     КонецЕсли;
КонецФункции

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

	Если ПеременнаяСодержитСвойство(ОбъектЗаполнения, ИмяСвойство) Тогда
		ОбъектЗаполнения[ИмяСвойство] = ЗначениеСвойства;
	КонецЕсли;

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

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

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

	ДлинаПрефикса = СтрДлина(ИспользуемыйПрефиксПодсистемы);
	Если Лев(Идентификатор, ДлинаПрефикса) = ИспользуемыйПрефиксПодсистемы Тогда
		Возврат Идентификатор;
	Иначе
		Возврат ИспользуемыйПрефиксПодсистемы + Идентификатор;
	КонецЕсли;

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

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

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

	ДлинаПрефикса = СтрДлина(ИспользуемыйПрефиксПодсистемы);
	Если Лев(Идентификатор, ДлинаПрефикса) = ИспользуемыйПрефиксПодсистемы Тогда
		Возврат Прав(Идентификатор, СтрДлина(Идентификатор) - ДлинаПрефикса);
	Иначе
		Возврат Идентификатор;
	КонецЕсли;

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

[Assistant] Функция НайтиРезультатТестированияПоИдентификатору(Знач КонтейнерРезультатовТестирования, Знач ИдентификаторТеста, Знач ВключатьПодчиненные = Ложь)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(Идентификатор, ВстроенаВКонфигурацию = Ложь, ЭтоОтчет = Ложь) Экспорт

	ОбъектПлагина = Неопределено;

	Если ЭтотОбъект.ЭтоВстроеннаяОбработка
		ИЛИ ВстроенаВКонфигурацию = Истина Тогда

		ИдентификаторСПрефиксомПодсистемы = ДополнитьИдентификаторПрефиксомПодсистемы(Идентификатор);
		ИдентификаторБезПрефиксаПодсистемы = ПолучитьИдентификаторБезПрефиксаПодсистемы(Идентификатор);

		Если ЭтоОтчет = Истина Тогда
			МенеджерВидаОбъектов = Отчеты;
			МетаданныеВидаОбъектов = Метаданные.Отчеты;
		Иначе
			МенеджерВидаОбъектов = Обработки;
			МетаданныеВидаОбъектов = Метаданные.Обработки;
		КонецЕсли;

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

	КонецЕсли;

	Если ОбъектПлагина = Неопределено Тогда
		Если ЭтоОтчет = Истина Тогда
			ОбъектПлагина = ВнешниеОтчеты.Создать(Идентификатор, Ложь);
		Иначе
			ОбъектПлагина = ВнешниеОбработки.Создать(Идентификатор, Ложь);
		КонецЕсли;
	КонецЕсли;

	Возврат ОбъектПлагина;

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

// } Подсистема конфигурации xUnitFor1C

Инициализация();

[Assistant] Функция СоздатьОбъектПлагина(Идентификатор, ВстроенаВКонфигурацию = Ложь, ЭтоОтчет = Ложь)


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ПрогнатьФичи`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция ПрогнатьФичи(Знач КаталогФайловПокрытия)
ФичиПрошли_core = ПрогнатьФичи_core(КаталогФайловПокрытия);
	ФичиПрошли_cmd = ПрогнатьФичи_cmd(КаталогФайловПокрытия);

	// Закомментировано, т.к. при сборке exe возникает ошибка
	// ФичиПрошли_exe = ПрогнатьФичи_exe(КаталогФайловПокрытия);
	ФичиПрошли_exe = Истина;

	// ПрогнатьФичи_opm всегда выполнять последней, т.к. в процессе ее выполнения очищается ./oscript_modules
	ФичиПрошли_opm = ПрогнатьФичи_opm(КаталогФайловПокрытия);
    // TODO: допиши оставшуюся часть

[Assistant]
Функция ПрогнатьФичи(Знач КаталогФайловПокрытия)

	ФичиПрошли_core = ПрогнатьФичи_core(КаталогФайловПокрытия);
	ФичиПрошли_cmd = ПрогнатьФичи_cmd(КаталогФайловПокрытия);

	// Закомментировано, т.к. при сборке exe возникает ошибка
	// ФичиПрошли_exe = ПрогнатьФичи_exe(КаталогФайловПокрытия);
	ФичиПрошли_exe = Истина;

	// ПрогнатьФичи_opm всегда выполнять последней, т.к. в процессе ее выполнения очищается ./oscript_modules
	ФичиПрошли_opm = ПрогнатьФичи_opm(КаталогФайловПокрытия);

	Возврат
		ФичиПрошли_opm
		И ФичиПрошли_core
		И ФичиПрошли_cmd
		И ФичиПрошли_exe;
КонецФункции

ИмяКаталогаФайловПокрытия = "coverage";
КаталогФайловПокрытия = "";

Для Каждого Элемент Из АргументыКоманднойСтроки Цикл
	Если Элемент = "coverage" Тогда

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

		Прервать;
	КонецЕсли;
КонецЦикла;

ТестыПрошли = Истина;

Попытка
	ТестыПрошли = ПрогнатьТесты();
Исключение
	ТестыПрошли = Ложь;
	Сообщить(СтрШаблон("Тесты через 1testrunner выполнены неудачно
	|%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
КонецПопытки;

ФичиПрошли = Истина;

Попытка
	ФичиПрошли = ПрогнатьФичи(КаталогФайловПокрытия);
Исключение
	ФичиПрошли = Ложь;
	Сообщить(СтрШаблон("Тесты поведения через 1bdd выполнены неудачно
	|%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
КонецПопытки;

Сообщить(СтрШаблон("Результат прогона всех фич <%1>
|", ФичиПрошли));

Если Не ФичиПрошли Или Не ТестыПрошли Тогда
	ВызватьИсключение "Тестирование завершилось неудачно!";
КонецЕсли;


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ОписаниеОкружения`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция ОписаниеОкружения()
Экспорт

	СистемнаяИнформация = Новый СистемнаяИнформация();
	ОписаниеСерверногоОкружения = ЮТМетодыСлужебный.ВызватьФункциюКонфигурацииНаСервере("ЮТОкружениеСлужебныйКлиентСервер",
																						"ОписаниеСерверногоОкружения");

	Платформа = Платформа(СистемнаяИнформация);

	Окружение = ЮТФабрика.НовоеОписаниеОкружения();

	Окружение.Конфигурация = ОписаниеСерверногоОкружения.Конфигурация;
	Окружение.ВерсияКонфигурации = ОписаниеСерверногоОкружения.ВерсияКонфигурации;
	Окружение.ВерсияПлатформы = СистемнаяИнформация.ВерсияПриложения;
	Окружение.ИнформационнаяСреда = "DEV";
	Окружение.ТестовыйДвижок = ОписаниеСерверногоОкружения.ТестовыйДвижок;
	Окружение.ВерсияТестовогоДвижка = ОписаниеСерверногоОкружения.ВерсияТестовогоДвижка;

	Окружение.ВстроенныйЯзык = ОписаниеСерверногоОкружения.ВстроенныйЯзык;

	Окружение.ОперационнаяСистемаКлиент = Платформа.ОперационнаяСистема;
	Окружение.АрхитектураКлиент = Платформа.Архитектура;

	Окружение.ОперационнаяСистемаСервер = ОписаниеСерверногоОкружения.ОперационнаяСистема;
	Окружение.АрхитектураСервер = ОписаниеСерверногоОкружения.Архитектура;
    // TODO: допиши оставшуюся часть

[Assistant]
//©///////////////////////////////////////////////////////////////////////////©//
//
//  Copyright 2021-2025 BIA-Technologies Limited Liability Company
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//

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

// Собирает информацию об окружения, как сервера, так и клиента.
//
// Возвращаемое значение:
//  см. ЮТФабрика.НовоеОписаниеОкружения
Функция ОписаниеОкружения() Экспорт

	СистемнаяИнформация = Новый СистемнаяИнформация();
	ОписаниеСерверногоОкружения = ЮТМетодыСлужебный.ВызватьФункциюКонфигурацииНаСервере("ЮТОкружениеСлужебныйКлиентСервер",
																						"ОписаниеСерверногоОкружения");

	Платформа = Платформа(СистемнаяИнформация);

	Окружение = ЮТФабрика.НовоеОписаниеОкружения();

	Окружение.Конфигурация = ОписаниеСерверногоОкружения.Конфигурация;
	Окружение.ВерсияКонфигурации = ОписаниеСерверногоОкружения.ВерсияКонфигурации;
	Окружение.ВерсияПлатформы = СистемнаяИнформация.ВерсияПриложения;
	Окружение.ИнформационнаяСреда = "DEV";
	Окружение.ТестовыйДвижок = ОписаниеСерверногоОкружения.ТестовыйДвижок;
	Окружение.ВерсияТестовогоДвижка = ОписаниеСерверногоОкружения.ВерсияТестовогоДвижка;

	Окружение.ВстроенныйЯзык = ОписаниеСерверногоОкружения.ВстроенныйЯзык;

	Окружение.ОперационнаяСистемаКлиент = Платформа.ОперационнаяСистема;
	Окружение.АрхитектураКлиент = Платформа.Архитектура;

	Окружение.ОперационнаяСистемаСервер = ОписаниеСерверногоОкружения.ОперационнаяСистема;
	Окружение.АрхитектураСервер = ОписаниеСерверногоОкружения.Архитектура;

	Окружение.ФайловаяБаза = ЭтоФайловаяБаза();

	Окружение.Расширения = ОписаниеСерверногоОкружения.Расширения;
#Если ВебКлиент Тогда
	Окружение.ВебКлиент = Истина;
#ИначеЕсли ТолстыйКлиентОбычноеПриложение Тогда
	Окружение.ОбычноеПриложение = Истина;
	Окружение.ТолстыйКлиент = Истина;
#ИначеЕсли ТолстыйКлиентУправляемоеПриложение Тогда
	Окружение.ТолстыйКлиент = Истина;
#КонецЕсли

	//@skip-check use-non-recommended-method
	Окружение.ВремяЗапуска = ТекущаяДата(); // BSLLS:DeprecatedCurrentDate-off

	//@skip-check constructor-function-return-section
	Возврат Окружение;

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

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

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

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

	Окружение = ОписаниеОкружения();
	ЮТКонтекстСлужебный.УстановитьЗначениеКонтекста("Окружение", Окружение, Истина);

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

Функция ЭтоФайловаяБаза()

	Возврат СтрНайти(Врег(СтрокаСоединенияИнформационнойБазы()), "FILE=") = 1;

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

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

	ОперационнаяСистема = Неопределено;
	Архитектура = Неопределено;

	Linux = "Linux";
	Windows = "Windows";
	MacOS = "MacOS";

	//@skip-check bsl-variable-name-invalid
	x86 = "i386";
	//@skip-check bsl-variable-name-invalid
	x64 = "x86_64";

	ТипКлиентскойПлатформы = СистемнаяИнформация.ТипПлатформы;

	Если ТипКлиентскойПлатформы = ТипПлатформы.Linux_x86 Тогда
		ОперационнаяСистема = Linux;
		Архитектура = x86;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.Linux_x86_64 Тогда
		ОперационнаяСистема = Linux;
		Архитектура = x64;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.Windows_x86 Тогда
		ОперационнаяСистема = Windows;
		Архитектура = x86;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.Windows_x86_64 Тогда
		ОперационнаяСистема = Windows;
		Архитектура = x64;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.MacOS_x86 Тогда
		ОперационнаяСистема = MacOS;
		Архитектура = x86;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.MacOS_x86_64 Тогда
		ОперационнаяСистема = MacOS;
		Архитектура = x64;
	Иначе
		ВызватьИсключение "Неподдерживаемый тип платформы";
	КонецЕсли;

	Возврат Новый Структура("ОперационнаяСистема, Архитектура", ОперационнаяСистема, Архитектура);

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

#Если Сервер Тогда
Функция ОписаниеСерверногоОкружения() Экспорт

	СистемнаяИнформация = Новый СистемнаяИнформация();
	Платформа = Платформа(СистемнаяИнформация);

	Окружение = Новый Структура;
	Окружение.Вставить("ОперационнаяСистема", Платформа.ОперационнаяСистема);
	Окружение.Вставить("Архитектура", Платформа.Архитектура);

	ЭтоРусскийВстроенныйЯзык = Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский;
	Окружение.Вставить("ВстроенныйЯзык", Формат(ЭтоРусскийВстроенныйЯзык, "БЛ=en; БИ=ru;"));

	Расширение = Метаданные.ОбщиеМодули.ЮТОкружениеСлужебныйКлиентСервер.РасширениеКонфигурации();
	Окружение.Вставить("ТестовыйДвижок", Расширение.Имя);
	Окружение.Вставить("ВерсияТестовогоДвижка", Расширение.Версия);
	Окружение.Вставить("Конфигурация", Метаданные.Представление());
	Окружение.Вставить("ВерсияКонфигурации", Метаданные.Версия);

	Окружение.Вставить("Расширения", Новый Массив);

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

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

	Возврат  Окружение;

КонецФункции
#КонецЕсли

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


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

//©///////////////////////////////////////////////////////////////////////////©//
//
//  Copyright 2021-2025 BIA-Technologies Limited Liability Company
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//

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

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

	ПараметрыИсполнения = ЮТАсинхроннаяОбработкаСлужебныйКлиент.ЦепочкаАсинхроннойОбработки();
	ПараметрыИсполнения.Вставить("ФинальныйОбработчик", Обработчик);

	КаталогПроекта = ЮТНастройкиВыполнения.КаталогПроекта();

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

	ПолныйПуть = ЮТФайлы.ОбъединитьПути(КаталогПроекта, ПутьКФайлуПроекта);

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

	ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПроверкиСуществования");
	ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПроверкиКаталога");
	ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикРезультатовПоиска");
	ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПереместитьФайлы");
	ДобавитьОбработчикЦепочки(ПараметрыИсполнения, "ОбработчикПеремещения");
	ПараметрыИсполнения.Цепочка.Добавить(Обработчик);

	ЮТФайлы.Существует(ПолныйПуть, ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(ПараметрыИсполнения));

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

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

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

#Область ФайлыПроекта

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

	Если НЕ Существует Тогда
		Сообщение = СтрШаблон("Файл/каталог проекта `%1` не существует. Полный путь: `%2`", Параметры.ПутьКФайлуПроекта, Параметры.ПолныйПуть);
		ПрерватьОбработку(Сообщение, Параметры);
		Возврат;
	КонецЕсли;

	ЮТФайлы.ЭтоКаталог(Параметры.ПолныйПуть, ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(Параметры));

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

Процедура ОбработчикПроверкиКаталога(ЭтоКаталог, Параметры) Экспорт

	Обработчик = ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(Параметры);
	Если ЭтоКаталог Тогда
		НачатьПоискФайлов(Обработчик, Параметры.ПолныйПуть, "*.*", Истина);
	Иначе
		НачатьПоискФайлов(Обработчик, Параметры.ПолныйПуть);
	КонецЕсли;

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

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

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

	ПараметрыПроверки = Новый Структура("Файлы, Индекс, Параметры", НайденныеФайлы, НайденныеФайлы.ВГраница(), Параметры);
	ИсключитьКаталоги(Неопределено, ПараметрыПроверки);

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

Процедура ОбработчикПереместитьФайлы(НайденныеФайлы, Параметры) Экспорт

	ФайлыДляПеремещения = Новый Массив();

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

	Обработчик = ЮТАсинхроннаяОбработкаСлужебныйКлиент.СледующийОбработчик(Параметры);
	НачатьПомещениеФайлов(Обработчик, ФайлыДляПеремещения, , Ложь);

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

Процедура ИсключитьКаталоги(ЭтоКаталог, ПараметрыПроверки) Экспорт

	Если ЭтоКаталог <> Неопределено Тогда

		Если ЭтоКаталог Тогда
			ПараметрыПроверки.Файлы.Удалить(ПараметрыПроверки.Индекс);
		КонецЕсли;
		ПараметрыПроверки.Индекс = ПараметрыПроверки.Индекс - 1;

	КонецЕсли;

	Если ПараметрыПроверки.Индекс < 0 Тогда
		ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьСледующийОбработчик(ПараметрыПроверки.Параметры, ПараметрыПроверки.Файлы);
		Возврат;
	КонецЕсли;

	Файл = ПараметрыПроверки.Файлы[ПараметрыПроверки.Индекс];
	Обработчик = Новый ОписаниеОповещения("ИсключитьКаталоги", ЭтотОбъект, ПараметрыПроверки);
	ЮТФайлы.ЭтоКаталог(Файл.ПолноеИмя, Обработчик);

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

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

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

	ОписаниеФайлов = Новый Массив;

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

	РезультатПередачиФайлов = ЮТРазрешениеЗависимостейСлужебныйВызовСервера.ПоместитьФайлыВРабочийКаталог(ОписаниеФайлов);

	Результат = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
	Результат.Успешно = РезультатПередачиФайлов <> Неопределено;

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

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

	ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьСледующийОбработчик(Параметры, Результат);

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

Процедура ПрерватьОбработку(Ошибка, Параметры)

	Обработчик = Параметры.ФинальныйОбработчик;
	Результат = ЮТФабрикаСлужебный.РезультатРазрешенияЗависимости();
	Результат.Ошибка = Ошибка;

	ЮТАсинхроннаяОбработкаСлужебныйКлиент.ВызватьОбработчик(Обработчик, Результат);

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

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

Процедура ДобавитьОбработчикЦепочки(ПараметрыИсполнения, ИмяМетода)

	Обработчик = Новый ОписаниеОповещения(ИмяМетода, ЭтотОбъект, ПараметрыИсполнения);
	ПараметрыИсполнения.Цепочка.Добавить(Обработчик);

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

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

[Assistant] Процедура ФайлыПроекта(ПутьКФайлуПроекта, Обработчик)


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ВариантыПараметров`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

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

	Варианты = Новый Массив;
	Варианты.Добавить(ЗначенияПоУмолчанию);

	Ключи = ЮТКоллекции.ВыгрузитьЗначения(ЗначенияПараметров, "Ключ");
    // TODO: допиши оставшуюся часть

[Assistant]
Функция ВариантыПараметров(ЗначенияПоУмолчанию, ЗначенияПараметров) Экспорт

	Варианты = Новый Массив;
	Варианты.Добавить(ЗначенияПоУмолчанию);

	Ключи = ЮТКоллекции.ВыгрузитьЗначения(ЗначенияПараметров, "Ключ");

	ДобавитьВарианты(Варианты, ЗначенияПоУмолчанию, ЗначенияПараметров, Ключи, 0);

	Возврат Варианты;

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

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

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

	Возврат ЮТКонструкторТестовыхДанныхСлужебный.Инициализировать(Менеджер);

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

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

Функция КонструкторДвижений(Документ, ИмяРегистра) Экспорт

	Возврат ЮТКонструкторТестовыхДанныхСлужебный.ИнициализироватьКонструкторДвижений(Документ, ИмяРегистра);

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

#Если Сервер Или ТолстыйКлиентОбычноеПриложение  Тогда
// Возвращает конструктор создания объекта XDTO.
//
// Параметры:
// ИмяТипа - Строка - Имя типа объекта XDTO.
// ПространствоИмен - Строка - Пространство имен типа объекта XDTO.
// Фабрика - ФабрикаXDTO - Фабрика, используемая для создания объектов XDTO. По умолчанию используется стандартная фабрика XDTO.
//
// Возвращаемое значение:
// ОбработкаОбъект.ЮТКонструкторОбъектаXDTO - Конструктор объекта XDTO.
//
// Пример:
// Конструктор = КонструкторОбъектаXDTO("Товар", "http://example.com/namespace", Новый ФабрикаXDTO());
// Конструктор.Установить("Наименование", "Товар 1");
// Конструктор.Установить("Цена", 100);
// Объект = Конструктор.ПолучитьОбъект(); // Создает объект XDTO с указанными реквизитами.
//
// Конструктор = КонструкторОбъектаXDTO("ДокументПриходТоваров", "http://example.com/namespace");
// Конструктор.Установить("Организация", Справочники.Организации.ПустаяСсылка());
// Конструктор.Установить("Склад", Справочники.Склады.ПустаяСсылка());
// Конструктор.Установить("Товар", Справочники.Товары.ПустаяСсылка());
// Конструктор.Установить("Количество", 10);
// Объект = Конструктор.ПолучитьОбъект(); // Создает объект XDTO с указанными реквизитами.

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

	Обработка = Обработки.ЮТКонструкторОбъектаXDTO.Создать();
	Обработка.Инициализировать(ИмяТипа, ПространствоИмен, Фабрика);

	Возврат Обработка;

КонецФункции
#КонецЕсли

// Удаляет переданные объекта
//
// Параметры:
// Ссылки - Массив из ЛюбаяСсылка - Массив ссылок на объекты, которые необходимо удалить.
// Привилегированно - Булево - Выполнить удаление в привилегированном режиме (без учета прав на объекты)

Процедура Удалить(Ссылки, Привилегированно = Ложь) Экспорт

	Если НЕ ЗначениеЗаполнено(Ссылки) Тогда
		Возврат;
	КонецЕсли;

#Если Сервер Тогда
	ЮТТестовыеДанныеСлужебныйСервер.Удалить(Ссылки, Привилегированно);
#Иначе
	ЮТТестовыеДанныеСлужебныйВызовСервера.Удалить(Ссылки, Привилегированно);
#КонецЕсли

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

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

Процедура ДобавитьКУдалению(Ссылки) Экспорт

	Если НЕ ЗначениеЗаполнено(Ссылки) Тогда
		Возврат;
	КонецЕсли;

	Если ТипЗнч(Ссылки) <> Тип("Массив") Тогда
		Ссылки = ЮТКоллекции.ЗначениеВМассиве(Ссылки);
	КонецЕсли;

	Для Каждого Ссылка Из Ссылки Цикл
		ЮТТестовыеДанныеСлужебный.ДобавитьТестовуюЗапись(Ссылка);
	КонецЦикла;

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

// Возвращает объект подражателя для формирования осмысленных тестовых данных
//
// Возвращаемое значение:
//  ОбщийМодуль - см. Подражатель

Функция Подражатель() Экспорт

	Возврат ЮТПодражатель;

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

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


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ЭтоПодходящееРасширение`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция ЭтоПодходящееРасширение(ИмяРасширения)
Экспорт

	Контекст = ЮТКонтекстСлужебный.КонтекстЧитателя();
    // TODO: допиши оставшуюся часть

[Assistant]
Функция ЭтоПодходящееРасширение(ИмяРасширения) Экспорт

	Контекст = ЮТКонтекстСлужебный.КонтекстЧитателя();

	НормализованноеИмяРасширения = НРег(ИмяРасширения);

	Возврат НЕ Контекст.Фильтр.ЕстьФильтрРасширений ИЛИ Контекст.Фильтр.Расширения[НормализованноеИмяРасширения] <> Неопределено;

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

Функция ЭтоПодходящийМодуль(МетаданныеМодуля) Экспорт

	Контекст = ЮТКонтекстСлужебный.КонтекстЧитателя();

	Успешно = ЗначениеЗаполнено(МетаданныеМодуля.Расширение)
		И (НЕ Контекст.Фильтр.ЕстьФильтрМодулей ИЛИ Контекст.Фильтр.Модули.Свойство(МетаданныеМодуля.Имя))
		И ЭтоПодходящееРасширение(МетаданныеМодуля.Расширение);

	Если Успешно Тогда
		Отказ = Ложь;
		ЮТСобытияСлужебный.ФильтрацияТестов_ПроверкаМодуля(МетаданныеМодуля, Отказ);
		Если Отказ Тогда
			Успешно = Ложь;
		КонецЕсли;
	КонецЕсли;

	Возврат Успешно;

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

// Отфильтровать тестовые наборы.
//
// Параметры:
//  ОписаниеТестовогоМодуля - см. ЮТФабрикаСлужебный.ОписаниеТестовогоМодуля

Процедура ОтфильтроватьТестовыеНаборы(ОписаниеТестовогоМодуля) Экспорт

	Фильтр = ЮТКонтекстСлужебный.КонтекстЧитателя().Фильтр;

	Если НЕ Фильтр.ЕстьФильтрТестов И НЕ Фильтр.ЕстьФильтрКонтекстов И НЕ Фильтр.ЕстьФильтрТегов Тогда
		Возврат;
	КонецЕсли;

	НаборыТестов = ОписаниеТестовогоМодуля.НаборыТестов;
	МетаданныеМодуля = ОписаниеТестовогоМодуля.Метаданные;

	Результат = Новый Массив();

	СостояниеФильтрации = Новый Структура;
	ДоступныеТестовыеМетоды(Фильтр, МетаданныеМодуля, СостояниеФильтрации);

	Для Каждого Набор Из НаборыТестов Цикл

		Если НЕ ЭтоПодходящийНабор(Набор, Фильтр) Тогда
			Продолжить;
		КонецЕсли;

		ОтфильтрованныйНабор = ЮТКоллекции.СкопироватьСтруктуру(Набор, Ложь);
		ОтфильтрованныйНабор.Тесты = Новый Массив;

		ОбработатьТегиНабора(ОписаниеТестовогоМодуля, Набор, Фильтр, СостояниеФильтрации);

		Для Каждого Тест Из Набор.Тесты Цикл

			ТестПодходитПодФильтр = ФильтрТестов(Тест, Фильтр, СостояниеФильтрации)
				И ФильтрКонтекста(Тест, Фильтр)
				И ФильтрТегов(Тест, Фильтр, СостояниеФильтрации);

			Если ТестПодходитПодФильтр Тогда

				ОтфильтрованныйТест = ЮТКоллекции.СкопироватьСтруктуру(Тест, Ложь);
				ОтфильтрованныйНабор.Тесты.Добавить(ОтфильтрованныйТест);

			КонецЕсли;

		КонецЦикла;

		Если ОтфильтрованныйНабор.Тесты.Количество() Тогда
			Результат.Добавить(ОтфильтрованныйНабор);
		КонецЕсли;

	КонецЦикла;

	ОписаниеТестовогоМодуля.НаборыТестов = Результат;

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

// Конструктор фильтра поиска тестовых методов
//
// Возвращаемое значение:
//  Структура - Фильтр:
// * Расширения - Структура - Имена расширений
// * Модули - Структура - Имена модулей
// * Наборы - Соответствие из Строка - Имена тестовых наборов
// * Теги - Соответствие из Строка
// * Контексты - Массив из Строка - Контексты вызова тестовых методов
// * Тесты - Массив из см. ОписаниеИмениТеста - Список путей к тестовым методам

Функция Фильтр() Экспорт

	//@skip-check structure-consructor-too-many-keys
	Фильтр = Новый Структура("Расширения, Модули, Наборы, Теги, Контексты, Тесты");

	Фильтр.Расширения = Новый Соответствие();
	Фильтр.Модули = Новый Структура();
	Фильтр.Теги = Новый Соответствие();
	Фильтр.Контексты = Новый Массив();
	Фильтр.Наборы = Новый Соответствие();
	Фильтр.Тесты = Новый Массив();

	//@skip-check constructor-function-return-section
	Возврат Фильтр;

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

Процедура УстановитьКонтекст(ПараметрыЗапускаТестов) Экспорт

	Расширения = ЮТКоллекции.ЗначениеСтруктуры(ПараметрыЗапускаТестов.filter, "extensions", Новый Массив);
	Модули = ЮТКоллекции.ЗначениеСтруктуры(ПараметрыЗапускаТестов.filter, "modules", Новый Массив);
	Контексты = ЮТКоллекции.ЗначениеСтруктуры(ПараметрыЗапускаТестов.filter, "contexts");
	Тесты = ЮТКоллекции.ЗначениеСтруктуры(ПараметрыЗапускаТестов.filter, "tests", Новый Массив);

	Теги = ЮТКоллекции.ЗначениеСтруктуры(ПараметрыЗапускаТестов.filter, "tags", Новый Массив);
	Наборы = ЮТКоллекции.ЗначениеСтруктуры(ПараметрыЗапускаТестов.filter, "suites", Новый Массив);

	Фильтр = Фильтр();

	Фильтр.Расширения = МассивВСоответствие(Расширения);
	Фильтр.Модули = ЮТКоллекции.МассивВСтруктуру(Модули);

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

	Если ЗначениеЗаполнено(Теги) Тогда
		Фильтр.Теги = МассивВСоответствие(Теги);
	КонецЕсли;

	Если ЗначениеЗаполнено(Наборы) Тогда
		Фильтр.Наборы = МассивВСоответствие(Наборы);
	КонецЕсли;

	МодулиТестов = Новый Структура();

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

	Если МодулиТестов.Количество() И Фильтр.Модули.Количество() = 0 Тогда

		Фильтр.Модули = МодулиТестов;

	ИначеЕсли МодулиТестов.Количество() Тогда

		Модули = Новый Структура();

		Для Каждого Элемент Из Фильтр.Модули Цикл
			Если МодулиТестов.Свойство(Элемент.Ключ) Тогда
				Модули.Вставить(Элемент.Ключ, Истина);
			КонецЕсли;
		КонецЦикла;

		Фильтр.Модули = Модули;

	КонецЕсли;

	Фильтр.Вставить("ЕстьФильтрРасширений", Фильтр.Расширения.Количество() > 0);
	Фильтр.Вставить("ЕстьФильтрМодулей", МодулиТестов.Количество() ИЛИ Фильтр.Модули.Количество());
	Фильтр.Вставить("ЕстьФильтрНаборов", ЗначениеЗаполнено(Фильтр.Наборы));
	Фильтр.Вставить("ЕстьФильтрТестов", Фильтр.Тесты.Количество() > 0 );
	Фильтр.Вставить("ЕстьФильтрКонтекстов", ЗначениеЗаполнено(Фильтр.Контексты));
	Фильтр.Вставить("ЕстьФильтрТегов", ЗначениеЗаполнено(Фильтр.Теги));

	ЮТКонтекстСлужебный.УстановитьКонтекстЧитателя(Новый Структура("Фильтр", Фильтр));

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

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

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

Функция ОписаниеИмениТеста(Путь)

	Части = СтрРазделить(Путь, ".");

	Если Части.Количество() <= 1 ИЛИ Части.Количество() > 3 Тогда
		ВызватьИсключение СтрШаблон("Не корректный формат пути к тесту `%1`, должен быть в формате `ИмяМодуля.ИмяМетода{.Контекст}`", Путь);
	КонецЕсли;

	Описание = Новый Структура("ИмяМодуля, ИмяМетода, Контекст");

	Для Инд = 0 По Части.ВГраница() Цикл
		Части[Инд] = СокрЛП(Части[Инд]);
	КонецЦикла;

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

	Возврат Описание;

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

Процедура ДоступныеТестовыеМетоды(Фильтр, ОписаниеМодуля, СостояниеФильтрации)

	Если НЕ Фильтр.ЕстьФильтрТестов Тогда
		Возврат;
	КонецЕсли;

	ДоступныеТестовыеМетоды = Новый Соответствие();

	Для Каждого ОписаниеИмениТеста Из Фильтр.Тесты Цикл

		Если СтрСравнить(ОписаниеИмениТеста.ИмяМодуля, ОписаниеМодуля.Имя) = 0 Тогда
			ОписаниеИмениТеста.ИмяМетода = ВРег(ОписаниеИмениТеста.ИмяМетода);

			СохраненноеОписаниеИмени = ДоступныеТестовыеМетоды[ОписаниеИмениТеста.ИмяМетода];

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

	КонецЦикла;

	СостояниеФильтрации.Вставить("ДоступныеТестовыеМетоды", ДоступныеТестовыеМетоды);

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


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ИсполняемыеСценарииМодуля`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

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

	ЭтоТестовыйМодуль = Истина;

	ЮТСобытияСлужебный.ПередЧтениемСценариевМодуля(МетаданныеМодуля);

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

	Если Ошибка <> Неопределено Тогда

		ТипыОшибок = ЮТФабрикаСлужебный.ТипыОшибок();
		ТипОшибки = ЮТРегистрацияОшибокСлужебный.ТипОшибки(Ошибка, ПолноеИмяМетода);

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

			Сообщение = "Используется устаревшая сигнатура метода `ИсполняемыеСценарии`, метод не должен принимать параметров.";
			ЮТОбщий.СообщитьПользователю(Сообщение);
			ЮТЛогирование.Предостережение(Сообщение);
		КонецЕсли;

	КонецЕсли;
    // TODO: допиши оставшуюся часть

[Assistant]
//©///////////////////////////////////////////////////////////////////////////©//
//
//  Copyright 2021-2025 BIA-Technologies Limited Liability Company
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
//©///////////////////////////////////////////////////////////////////////////©//

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

// ПрочитатьНаборТестов
// 	Читает набор тестов из модуля
// Параметры:
//  МетаданныеМодуля - см. ЮТФабрика.ОписаниеМетаданныеМодуля
//
// Возвращаемое значение:
//  - Неопределено - Если это не тестовый модуль
//  - см. ЮТФабрикаСлужебный.ОписаниеТестовогоМодуля
Функция ИсполняемыеСценарииМодуля(Знач МетаданныеМодуля) Экспорт

	ЭтоТестовыйМодуль = Истина;

	ЮТСобытияСлужебный.ПередЧтениемСценариевМодуля(МетаданныеМодуля);

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

	Если Ошибка <> Неопределено Тогда

		ТипыОшибок = ЮТФабрикаСлужебный.ТипыОшибок();
		ТипОшибки = ЮТРегистрацияОшибокСлужебный.ТипОшибки(Ошибка, ПолноеИмяМетода);

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

			Сообщение = "Используется устаревшая сигнатура метода `ИсполняемыеСценарии`, метод не должен принимать параметров.";
			ЮТОбщий.СообщитьПользователю(Сообщение);
			ЮТЛогирование.Предостережение(Сообщение);
		КонецЕсли;

	КонецЕсли;

	Если Ошибка <> Неопределено Тогда

		ОписаниеТестовогоМодуля = ОписаниеТестовогоМодуляСОшибкой(МетаданныеМодуля, Ошибка);

	ИначеЕсли ЭтоТестовыйМодуль Тогда

		ОписаниеТестовогоМодуля = ЮТТестыСлужебный.ОписаниеМодуля();
		ЮТФильтрацияСлужебный.ОтфильтроватьТестовыеНаборы(ОписаниеТестовогоМодуля);
		ЮТСобытияСлужебный.ПослеЧтенияСценариевМодуля(ОписаниеТестовогоМодуля);

	Иначе

		ОписаниеТестовогоМодуля = Неопределено;

	КонецЕсли;

	Возврат ОписаниеТестовогоМодуля;

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

Функция ОписаниеТестовогоМодуляСОшибкой(МетаданныеМодуля, Ошибка) Экспорт

	НаборПоУмолчанию = ЮТФабрикаСлужебный.ОписаниеТестовогоНабора(МетаданныеМодуля.Имя);
	ЮТРегистрацияОшибокСлужебный.ЗарегистрироватьОшибкуЧтенияТестов(НаборПоУмолчанию, "Ошибка формирования списка тестовых методов", Ошибка);

	ОписаниеТестовогоМодуля = ЮТФабрикаСлужебный.ОписаниеТестовогоМодуля(МетаданныеМодуля, Новый Массив);
	ОписаниеТестовогоМодуля.НаборыТестов.Добавить(НаборПоУмолчанию);

	Возврат ОписаниеТестовогоМодуля;

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

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

	ЭтоТестовыйМодуль = Истина;

	ЮТСобытияСлужебный.ПередЧтениемСценариевМодуля(МетаданныеОбъекта);
	ИмяМетода = ИмяМетодаСценариев();

	Ошибка = ЮТМетодыСлужебный.ВыполнитьМетодОбъектаСПерехватомОшибки(Объект, ИмяМетода);

	Если Ошибка <> Неопределено Тогда

		ТипыОшибок = ЮТФабрикаСлужебный.ТипыОшибок();
		ТипОшибки = ЮТРегистрацияОшибокСлужебный.ТипОшибки(Ошибка, ИмяМетода);

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

			Сообщение = "Используется устаревшая сигнатура метода `ИсполняемыеСценарии`, метод не должен принимать параметров.";
			ЮТОбщий.СообщитьПользователю(Сообщение);
			ЮТЛогирование.Предостережение(Сообщение);
		КонецЕсли;

	КонецЕсли;

	Если Ошибка <> Неопределено Тогда

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

		ОписаниеТестовогоМодуля = ЮТФабрикаСлужебный.ОписаниеТестовогоМодуля(МетаданныеОбъекта, Новый Массив);
		ОписаниеТестовогоМодуля.НаборыТестов.Добавить(НаборПоУмолчанию);

	ИначеЕсли ЭтоТестовыйМодуль Тогда

		ОписаниеТестовогоМодуля = ЮТТестыСлужебный.ОписаниеМодуля();
		ЮТФильтрацияСлужебный.ОтфильтроватьТестовыеНаборы(ОписаниеТестовогоМодуля);
		ЮТСобытияСлужебный.ПослеЧтенияСценариевМодуля(ОписаниеТестовогоМодуля);

	Иначе

		ОписаниеТестовогоМодуля = Неопределено;

	КонецЕсли;

	Возврат ОписаниеТестовогоМодуля;

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

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

	Если МетаданныеМодуля.Глобальный Или МетаданныеМодуля.ВызовСервера Тогда
		Возврат Ложь;
	КонецЕсли;

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

#Если Сервер Тогда
	Возврат ЮТМетодыСлужебный.МетодМодуляСуществует(МетаданныеМодуля.Имя, ИмяМетодаСценариев());
#КонецЕсли

	Если МетаданныеМодуля.Сервер Тогда
		//@skip-check unknown-method-property
		Возврат ЮТЧитательСлужебныйВызовСервера.ЭтоТестовыйМодуль(МетаданныеМодуля);
	Иначе
		Возврат Ложь;
	КонецЕсли;

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

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

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

Функция ИмяМетодаСценариев()

	Возврат "ИсполняемыеСценарии";

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

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


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

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

	Если ДанныеШаблона = Неопределено Тогда
		ДанныеШаблона = ПолучитьМакет("ШаблонОбработки");
	КонецЕсли;

	Поток = ДанныеШаблона.ОткрытьПотокДляЧтения();
	ПараметрыЗаписи = ПараметрыЗаписи();
	Попытка
		ФайлыОбработки = ПрочитатьКонтейнер(Поток, ПараметрыЗаписи, Истина);
		Поток.Закрыть();
	Исключение
		Поток.Закрыть();
		ВызватьИсключение;
	КонецПопытки;

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

// Возвращает список файлов загруженной обработки
//
// Возвращаемое значение:
//  Массив из см. ЗаписьОглавления - Файлы обработки

Функция ФайлыОбработки() Экспорт

	Возврат ФайлыОбработки;

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

// Устанавливает данные внутреннего файла обработки.
//
// Параметры:
//  ПолноеИмяФайла - Строка - Полное имя файла, разделитель пути - `/`
//  Текст - Строка - Новый текст файла

Процедура УстановитьДанныеФайла(ПолноеИмяФайла, Текст) Экспорт

	Файл = НайтиФайл(ПолноеИмяФайла);
	Если Файл.ЭтоКонтейнер Тогда
		ВызватьИсключение СтрШаблон("%1 это контейнер, а должен быть обычный файл", ПолноеИмяФайла);
	КонецЕсли;

	Файл.Данные = ПолучитьДвоичныеДанныеИзСтроки(Текст, КодировкаТекста.UTF8, Ложь);

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

// Возвращает текст файла
//
// Параметры:
//  ПолноеИмяФайла - Строка - Полное имя файла, разделитель пути - `/`
//
// Возвращаемое значение:
//  Строка - Текст файла

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

	Файл = НайтиФайл(ПолноеИмяФайла);
	Если Файл.ЭтоКонтейнер Тогда
		ВызватьИсключение СтрШаблон("%1 это контейнер, а должен быть обычный файл", ПолноеИмяФайла);
	КонецЕсли;

	Возврат ПолучитьСтрокуИзДвоичныхДанных(Файл.Данные);

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

// Собирает обработку из файлов
//
// Возвращаемое значение:
//  ДвоичныеДанные - Обработку

Функция СформироватьОбработку() Экспорт

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

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

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

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

#Область Чтение

Функция ПрочитатьКонтейнер(Поток, ПараметрыЗаписи, Распаковывать)

	РазмерЗаголовкаКонтейнера = 16;

	ПотокОглавления = ПотокДокумента(Поток, ПараметрыЗаписи, РазмерЗаголовкаКонтейнера);
	Оглавление = ДанныеОглавления(ПотокОглавления, ПараметрыЗаписи); // Пропускаем заголовок контейнера - 16 байт
	ПотокОглавления.Закрыть();

	ЗагрузитьФайлы(Поток, ПараметрыЗаписи, Оглавление, Распаковывать);

	Возврат Оглавление;

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

Процедура ЗагрузитьФайлы(Поток, ПараметрыЗаписи, Оглавление, Распаковывать)

	Для Каждого Запись Из Оглавление Цикл
		Запись.ИмяФайла = ИмяФайлаИзАтрибутов(Поток, ПараметрыЗаписи, Запись.АдресЗаголовкаФайла);
		Данные = ДанныеФайла(Поток, ПараметрыЗаписи, Запись.АдресТелаФайла, Распаковывать);
		Запись.ЭтоКонтейнер = ЭтоКонтейнер(Данные);

		Если Запись.ЭтоКонтейнер Тогда
			ВложенныйПоток = Данные.ОткрытьПотокДляЧтения();
			ДанныеКонтейнера = ПрочитатьКонтейнер(ВложенныйПоток, ПараметрыЗаписи, Ложь);
			ВложенныйПоток.Закрыть();
			Запись.Данные = ДанныеКонтейнера;
		Иначе
			Запись.Данные = Данные;
		КонецЕсли;

	КонецЦикла;

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

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

	РазмерБлокаДат = 20;

	ПотокАтрибутыФайла = ПотокДокумента(Поток, ПараметрыЗаписи, АдресАтрибутовФайла);
	Чтение = Новый ЧтениеДанных(ПотокАтрибутыФайла, КодировкаТекста.UTF16, ПорядокБайтов.LittleEndian, , Символ(0));
	Чтение.Пропустить(РазмерБлокаДат); // Атрибуты
	ИмяФайла = СокрП(Чтение.ПрочитатьСтроку());
	ПотокАтрибутыФайла.Закрыть();

	Возврат ИмяФайла;

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

Функция ДанныеФайла(Поток, ПараметрыЗаписи, АдресДанныеФайла, Распаковать)

	ПотокДанные = ПотокДокумента(Поток, ПараметрыЗаписи, АдресДанныеФайла);
	Данные = ПотокДанные.ЗакрытьИПолучитьДвоичныеДанные();
	ПотокДанные.Закрыть();

	Если Распаковать Тогда
		Данные = РаспаковатьДанные(Данные);
	КонецЕсли;

	Возврат Данные;

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

Функция РаспаковатьДанные(Знач ДвоичныеДанные)

	Заголовок64 = "AgFTS2/0iI3BTqDV67a9oKcNAFEArv89AAAAAAAAAO+7v3siIyIsODcxMjYyMDAt
		|M2U5OC00NGUwLWI5MzEtY2NiMWQ3ZWRjNDk3LA0KezEsDQp7MH0NCn0NCn0AAAAA
		|//////////8=";
	ЗаголовокДляХранилищаЗначения = Base64Значение(Заголовок64);

	Поток = Новый ПотокВПамяти;
	ПотокЗаголовка = ЗаголовокДляХранилищаЗначения.ОткрытьПотокДляЧтения();
	ПотокЗаголовка.КопироватьВ(Поток);
	ПотокЗаголовка.Закрыть();
	ПотокДанных = ДвоичныеДанные.ОткрытьПотокДляЧтения();
	ПотокДанных.КопироватьВ(Поток);
	ПотокДанных.Закрыть();
	СводныйФайл = Поток.ЗакрытьИПолучитьДвоичныеДанные();
	ХранилищеЗначения = XMLЗначение(Тип("ХранилищеЗначения"), ПолучитьBase64СтрокуИзДвоичныхДанных(СводныйФайл));

	Попытка
		РаспакованныеДанные = ХранилищеЗначения.Получить();
	Исключение
		РаспакованныеДанные = ПолучитьДвоичныеДанныеИзHexСтроки("");
	КонецПопытки;

	Возврат РаспакованныеДанные;

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

Функция ЗаголовокБлока(Чтение)

	ВозвратКаретки = 13;
	ПереносСтроки = 10;

	Если Чтение.ПрочитатьБайт() <> ВозвратКаретки Или Чтение.ПрочитатьБайт() <> ПереносСтроки Тогда
		ВызватьИсключение "Заголовок блока должен начинаться с `0D 0A`";
	КонецЕсли;

	ДлинаФайла = ЧислоЗаголовка(Чтение);
	Чтение.Пропустить(1); // Пробел 20
	ДлинаБлока = ЧислоЗаголовка(Чтение);
	Чтение.Пропустить(1); // Пробел 20
	СледующийБлок = ЧислоЗаголовка(Чтение);
	Чтение.Пропустить(3); // 20 0D 0A

	Чтение.Закрыть();
	ДанныеЗаголовка = Новый Структура("ДлинаФайла, ДлинаБлока, СледующийБлок", ДлинаФайла, ДлинаБлока, СледующийБлок);

	Возврат ДанныеЗаголовка;

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

Функция ПотокДокумента(ВходнойПоток, ПараметрыЗаписи, АдресБлока)
	ОсталосьПрочитать = -1;

	СледующийБлок = АдресБлока;
	МаксимальноеЦелоеЧисло = ПараметрыЗаписи.МаксимальноеЦелоеЧисло;
	ЭтоПервыйБлок = Истина;

	Пока СледующийБлок < МаксимальноеЦелоеЧисло Цикл

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

		ВходнойПоток.Перейти(СледующийБлок, ПозицияВПотоке.Начало);
		Чтение = Новый ЧтениеДанных(ВходнойПоток, КодировкаТекста.ANSI, ПорядокБайтов.LittleEndian);

		Заголовок = ЗаголовокБлока(Чтение);
		СледующийБлок = Заголовок.СледующийБлок;

		Если Заголовок.ДлинаБлока = 0 Тогда
			ВызватьИсключение "Ошибка чтения потока из контейнера. Длина блока = 0.";
		КонецЕсли;

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

		Читаем = Мин(Заголовок.ДлинаБлока, ОсталосьПрочитать);
		Буфер = Чтение.ПрочитатьВБуферДвоичныхДанных(Читаем);
		Чтение.Закрыть();
		Запись.ЗаписатьБуферДвоичныхДанных(Буфер);
		ОсталосьПрочитать = ОсталосьПрочитать - Читаем;
	КонецЦикла;

	Запись.Закрыть();

	Если ОсталосьПрочитать > 0 Тогда
		ВызватьИсключение "Ошибка чтения потока из контейнера. Поток не считан до конца, но цепочка блоков закончилась.";
	КонецЕсли;

	ПотокЗаписи.Перейти(0, ПозицияВПотоке.Начало);

	Возврат ПотокЗаписи;

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

Функция ДанныеОглавления(Поток, ПараметрыЗаписи)

	Чтение = Новый ЧтениеДанных(Поток, , ПорядокБайтов.LittleEndian);
	Оглавление = Новый Массив;

	Пока Истина Цикл

		Запись = ЗаписьОглавления();
		Запись.АдресЗаголовкаФайла = Чтение.ПрочитатьЦелое32();

		Если Запись.АдресЗаголовкаФайла = Неопределено Тогда
			Прервать;
		КонецЕсли;

		Запись.АдресТелаФайла = Чтение.ПрочитатьЦелое32();
		Чтение.Пропустить(ПараметрыЗаписи.РазмерПоляАдресации); // 4 байта зарезервированное поле (7FFFFFFF)

		Оглавление.Добавить(Запись);

	КонецЦикла;

	Возврат Оглавление;

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

Функция ЧислоЗаголовка(Чтение)

	РазмерПоля = 8;
	Значение = "0x" + Чтение.ПрочитатьСимволы(РазмерПоля);
	Возврат ЧислоИзШестнадцатеричнойСтроки(Значение);

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

[Assistant] Процедура ЗагрузитьШаблон(Знач ДанныеШаблона = Неопределено)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

// Загрузчик CLI-пакета с рекурсивным обнаружением классов.
// Сканирует все *.os файлы в директории cli/ и её подкаталогах,
// регистрируя каждый как класс.

// BSLLS:UnusedLocalMethod-off  Стандартный хук OneScript - вызывается рантаймом при загрузке пакета.
// BSLLS:UnusedParameters-off   СтандартнаяОбработка/Отказ - часть контракта хука.
Процедура ИмяФункции(Путь, СтандартнаяОбработка, Отказ)
// BSLLS:UnusedLocalMethod-on
// BSLLS:UnusedParameters-on

	ИмяЗагрузчика = "package-loader.os";

	Файлы = НайтиФайлы(Путь, "*.os", Истина);
	Для Каждого Файл Из Файлы Цикл

		Если Файл.Имя = ИмяЗагрузчика Тогда
			Продолжить;
		КонецЕсли;

		ДобавитьКласс(Файл.ПолноеИмя, Файл.ИмяБезРасширения);

	КонецЦикла;

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

[Assistant] Процедура ПриЗагрузкеБиблиотеки(Путь, СтандартнаяОбработка, Отказ)


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `ИзменитьСвойстваРасширения`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура ИзменитьСвойстваРасширения(Знач ПараметрыПодключения, Знач ИмяРасширения, Знач Свойства, Знач ПараметрыПлатформы = Неопределено)
Экспорт

	Лог.Отладка("Изменение свойств расширения: %1", ИмяРасширения);
	Менеджер = СоздатьМенеджер(ПараметрыПлатформы);
	УстановитьКонтекстИБ(Менеджер, ПараметрыПодключения);
	Менеджер.ИзменитьСвойстваРасширения(
		ИмяРасширения,
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура ИзменитьСвойстваРасширения(Знач ПараметрыПодключения, Знач ИмяРасширения, Знач Свойства, Знач ПараметрыПлатформы = Неопределено) Экспорт

	Лог.Отладка("Изменение свойств расширения: %1", ИмяРасширения);
	Менеджер = СоздатьМенеджер(ПараметрыПлатформы);
	УстановитьКонтекстИБ(Менеджер, ПараметрыПодключения);
	Менеджер.ИзменитьСвойстваРасширения(
		ИмяРасширения,
		Свойства.Активность,
		Свойства.БезопасныйРежим,
		Свойства.ИмяПрофиляБезопасности,
		Свойства.ЗащитаОтОпасныхДействий,
		Свойства.ИспользуетсяВ_РИБ,
		Свойства.ОбластьДействия_ИБ);

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

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

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

Процедура ОбновитьВсеРасширенияВнутри(Знач Менеджер)

	Лог.Отладка("Обновление всех расширений через ibcmd: получение списка");
	Описания = Менеджер.ОписанияРасширений();
	Если Описания.Количество() = 0 Тогда
		Лог.Информация("✓ Расширений в инфобазе нет - обновление пропущено");
		Возврат;
	КонецЕсли;

	Лог.Информация("Обновление расширений через ibcmd: найдено %1", Описания.Количество());
	Для Каждого Описание Из Описания Цикл
		Имя = Описание.Получить("name");
		Если НЕ ЗначениеЗаполнено(Имя) Тогда
			Продолжить;
		КонецЕсли;
		Лог.Информация("Обновление расширения '%1' через ibcmd", Имя);
		Менеджер.ОбновитьКонфигурациюБазыДанных(Имя);
	КонецЦикла;
	Лог.Информация("✓ Обновлено расширений через ibcmd: %1", Описания.Количество());

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

Функция СоздатьМенеджер(ПараметрыПлатформы)

	ВерсияПлатформы = ПолучитьВерсиюПлатформы(ПараметрыПлатформы);
	Лог.Отладка("Создание УправлениеИБ с версией платформы: %1", ВерсияПлатформы);
	Менеджер = СоздатьЭкземплярУправленияИБ(ВерсияПлатформы);
	КаталогДанныхАвтономногоСервера = ВременныеФайлы.СоздатьКаталог();
	Менеджер.УстановитьПараметрыАвтономногоСервера(КаталогДанныхАвтономногоСервера);
	Лог.Отладка("УправлениеИБ создан успешно");
	Возврат Менеджер;

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

Функция СоздатьЭкземплярУправленияИБ(ВерсияПлатформы)
	Если _ФабрикаУправленияИБ <> Неопределено Тогда
		Возврат _ФабрикаУправленияИБ.Создать(ВерсияПлатформы);
	КонецЕсли;
	Возврат Новый УправлениеИБ(ВерсияПлатформы);
КонецФункции

Функция ПолучитьВерсиюПлатформы(ПараметрыПлатформы)

	Если ПараметрыПлатформы <> Неопределено
		И ЗначениеЗаполнено(ПараметрыПлатформы.ВерсияПлатформы) Тогда
		Лог.Отладка("Используется версия платформы из параметров: %1", ПараметрыПлатформы.ВерсияПлатформы);
		Возврат ПараметрыПлатформы.ВерсияПлатформы;
	КонецЕсли;

	Лог.Отладка("Используется версия платформы по умолчанию: 8");
	Возврат "8";

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

Процедура УстановитьКонтекстИБ(Менеджер, ПараметрыПодключения)

	ЕстьСУБД = Ложь;
	Если ПараметрыПодключения.Свойство("ТипСУБД") Тогда
		ЕстьСУБД = ЗначениеЗаполнено(ПараметрыПодключения.ТипСУБД);
	КонецЕсли;

	Если ЕстьСУБД Тогда
		Лог.Отладка("Установка параметров серверной ИБ: СУБД=%1, сервер=%2, БД=%3",
			ПараметрыПодключения.ТипСУБД, ПараметрыПодключения.СерверСУБД, ПараметрыПодключения.ИмяБазыДанных);
		Менеджер.УстановитьПараметрыСервернойИБ(
			ПараметрыПодключения.ТипСУБД,
			ПараметрыПодключения.СерверСУБД,
			ПараметрыПодключения.ИмяБазыДанных,
			ПараметрыПодключения.ПользовательСУБД,
			ПараметрыПодключения.ПарольСУБД);
		Лог.Отладка("Параметры серверной ИБ установлены");
	Иначе
		КаталогИБ = ИзвлечьКаталогФайловойИБ(ПараметрыПодключения);
		Лог.Отладка("Установка параметров файловой ИБ: каталог=%1", КаталогИБ);
		Менеджер.УстановитьПараметрыФайловойИБ(КаталогИБ);
		Лог.Отладка("Параметры файловой ИБ установлены");
	КонецЕсли;

	Если ЗначениеЗаполнено(ПараметрыПодключения.Пользователь) Тогда
		Лог.Отладка("Установка параметров авторизации ИБ: пользователь=%1", ПараметрыПодключения.Пользователь);
		Менеджер.УстановитьПараметрыАвторизацииИБ(
			ПараметрыПодключения.Пользователь,
			ПараметрыПодключения.Пароль);
		Лог.Отладка("Параметры авторизации ИБ установлены");
	КонецЕсли;

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

Функция ИзвлечьКаталогФайловойИБ(ПараметрыПодключения)

	Если ПараметрыПодключения.Свойство("КаталогБазы")
		И ЗначениеЗаполнено(ПараметрыПодключения.КаталогБазы) Тогда
		Лог.Отладка("Извлечен каталог файловой ИБ из КаталогБазы: %1", ПараметрыПодключения.КаталогБазы);
		Возврат ПараметрыПодключения.КаталогБазы;
	КонецЕсли;

	Путь = ПараметрыПодключения.СтрокаПодключения;
	Путь = СтрЗаменить(Путь, "/F", "");
	Путь = СтрЗаменить(Путь, """", "");
	Путь = СокрЛП(Путь);
	Путь = Новый Файл(Путь).ПолноеИмя;
	Лог.Отладка("Извлечен каталог файловой ИБ из СтрокаПодключения: %1", Путь);
	Возврат Путь;

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

Функция ПрочитатьМассивФайловИзСписка(Знач ПутьКСпискуФайлов)

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

	Чтение = Новый ЧтениеТекста(ПутьКСпискуФайлов, "UTF-8");
	Строка = Чтение.ПрочитатьСтроку();
	Пока Строка <> Неопределено Цикл
		Строка = СокрЛП(Строка);
		Если ЗначениеЗаполнено(Строка) Тогда
			МассивФайлов.Добавить(Строка);
		КонецЕсли;
		Строка = Чтение.ПрочитатьСтроку();
	КонецЦикла;
	Чтение.Закрыть();

	Возврат МассивФайлов;

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

Функция РазобратьФайлИзмененийКонфигурации(Знач ПутьКФайлуИзменений)

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

	УникальныеФайлы = Новый Соответствие;
	Чтение = Новый ЧтениеТекста(ПутьКФайлуИзменений, "UTF-8");
	СтрокаИзменения = Чтение.ПрочитатьСтроку();

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

	Чтение.Закрыть();

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

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

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

Функция ОбработатьСтрокуИзменения(УникальныеФайлы, Знач СтрокаИзменения)

	НижнийРегистр = НРег(СтрокаИзменения);

	Если НижнийРегистр = "fulldump" ИЛИ НижнийРегистр = "modified: all" Тогда
		Возврат Истина;
	КонецЕсли;

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

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

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

Функция ПреобразоватьСтрокуИзмененияВОтносительныйПуть(Знач СтрокаИзменения)

	СтрокаИзменения = СтрЗаменить(СтрокаИзменения, "modified: ", "");
	СтрокаИзменения = СтрЗаменить(СтрокаИзменения, "Modified: ", "");
	СтрокаИзменения = СокрЛП(СтрокаИзменения);

	Если СтрНачинаетсяС(СтрокаИзменения, "Configuration") Тогда
		Возврат "Configuration.xml";
	КонецЕсли;

	Части = СтрРазделить(СтрокаИзменения, ".", Ложь);
	Если Части.Количество() < 2 Тогда
		Возврат "";
	КонецЕсли;

	КорневойТип = Части[0] + "s";
	ИмяОбъекта = Части[1];

	Возврат КорневойТип + "/" + ИмяОбъекта + ".xml";

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

Процедура ОбеспечитьПустойКаталог(Знач КаталогВыгрузки)

	Файл = Новый Файл(КаталогВыгрузки);
	Если Файл.Существует() Тогда
		Лог.Отладка("Удаление существующего каталога: %1", КаталогВыгрузки);
		УдалитьФайлы(КаталогВыгрузки);
		Лог.Отладка("Каталог удален");
	КонецЕсли;
	Лог.Отладка("Создание пустого каталога: %1", КаталогВыгрузки);
	СоздатьКаталог(КаталогВыгрузки);
	Лог.Отладка("Каталог создан");

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

Функция АбсолютныйПуть(Знач Путь)
	Файл = Новый Файл(Путь);
	Возврат Файл.ПолноеИмя;
КонецФункции

// Сформировать строку подключения к файловой ИБ для конфигуратора (1cv8).

Функция ФайловаяИБ(Знач КаталогБазы)
	Возврат "/F""" + КаталогБазы + """";
КонецФункции

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


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `JSONВСтруктуру`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

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

	// Находим позицию последнего закрывающего фигурного скобки, используя поиск с конца
	ПозицияКонца = СтрНайти(СтрокаJSON, "}", НаправлениеПоиска.СКонца);
	Если ПозицияКонца = 0 Тогда
		// Если закрывающая скобка не найдена, возвращаем Неопределено
		Возврат Неопределено;
	КонецЕсли;

	// Вычисляем длину фрагмента с JSON: от первого "{" до последнего "}" включительно
	ДлинаФрагмента = ПозицияКонца - ПозицияНачала + 1;
    // TODO: допиши оставшуюся часть

[Assistant]
// Репозиторий проекта:
// https://github.com/vladimir-kharin/1c_formatter
//
// Харин Владимир (С) 2025. https://vharin.ru
// Telegram - https://t.me/vladimir_kharin

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

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

	// Находим позицию последнего закрывающего фигурного скобки, используя поиск с конца
	ПозицияКонца = СтрНайти(СтрокаJSON, "}", НаправлениеПоиска.СКонца);
	Если ПозицияКонца = 0 Тогда
		// Если закрывающая скобка не найдена, возвращаем Неопределено
		Возврат Неопределено;
	КонецЕсли;

	// Вычисляем длину фрагмента с JSON: от первого "{" до последнего "}" включительно
	ДлинаФрагмента = ПозицияКонца - ПозицияНачала + 1;

	// Извлекаем корректную часть JSON из строки
	ЧистыйJSON = Сред(СтрокаJSON, ПозицияНачала, ДлинаФрагмента);

	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ЧистыйJSON);

	Результат = ПрочитатьJSON(ЧтениеJSON);

	ЧтениеJSON.Закрыть();

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

// Отправляет запрос к ИИ API и возвращает ответ
//
// Параметры:
//  Текст        - Строка - Текущее сообщение пользователя для отправки модели
//  КлючAPI      - Строка - Ключ API для аутентификации
//  БазовыйАдрес - Строка - URL-адрес API, опционально, по умолчанию - OpenRouter
//  Модель       - Строка - Название модели, опционально, по умолчанию - deepseek/deepseek-chat
//  ИсторияЧата  - Массив - История чата в формате [{role: "user|assistant", content: "текст сообщения"}, ...].
//                           Этот параметр модифицируется внутри функции:
//                           - Текущее сообщение пользователя (параметр Текст) добавляется к истории
//                           - Ответ модели также добавляется к истории
//                           Если параметр не передан (Неопределено), функция работает в режиме
//                           одиночного запроса без поддержки контекста.
//
// Возвращаемое значение:
//  Строка - Текст ответа от модели (последнее сообщение ассистента)
//
// Примечание:
//  При использовании параметра ИсторияЧата учитывайте, что он будет изменен внутри функции.
//  Это позволяет поддерживать контекст беседы между несколькими вызовами функции.
&НаКлиенте
Функция ОтправитьЗапросOpenAI(Текст, КлючAPI, БазовыйАдрес = Неопределено, Модель = Неопределено, ИсторияЧата = Неопределено) Экспорт
	// Проверка наличия ключа API
	Если ПустаяСтрока(КлючAPI) Тогда
		ВызватьИсключение "Не указан ключ API";
	КонецЕсли;

	ТекБазовыйАдрес = ?(ЗначениеЗаполнено(БазовыйАдрес), БазовыйАдрес, "https://openrouter.ai/api/v1/chat/completions");
	ТекМодель = ?(ЗначениеЗаполнено(Модель), Модель, "deepseek/deepseek-chat");

	// Разбор базового адреса
	РазобранныйURL = РазобратьURL(ТекБазовыйАдрес);

	// Подготовка HTTP-запроса
	HTTPСоединение = Новый HTTPСоединение(
		РазобранныйURL.Хост,
		РазобранныйURL.Порт,
		,
		,
		,
		120,
		?(РазобранныйURL.Схема = "https", Новый ЗащищенноеСоединениеOpenSSL, Неопределено));
	HTTPЗапрос = Новый HTTPЗапрос(РазобранныйURL.Путь);
	HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
	HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer " + КлючAPI);

	// Формирование тела запроса
	СтруктураЗапроса = Новый Структура;
	СтруктураЗапроса.Вставить("model", ТекМодель);

	// Проверяем, передана ли история чата
	Если ТипЗнч(ИсторияЧата) = Тип("Массив") Тогда
		// Добавляем текущее сообщение к истории
		Если ЗначениеЗаполнено(Текст) Тогда
			ИсторияЧата.Добавить(Новый Структура("role,content", "user", Текст));
		КонецЕсли;

		// Используем обновленную историю сообщений
		СтруктураЗапроса.Вставить("messages", ИсторияЧата);
	Иначе
		// Режим обратной совместимости - создаем новый массив с одним сообщением
		СтруктураЗапроса.Вставить("messages", Новый Массив);
		СтруктураЗапроса.messages.Добавить(Новый Структура("role,content", "user", Текст));
	КонецЕсли;

	HTTPЗапрос.УстановитьТелоИзСтроки(СтруктураВJSON(СтруктураЗапроса));

	// Отправка запроса
	Попытка
		HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
	Исключение
		ВызватьИсключение "Ошибка отправки запроса: " + ОписаниеОшибки();
	КонецПопытки;

	// Обработка ответа
	ТелоОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
	Если HTTPОтвет.КодСостояния <> 200 Тогда
		ВызватьИсключение СтрШаблон(
			"Ошибка API. Код: %1, Ответ: %2",
			HTTPОтвет.КодСостояния,
			ТелоОтвета
		);
	КонецЕсли;

	// Разбор JSON-ответа
	ОтветJSON = JSONВСтруктуру(ТелоОтвета);

	// Проверка на наличие ошибки в ответе
	Если ОтветJSON.Свойство("error") Тогда
		ВызватьИсключение СтрШаблон(
			"Ошибка API. Код: %1, Сообщение: %2",
			ОтветJSON.error.code,
			ТелоОтвета
		);
	КонецЕсли;

	// Получаем ответ модели
	ОтветМодели = "";
	Если ОтветJSON.choices.Количество() > 0 Тогда
		ОтветМодели = ОтветJSON.choices[0].message.content;

		// Если передана история чата, добавляем в неё ответ модели
		Если ТипЗнч(ИсторияЧата) = Тип("Массив") Тогда
			ИсторияЧата.Добавить(Новый Структура("role,content", "assistant", ОтветМодели));
		КонецЕсли;
	КонецЕсли;

	Возврат ОтветМодели;
КонецФункции

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

	    // Проверка и удаление протокола
	    Если НРег(Лев(URL, 8)) = "https://" Тогда
	        РезультатРазбора.Схема = "https";
	        URL = Сред(URL, 9);
	    ИначеЕсли НРег(Лев(URL, 7)) = "http://" Тогда
	        РезультатРазбора.Схема = "http";
	        URL = Сред(URL, 8);
	    Иначе
	        ВызватьИсключение "Неверный формат URL: отсутствует протокол http или https";
	    КонецЕсли;

	    // Разделение хоста, порта и пути
	    ПозицияСлеш = СтрНайти(URL, "/");
	    Если ПозицияСлеш > 0 Тогда
	        ХостИПорт = Лев(URL, ПозицияСлеш - 1);
	        РезультатРазбора.Путь = Сред(URL, ПозицияСлеш);
	    Иначе
	        ХостИПорт = URL;
	        РезультатРазбора.Путь = "/";
	    КонецЕсли;

	    // Разделение хоста и порта
	    ПозицияДвоеточие = СтрНайти(ХостИПорт, ":");
	    Если ПозицияДвоеточие > 0 Тогда
	        РезультатРазбора.Хост = Лев(ХостИПорт, ПозицияДвоеточие - 1);
	        РезультатРазбора.Порт = Число(Сред(ХостИПорт, ПозицияДвоеточие + 1));
	    Иначе
	        РезультатРазбора.Хост = ХостИПорт;
	        РезультатРазбора.Порт = ?(РезультатРазбора.Схема = "https", 443, 80);
	    КонецЕсли;

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

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

	Возврат ЗаписьJSON.Закрыть();
КонецФункции

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


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

// Репозиторий проекта:
// https://github.com/vladimir-kharin/1c_formatter
//
// Харин Владимир (С) 2025. https://vharin.ru
// Telegram - https://t.me/vladimir_kharin

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

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

	// Находим позицию последнего закрывающего фигурного скобки, используя поиск с конца
	ПозицияКонца = СтрНайти(СтрокаJSON, "}", НаправлениеПоиска.СКонца);
	Если ПозицияКонца = 0 Тогда
		// Если закрывающая скобка не найдена, возвращаем Неопределено
		Возврат Неопределено;
	КонецЕсли;

	// Вычисляем длину фрагмента с JSON: от первого "{" до последнего "}" включительно
	ДлинаФрагмента = ПозицияКонца - ПозицияНачала + 1;

	// Извлекаем корректную часть JSON из строки
	ЧистыйJSON = Сред(СтрокаJSON, ПозицияНачала, ДлинаФрагмента);

	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ЧистыйJSON);

	Результат = ПрочитатьJSON(ЧтениеJSON);

	ЧтениеJSON.Закрыть();

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

// Отправляет запрос к ИИ API и возвращает ответ
//
// Параметры:
//  Текст        - Строка - Текущее сообщение пользователя для отправки модели
//  КлючAPI      - Строка - Ключ API для аутентификации
//  БазовыйАдрес - Строка - URL-адрес API, опционально, по умолчанию - OpenRouter
//  Модель       - Строка - Название модели, опционально, по умолчанию - deepseek/deepseek-chat
//  ИсторияЧата  - Массив - История чата в формате [{role: "user|assistant", content: "текст сообщения"}, ...].
//                           Этот параметр модифицируется внутри функции:
//                           - Текущее сообщение пользователя (параметр Текст) добавляется к истории
//                           - Ответ модели также добавляется к истории
//                           Если параметр не передан (Неопределено), функция работает в режиме
//                           одиночного запроса без поддержки контекста.
//
// Возвращаемое значение:
//  Строка - Текст ответа от модели (последнее сообщение ассистента)
//
// Примечание:
//  При использовании параметра ИсторияЧата учитывайте, что он будет изменен внутри функции.
//  Это позволяет поддерживать контекст беседы между несколькими вызовами функции.
&НаКлиенте
Функция ОтправитьЗапросOpenAI(Текст, КлючAPI, БазовыйАдрес = Неопределено, Модель = Неопределено, ИсторияЧата = Неопределено) Экспорт
	// Проверка наличия ключа API
	Если ПустаяСтрока(КлючAPI) Тогда
		ВызватьИсключение "Не указан ключ API";
	КонецЕсли;

	ТекБазовыйАдрес = ?(ЗначениеЗаполнено(БазовыйАдрес), БазовыйАдрес, "https://openrouter.ai/api/v1/chat/completions");
	ТекМодель = ?(ЗначениеЗаполнено(Модель), Модель, "deepseek/deepseek-chat");

	// Разбор базового адреса
	РазобранныйURL = РазобратьURL(ТекБазовыйАдрес);

	// Подготовка HTTP-запроса
	HTTPСоединение = Новый HTTPСоединение(
		РазобранныйURL.Хост,
		РазобранныйURL.Порт,
		,
		,
		,
		120,
		?(РазобранныйURL.Схема = "https", Новый ЗащищенноеСоединениеOpenSSL, Неопределено));
	HTTPЗапрос = Новый HTTPЗапрос(РазобранныйURL.Путь);
	HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
	HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer " + КлючAPI);

	// Формирование тела запроса
	СтруктураЗапроса = Новый Структура;
	СтруктураЗапроса.Вставить("model", ТекМодель);

	// Проверяем, передана ли история чата
	Если ТипЗнч(ИсторияЧата) = Тип("Массив") Тогда
		// Добавляем текущее сообщение к истории
		Если ЗначениеЗаполнено(Текст) Тогда
			ИсторияЧата.Добавить(Новый Структура("role,content", "user", Текст));
		КонецЕсли;

		// Используем обновленную историю сообщений
		СтруктураЗапроса.Вставить("messages", ИсторияЧата);
	Иначе
		// Режим обратной совместимости - создаем новый массив с одним сообщением
		СтруктураЗапроса.Вставить("messages", Новый Массив);
		СтруктураЗапроса.messages.Добавить(Новый Структура("role,content", "user", Текст));
	КонецЕсли;

	HTTPЗапрос.УстановитьТелоИзСтроки(СтруктураВJSON(СтруктураЗапроса));

	// Отправка запроса
	Попытка
		HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
	Исключение
		ВызватьИсключение "Ошибка отправки запроса: " + ОписаниеОшибки();
	КонецПопытки;

	// Обработка ответа
	ТелоОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
	Если HTTPОтвет.КодСостояния <> 200 Тогда
		ВызватьИсключение СтрШаблон(
			"Ошибка API. Код: %1, Ответ: %2",
			HTTPОтвет.КодСостояния,
			ТелоОтвета
		);
	КонецЕсли;

	// Разбор JSON-ответа
	ОтветJSON = JSONВСтруктуру(ТелоОтвета);

	// Проверка на наличие ошибки в ответе
	Если ОтветJSON.Свойство("error") Тогда
		ВызватьИсключение СтрШаблон(
			"Ошибка API. Код: %1, Сообщение: %2",
			ОтветJSON.error.code,
			ТелоОтвета
		);
	КонецЕсли;

	// Получаем ответ модели
	ОтветМодели = "";
	Если ОтветJSON.choices.Количество() > 0 Тогда
		ОтветМодели = ОтветJSON.choices[0].message.content;

		// Если передана история чата, добавляем в неё ответ модели
		Если ТипЗнч(ИсторияЧата) = Тип("Массив") Тогда
			ИсторияЧата.Добавить(Новый Структура("role,content", "assistant", ОтветМодели));
		КонецЕсли;
	КонецЕсли;

	Возврат ОтветМодели;
КонецФункции

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

	    // Проверка и удаление протокола
	    Если НРег(Лев(URL, 8)) = "https://" Тогда
	        РезультатРазбора.Схема = "https";
	        URL = Сред(URL, 9);
	    ИначеЕсли НРег(Лев(URL, 7)) = "http://" Тогда
	        РезультатРазбора.Схема = "http";
	        URL = Сред(URL, 8);
	    Иначе
	        ВызватьИсключение "Неверный формат URL: отсутствует протокол http или https";
	    КонецЕсли;

	    // Разделение хоста, порта и пути
	    ПозицияСлеш = СтрНайти(URL, "/");
	    Если ПозицияСлеш > 0 Тогда
	        ХостИПорт = Лев(URL, ПозицияСлеш - 1);
	        РезультатРазбора.Путь = Сред(URL, ПозицияСлеш);
	    Иначе
	        ХостИПорт = URL;
	        РезультатРазбора.Путь = "/";
	    КонецЕсли;

	    // Разделение хоста и порта
	    ПозицияДвоеточие = СтрНайти(ХостИПорт, ":");
	    Если ПозицияДвоеточие > 0 Тогда
	        РезультатРазбора.Хост = Лев(ХостИПорт, ПозицияДвоеточие - 1);
	        РезультатРазбора.Порт = Число(Сред(ХостИПорт, ПозицияДвоеточие + 1));
	    Иначе
	        РезультатРазбора.Хост = ХостИПорт;
	        РезультатРазбора.Порт = ?(РезультатРазбора.Схема = "https", 443, 80);
	    КонецЕсли;

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

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

	Возврат ЗаписьJSON.Закрыть();
КонецФункции

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

[Assistant] Функция JSONВСтруктуру(СтрокаJSON)