Загрузка данных


// Полная замена обработчика добавления обращения.
// Внешние зависимости исходного модуля сохранены:
// ПолучитьКуратораУслуги, ПолучитьСтруктуруОтветственного, ПолучитьРГПоSLA,
// РазобратьJSON, ПолучитьJSONОшибка, ЗаписатьВJSONДокументИнцидентДетально.

// Создает обращение. Initiator может быть кодом контактного лица или объектом
// {Email: <адрес>, Name: <ФИО>}.
//
// Параметры:
//  Запрос - HTTPСервисЗапрос - запрос на создание обращения.
//
// Возвращаемое значение:
//  HTTPСервисОтвет - созданное или ранее созданное обращение либо описание ошибки.
Функция Расш1_AddNewIncidentPost(Запрос)
	Перем ВнешняяТранзакция;

	ВнешняяТранзакция = ТранзакцияАктивна();
	Попытка
		Ответ = Новый HTTPСервисОтвет(200);
		ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку();
		Массив = РазобратьJSON(ТелоЗапроса);

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

		ТекСоот = Массив[0];
		// {+} ЦФ Амбарцумов 12.10.2026
		ВнешнийID = ТекСоот.Получить("ExternalId");
		Если ВнешнийID <> Неопределено Тогда
			НайденноеОбращение = Документы.Инцидент.НайтиПоРеквизиту("ВнешнийID", ВнешнийID);
			Если НайденноеОбращение <> Документы.Инцидент.ПустаяСсылка() Тогда
				Ответ.УстановитьТелоИзСтроки(
					ЗаписатьВJSONДокументИнцидентДетально(НайденноеОбращение).Закрыть());
				Возврат Ответ;
			КонецЕсли;
		КонецЕсли;
		// {-} ЦФ Амбарцумов 12.10.2026

		РезультатИнициатора = Расш1_РазрешитьИнициатора(ТекСоот.Получить("Initiator"));
		Если Не РезультатИнициатора.Успех Тогда
			Возврат Расш1_ПолучитьОтветОшибки(
				РезультатИнициатора.КодОтвета,
				РезультатИнициатора.ТекстОшибки);
		КонецЕсли;

		Если ВнешняяТранзакция Тогда
			НовыйДокумент = Расш1_СоздатьИЗаписатьОбращение(
				ТекСоот,
				ВнешнийID,
				РезультатИнициатора);
		Иначе
			НовыйДокумент = Расш1_СоздатьОбращениеВТранзакции(
				ТекСоот,
				ВнешнийID,
				РезультатИнициатора);
		КонецЕсли;

		Ответ.УстановитьТелоИзСтроки(
			ЗаписатьВJSONДокументИнцидентДетально(НовыйДокумент.Ссылка).Закрыть());
		Возврат Ответ;
	Исключение
		Если ВнешняяТранзакция Тогда
			ВызватьИсключение;
		КонецЕсли;

		Если СтрНайти(ОписаниеОшибки(), "Расш1_ОшибкаЗаписиОбращения") > 0 Тогда
			Возврат Расш1_ПолучитьОтветОшибки(200, "Не удалось записать создаваемый документ");
		КонецЕсли;

		Возврат Расш1_ПолучитьОтветОшибки(500, "Не удалось обработать запрос");
	КонецПопытки;
КонецФункции

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

