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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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