// Создает недостающего инициатора, заполняет и записывает обращение и наряды.
// Транзакцией управляет вызывающий код.
Функция Расш1_СоздатьИЗаписатьОбращение(ТекСоот, ВнешнийID, РезультатИнициатора)
	Перем СценарийОбработки, Отказ;

	Если РезультатИнициатора.НужноСоздатьКонтакт Тогда
		КонтактноеЛицо = Расш1_СоздатьКонтактноеЛицо(РезультатИнициатора);
	Иначе
		КонтактноеЛицо = РезультатИнициатора.КонтактноеЛицо;
	КонецЕсли;

	НовыйДокумент = Документы.Инцидент.СоздатьДокумент();
	НовыйДокумент.КонтактноеЛицо = КонтактноеЛицо;
	НовыйДокумент.Клиент = РезультатИнициатора.Клиент;
	Если ВнешнийID <> Неопределено Тогда
		НовыйДокумент.ВнешнийID = ВнешнийID;
	КонецЕсли;

	// {+} ЦФ Амбарцумов 12.10.2026
	Если ТекСоот.Получить("TypeOfAppel") <> Неопределено Тогда
		ТипОбращения = ТекСоот.Получить("TypeOfAppel");
		Если ТипОбращения = "Incident" Тогда
			НовыйДокумент.Тип = Справочники.ИТ_ТипыИнцидентов.НайтиПоНаименованию("Инцидент", Истина);
		ИначеЕсли ТипОбращения = "ChangeRequest" Тогда
			НовыйДокумент.Тип = Справочники.ИТ_ТипыИнцидентов.НайтиПоНаименованию(
				"Запрос на изменение",
				Истина);
		КонецЕсли;
	КонецЕсли;

	Если ТекСоот.Получить("Topic") <> Неопределено Тогда
		НовыйДокумент.ТемаОбращения = ТекСоот.Получить("Topic");
	КонецЕсли;
	Если ТекСоот.Получить("Data") <> Неопределено Тогда
		НовыйДокумент.Дата = Дата(ТекСоот.Получить("Data"));
	КонецЕсли;
	Если ТекСоот.Получить("Description") <> Неопределено Тогда
		НовыйДокумент.Описание = ТекСоот.Получить("Description");
	КонецЕсли;

	Если ТипЗнч(ТекСоот.Получить("MembershipServices")) = Тип("Соответствие")
		И ТекСоот.Получить("MembershipServices").Получить("UID") <> Неопределено
		И Не ПустаяСтрока(Строка(ТекСоот.Получить("MembershipServices").Получить("UID"))) Тогда
		НовыйДокумент.КомпонентаУслуги = Справочники.СоставУслуг.ПолучитьСсылку(
			Новый УникальныйИдентификатор(
				ТекСоот.Получить("MembershipServices").Получить("UID")));
		НовыйДокумент.Услуга = НовыйДокумент.КомпонентаУслуги.Владелец;
	КонецЕсли;

	Если ТипЗнч(ТекСоот.Получить("Category")) = Тип("Соответствие")
		И ТекСоот.Получить("Category").Получить("UID") <> Неопределено
		И Не ПустаяСтрока(Строка(ТекСоот.Получить("Category").Получить("UID"))) Тогда
		НовыйДокумент.Категория = Справочники.ИТ_Категории.ПолучитьСсылку(
			Новый УникальныйИдентификатор(ТекСоот.Получить("Category").Получить("UID")));
	КонецЕсли;

	Если ТипЗнч(ТекСоот.Получить("ConfigurationItems")) = Тип("Массив") Тогда
		Для Каждого Соот Из ТекСоот.Получить("ConfigurationItems") Цикл
			НовыйДокумент.КонфигурационныеЕдиницы.Добавить().КЕ =
				Справочники.ОбъектыОбслуживания.ПолучитьСсылку(
					Новый УникальныйИдентификатор(Соот.Получить("UID")));
		КонецЦикла;
	КонецЕсли;
	// {-} ЦФ Амбарцумов 12.10.2026

	// {+} ЦФ Амбарцумов 26.10.2026
	Если ТекСоот.Получить("IsMassIncident") <> Неопределено Тогда
		НовыйДокумент.ЦФ_ПодозрениеНаМассовуюПроблему = ТекСоот.Получить("IsMassIncident");
	КонецЕсли;
	// {-} ЦФ Амбарцумов 26.10.2026

	ТекущееКонтактноеЛицо = ИТ_ГлобальныйМодульСервер.Ит_глЗначениеПеременной(
		"глТекущееКонтактноеЛицо");
	НовыйДокумент.ЧасовойПоясДокумента = ПолучениеЗначенийСервер.ПолучитьПараметр(
		"ИТ_ЧасовойПояс",
		ТекущееКонтактноеЛицо);
	НовыйДокумент.ДатаНачалаРегистрации = НовыйДокумент.Дата;
	НовыйДокумент.КаналСвязи = Справочники.ИТ_КаналыСвязи.WebИнтерфейс;

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

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

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

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

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

	Возврат НовыйДокумент;
КонецФункции

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

	Если ТипЗнч(ЗначениеИнициатора) = Тип("Строка") Тогда
		КонтактноеЛицо = Справочники.ИТ_КонтактныеЛица.НайтиПоКоду(ЗначениеИнициатора);
		Возврат Расш1_ПроверитьСуществующийКонтакт(КонтактноеЛицо, "");
	КонецЕсли;

	Если ТипЗнч(ЗначениеИнициатора) <> Тип("Соответствие") Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(400, "Некорректный параметр Initiator");
	КонецЕсли;

	Имя = ЗначениеИнициатора.Получить("Name");
	АдресПочты = ЗначениеИнициатора.Получить("Email");
	Если ТипЗнч(Имя) <> Тип("Строка") Или ТипЗнч(АдресПочты) <> Тип("Строка") Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			400,
			"Параметры Initiator.Name и Initiator.Email должны быть строками");
	КонецЕсли;

	Имя = СокрЛП(Имя);
	АдресПочты = СокрЛП(АдресПочты);
	Если Имя = "" Или СтрДлина(Имя) > 100
		Или СтрНайти(Имя, Символы.ПС) > 0
		Или СтрНайти(Имя, Символы.ВК) > 0
		Или СтрНайти(Имя, Символы.Таб) > 0 Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(400, "Некорректное значение Initiator.Name");
	КонецЕсли;
	Если Не Расш1_КорректныйАдресПочты(АдресПочты) Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(400, "Некорректное значение Initiator.Email");
	КонецЕсли;

	Контакты = Расш1_НайтиКонтактыПоФИОИПочте(Имя, АдресПочты);
	АктивныеКонтакты = Новый Массив;
	Для Каждого ДанныеКонтакта Из Контакты Цикл
		Если Не ДанныеКонтакта.Уволен Тогда
			АктивныеКонтакты.Добавить(ДанныеКонтакта);
		КонецЕсли;
	КонецЦикла;

	Если АктивныеКонтакты.Количество() > 1 Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			409,
			"Найдено несколько активных контактных лиц с указанными данными");
	ИначеЕсли АктивныеКонтакты.Количество() = 1 Тогда
		Возврат Расш1_ПроверитьСуществующийКонтакт(
			АктивныеКонтакты[0].КонтактноеЛицо,
			Имя);
	ИначеЕсли Контакты.Количество() > 0 Тогда
		ФактическоеИмя = Контакты[0].Наименование;
		Если ПустаяСтрока(ФактическоеИмя) Тогда
			ФактическоеИмя = Имя;
		КонецЕсли;
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			404,
			СтрШаблон("Контактное лицо %1 уволено", ФактическоеИмя));
	КонецЕсли;

	ФизическиеЛица = Расш1_НайтиФизическиеЛицаПоФИОИПочте(Имя, АдресПочты);
	АктивныеФизическиеЛица = Новый Массив;
	Для Каждого ДанныеФизическогоЛица Из ФизическиеЛица Цикл
		Если Не ДанныеФизическогоЛица.Уволен Тогда
			АктивныеФизическиеЛица.Добавить(ДанныеФизическогоЛица);
		КонецЕсли;
	КонецЦикла;

	Если АктивныеФизическиеЛица.Количество() > 1 Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			409,
			"Найдено несколько активных физических лиц с указанными данными");
	ИначеЕсли АктивныеФизическиеЛица.Количество() = 1 Тогда
		Возврат Расш1_ПолучитьПланСозданияКонтакта(
			АктивныеФизическиеЛица[0].ФизическоеЛицо,
			Имя,
			АдресПочты);
	ИначеЕсли ФизическиеЛица.Количество() > 0 Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			404,
			СтрШаблон("Контактное лицо %1 уволено", Имя));
	КонецЕсли;

	Возврат Расш1_ПолучитьПланСозданияКонтакта(
		Справочники.ФизическиеЛица.ПустаяСсылка(),
		Имя,
		АдресПочты);
КонецФункции

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

	РезультатЗапроса = Запрос.Выполнить();
	Выборка = РезультатЗапроса.Выбрать();
	Результат = Новый Массив;
	Пока Выборка.Следующий() Цикл
		Результат.Добавить(Новый Структура(
			"КонтактноеЛицо,Наименование,Клиент,Уволен",
			Выборка.КонтактноеЛицо,
			Выборка.Наименование,
			Выборка.Клиент,
			Выборка.Уволен));
	КонецЦикла;
	Возврат Результат;
КонецФункции

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

	РезультатЗапроса = Запрос.Выполнить();
	Выборка = РезультатЗапроса.Выбрать();
	Результат = Новый Массив;
	Пока Выборка.Следующий() Цикл
		Результат.Добавить(Новый Структура(
			"ФизическоеЛицо,Уволен",
			Выборка.ФизическоеЛицо,
			Выборка.Уволен));
	КонецЦикла;
	Возврат Результат;
КонецФункции

// Проверяет существующий контакт из старого формата или текущего сеанса.
Функция Расш1_ПроверитьСуществующийКонтакт(КонтактноеЛицо, ИмяДляОшибки)
	Если Не ЗначениеЗаполнено(КонтактноеЛицо) Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(404, "Контактное лицо не найдено");
	КонецЕсли;

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

	ФактическоеИмя = Выборка.Наименование;
	Если ПустаяСтрока(ФактическоеИмя) Тогда
		ФактическоеИмя = ИмяДляОшибки;
	КонецЕсли;
	Если Не Выборка.Используется Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			404,
			СтрШаблон("Контактное лицо %1 уволено", ФактическоеИмя));
	КонецЕсли;
	Если Не ЗначениеЗаполнено(Выборка.Клиент) Тогда
		Возврат Расш1_ПолучитьОшибкаИнициатора(
			500,
			"Не удалось определить клиента контактного лица");
	КонецЕсли;

	Возврат Расш1_ПолучитьУспехИнициатора(КонтактноеЛицо, Выборка.Клиент);
КонецФункции

// Возвращает проверенный план создания контакта для существующего или нового физлица.
Функция Расш1_ПолучитьПланСозданияКонтакта(ФизическоеЛицо, Имя, АдресПочты)
	Если Не ЗначениеЗаполнено(ФизическоеЛицо) Тогда
		ФИО = Расш1_РазобратьФИО(Имя);
		Если СтрДлина(ФИО.Фамилия) > 50
			Или СтрДлина(ФИО.Имя) > 50
			Или СтрДлина(ФИО.Отчество) > 50 Тогда
			Возврат Расш1_ПолучитьОшибкаИнициатора(
				400,
				"Компоненты Initiator.Name не должны превышать 50 символов");
		КонецЕсли;
	КонецЕсли;

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

	Результат = Расш1_ПолучитьУспехИнициатора(
		Справочники.ИТ_КонтактныеЛица.ПустаяСсылка(),
		КлиентПоУмолчанию);
	Результат.НужноСоздатьКонтакт = Истина;
	Результат.ФизическоеЛицо = ФизическоеЛицо;
	Результат.Имя = Имя;
	Результат.АдресПочты = АдресПочты;
	Результат.СостояниеПоУмолчанию = СостояниеПоУмолчанию;
	Возврат Результат;
КонецФункции

// Создает недостающие данные инициатора внутри транзакции обработчика.
Функция Расш1_СоздатьКонтактноеЛицо(ПланИнициатора)
	ФизическоеЛицо = ПланИнициатора.ФизическоеЛицо;
	Если Не ЗначениеЗаполнено(ФизическоеЛицо) Тогда
		НовоеФизЛицо = Справочники.ФизическиеЛица.СоздатьЭлемент();
		НовоеФизЛицо.Наименование = ПланИнициатора.Имя;
		НовоеФизЛицо.Записать();
		ФизическоеЛицо = НовоеФизЛицо.Ссылка;

		ФИО = Расш1_РазобратьФИО(ПланИнициатора.Имя);
		МенеджерЗаписиФИО = РегистрыСведений.ФИОФизЛиц.СоздатьМенеджерЗаписи();
		МенеджерЗаписиФИО.ФизЛицо = ФизическоеЛицо;
		МенеджерЗаписиФИО.Период = ТекущаяДатаСеанса();
		МенеджерЗаписиФИО.Фамилия = ФИО.Фамилия;
		МенеджерЗаписиФИО.Имя = ФИО.Имя;
		МенеджерЗаписиФИО.Отчество = ФИО.Отчество;
		МенеджерЗаписиФИО.Записать(Истина);

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

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

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

	НовыйВид = Справочники.ВидыКонтактнойИнформации.СоздатьЭлемент();
	НовыйВид.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
	НовыйВид.ВидОбъектаКонтактнойИнформации =
		Перечисления.ВидыОбъектовКонтактнойИнформации.ФизическиеЛица;
	НовыйВид.Наименование = "Основной";
	НовыйВид.Записать();
	Возврат НовыйВид.Ссылка;
КонецФункции

Функция Расш1_РазобратьФИО(ПолноеИмя)
	ЧастиФИО = СтрРазделить(ПолноеИмя, " ", Ложь);
	Фамилия = "";
	Имя = "";
	Отчество = "";
	Если ЧастиФИО.Количество() > 0 Тогда
		Фамилия = ЧастиФИО[0];
	КонецЕсли;
	Если ЧастиФИО.Количество() > 1 Тогда
		Имя = ЧастиФИО[1];
	КонецЕсли;
	Для ИндексЧасти = 2 По ЧастиФИО.ВГраница() Цикл
		Если Отчество <> "" Тогда
			Отчество = Отчество + " ";
		КонецЕсли;
		Отчество = Отчество + ЧастиФИО[ИндексЧасти];
	КонецЦикла;

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

Функция Расш1_КорректныйАдресПочты(АдресПочты)
	Если АдресПочты = "" Или СтрДлина(АдресПочты) > 254
		Или СтрНайти(АдресПочты, " ") > 0
		Или СтрНайти(АдресПочты, Символы.ПС) > 0
		Или СтрНайти(АдресПочты, Символы.ВК) > 0
		Или СтрНайти(АдресПочты, Символы.Таб) > 0
		Или НРег(Лев(АдресПочты, 7)) = "mailto:"
		Или СтрНайти(АдресПочты, "<") > 0
		Или СтрНайти(АдресПочты, ">") > 0
		Или СтрНайти(АдресПочты, "[") > 0
		Или СтрНайти(АдресПочты, "]") > 0
		Или СтрНайти(АдресПочты, "(") > 0
		Или СтрНайти(АдресПочты, ")") > 0 Тогда
		Возврат Ложь;
	КонецЕсли;

	ПозицияСобаки = СтрНайти(АдресПочты, "@");
	Если ПозицияСобаки <= 1 Или ПозицияСобаки >= СтрДлина(АдресПочты)
		Или СтрНайти(Сред(АдресПочты, ПозицияСобаки + 1), "@") > 0 Тогда
		Возврат Ложь;
	КонецЕсли;
	Возврат Истина;
КонецФункции

// Экранирует служебные символы ПОДОБНО; шаблон не содержит подстановочных процентов.
Функция Расш1_ЭкранироватьШаблонПочты(АдресПочты)
	Результат = СтрЗаменить(АдресПочты, "~", "~~");
	Результат = СтрЗаменить(Результат, "%", "~%");
	Результат = СтрЗаменить(Результат, "_", "~_");
	Результат = СтрЗаменить(Результат, "[", "~[");
	Результат = СтрЗаменить(Результат, "]", "~]");
	Результат = СтрЗаменить(Результат, "^", "~^");
	Возврат Результат;
КонецФункции

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

Функция Расш1_ПолучитьОшибкаИнициатора(КодОтвета, ТекстОшибки)
	Результат = Новый Структура;
	Результат.Вставить("Успех", Ложь);
	Результат.Вставить("КодОтвета", КодОтвета);
	Результат.Вставить("ТекстОшибки", ТекстОшибки);
	Возврат Результат;
КонецФункции

Функция Расш1_ПолучитьОтветОшибки(КодОтвета, ТекстОшибки)
	Ответ = Новый HTTPСервисОтвет(КодОтвета);
	Ответ.УстановитьТелоИзСтроки(ПолучитьJSONОшибка(ТекстОшибки));
	Возврат Ответ;
КонецФункции