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

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

// Включает или выключает почтовый клиент.
//
// Параметры:
//   Значение - Булево
//
Процедура УстановитьИспользованиеПочтовогоКлиента(Знач Значение) Экспорт

	Константы.ИспользоватьПочтовыйКлиент.Установить(Значение);

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

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

// Включает или выключает возможность отправки писем в формате HTML.
// Если выключить, то будет доступна отправка только в текстовом формате.
//
// Параметры:
//   Значение - Булево
//
Процедура УстановитьИспользованиеОтправкиПисемВФорматеHTML(Знач Значение) Экспорт

	Константы.ОтправлятьПисьмаВФорматеHTML.Установить(Значение);

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

// Проверяет возможность использования отправки писем в формате HTML.
//
// Возвращаемое значение:
//   Булево
//
Функция ИспользуетсяОтправкаПисемВФорматеHTML() Экспорт

	Возврат ПолучитьФункциональнуюОпцию("ОтправлятьПисьмаВФорматеHTML");

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

// Включает или выключает возможность учета телефонных звонков, SMS-сообщений,
// встреч и планирования взаимодействий.
//
// Параметры:
//   Значение - Булево
//
Процедура УстановитьИспользованиеПрочегоВзаимодействия(Знач Значение) Экспорт

	Константы.ИспользоватьПрочиеВзаимодействия.Установить(Значение);

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

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

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

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

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

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

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

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

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

	Если ТипЗнч(Объект) = Тип("ДокументОбъект.Встреча") 
		Или ТипЗнч(Объект) = Тип("ДокументОбъект.ЗапланированноеВзаимодействие") 
		Или ТипЗнч(Объект) = Тип("ДокументОбъект.СообщениеSMS") 
		Или ТипЗнч(Объект) = Тип("ДокументОбъект.ТелефонныйЗвонок") Тогда
		
		// Логика ограничения доступа по умолчанию: объект доступен если доступен  "Автор" или "Ответственный".
		// Ограничение по "УчетныеЗаписиЭлектроннойПочты".
		
		НомерНабора = 1;

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

		// Ограничение по "Ответственный".
		НомерНабора = НомерНабора + 1;

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

		СтрокаТаб = Таблица.Добавить();
		СтрокаТаб.НомерНабора     = НомерНабора;
		СтрокаТаб.ЗначениеДоступа = Объект.УчетнаяЗапись;

		// Ограничение по "Ответственный".
		НомерНабора = НомерНабора + 1;

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

		НомерНабора = 1;

		СтрокаТаблицы = Таблица.Добавить();
		СтрокаТаблицы.НомерНабора     = НомерНабора;
		СтрокаТаблицы.ЗначениеДоступа = Объект.УчетнаяЗапись;

		НомерНабора = НомерНабора + 1;

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

		НомерНабора = НомерНабора + 1;

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

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

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

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

// Выполняет полный перерасчет состояний по папкам, контактам и предметам.
//
Процедура ВыполнитьПолныйПерерасчетСостояний() Экспорт
	
	РассчитатьРассмотреноПоПапкам(Неопределено);
	РассчитатьРассмотреноПоКонтактам(Неопределено);
	РассчитатьРассмотреноПоПредметам(Неопределено);
	
КонецПроцедуры

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

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

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

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

#Область ШаблоныСообщений

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

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

		КонецПопытки;
		
	Иначе
		
		Письмо.Прочитать();
		Письмо.Удалить();
		
	КонецЕсли;
	
	РезультатОтправкиПисьма.Отправлено = Истина;
	Возврат РезультатОтправкиПисьма;
	
КонецФункции

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

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

	ТипСтрока = Новый ОписаниеТипов("Строка");

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

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

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

	Вложения = Новый ТаблицаЗначений;
	Вложения.Колонки.Добавить("Представление", ТипСтрока);
	Вложения.Колонки.Добавить("АдресВоВременномХранилище", ТипСтрока);
	Вложения.Колонки.Добавить("Кодировка", ТипСтрока);
	Вложения.Колонки.Добавить("Идентификатор", ТипСтрока);
	Сообщение.Вставить("Вложения", Вложения);

	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("Комментарий", "");
	ДополнительныеПараметры.Вставить("Предмет", "");
	ДополнительныеПараметры.Вставить("ФорматПисьма", Перечисления.СпособыРедактированияЭлектронныхПисем.HTML);
	ДополнительныеПараметры.Вставить("УведомитьОДоставке", Ложь);
	ДополнительныеПараметры.Вставить("УведомитьОПрочтении", Ложь);
	
	Сообщение.Вставить("ДополнительныеПараметры", ДополнительныеПараметры);

	Возврат Сообщение;

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

// Создает документ Сообщение SMS и отправляет его.
// 
// Параметры:
//  Сообщение - см. ШаблоныСообщенийСлужебный.СформироватьСообщение
//
Процедура СоздатьИОтправитьСообщениеSMS(Сообщение) Экспорт

	СообщениеSMS = Документы.СообщениеSMS.СоздатьДокумент();
	
	СообщениеSMS.Дата                    = ТекущаяДатаСеанса();
	СообщениеSMS.Автор                   = Пользователи.ТекущийПользователь();

	СообщениеSMS.Ответственный           = Пользователи.ТекущийПользователь();
	СообщениеSMS.Важность                = Перечисления.ВариантыВажностиВзаимодействия.Обычная;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// См. ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковОбновления.
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
	
	Обработчик = Обработчики.Добавить();
	Обработчик.НачальноеЗаполнение = Истина;
	Обработчик.Процедура = "Взаимодействия.ОтключитьПодсистемуВМоделиСервиса";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "3.1.5.108";
	Обработчик.Идентификатор = Новый УникальныйИдентификатор("35e85460-7125-4079-b5df-5a71dbb43a49");
	Обработчик.Процедура = "Справочники.ПапкиЭлектронныхПисем.ОбработатьДанныеДляПереходаНаНовуюВерсию";
	Обработчик.Комментарий =
		НСтр("ru = 'Заполняет в справочнике ""Папки электронных писем"" тип предопределенной папки'");
	Обработчик.РежимВыполнения = "Отложенно";
	Обработчик.ПроцедураЗаполненияДанныхОбновления = "Справочники.ПапкиЭлектронныхПисем.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
	Обработчик.ПроцедураПроверки    = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
	Обработчик.ЧитаемыеОбъекты      = "Справочник.ПапкиЭлектронныхПисем";
	Обработчик.ИзменяемыеОбъекты    = "Справочник.ПапкиЭлектронныхПисем";
	Обработчик.БлокируемыеОбъекты   = "Справочник.ПапкиЭлектронныхПисем";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "3.1.5.147";
	Обработчик.Идентификатор = Новый УникальныйИдентификатор("35e85660-7125-4079-b5df-5a71dbb43a48");
	Обработчик.Процедура = "Документы.ЭлектронноеПисьмоИсходящее.ОбработатьДанныеДляПереходаНаНовуюВерсию";
	Обработчик.Комментарий =
		НСтр("ru = 'Заполнение реквизита ""Текст"" документа ""Электронное письмо исходящее"" для писем в формате HTML у которых он ранее не был ошибочно заполнен'");
	Обработчик.РежимВыполнения = "Отложенно";
	Обработчик.ПроцедураЗаполненияДанныхОбновления = "Документы.ЭлектронноеПисьмоИсходящее.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
	Обработчик.ПроцедураПроверки    = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
	Обработчик.ЧитаемыеОбъекты      = "Документ.ЭлектронноеПисьмоИсходящее";
	Обработчик.ИзменяемыеОбъекты    = "Документ.ЭлектронноеПисьмоИсходящее";
	Обработчик.БлокируемыеОбъекты   = "Документ.ЭлектронноеПисьмоИсходящее";	
	
КонецПроцедуры

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

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

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

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

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

// См. УправлениеСвойствамиПереопределяемый.ПриПолученииПредопределенныхНаборовСвойств
Процедура ПриПолученииПредопределенныхНаборовСвойств(Наборы) Экспорт
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_Встреча";
	Набор.Идентификатор = Новый УникальныйИдентификатор("26c5b310-f6a7-47b0-b85a-6052216965e2");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_ЗапланированноеВзаимодействие";
	Набор.Идентификатор = Новый УникальныйИдентификатор("70425541-23e3-4e5a-8bd3-9587cc949dfa");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_СообщениеSMS";
	Набор.Идентификатор = Новый УникальныйИдентификатор("e9c48775-2727-46e1-bdb8-e9a0a68358a1");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_ТелефонныйЗвонок";
	Набор.Идентификатор = Новый УникальныйИдентификатор("da617a73-992a-42b9-8d20-e65e043c46bc");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_ЭлектронноеПисьмоВходящее";
	Набор.Идентификатор = Новый УникальныйИдентификатор("0467d0fe-1bf6-480d-ae0d-f2e36449d1df");
	
	Набор = Наборы.Строки.Добавить();
	Набор.Имя = "Документ_ЭлектронноеПисьмоИсходящее";
	Набор.Идентификатор = Новый УникальныйИдентификатор("123329af-4b94-4f47-9d39-e503190487bd");
КонецПроцедуры

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

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

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

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

// АПК:299-выкл программно вызываемая процедура

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

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

КонецПроцедуры
// АПК:299-вкл

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

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

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

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

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

#Область ВспомогательныеПроцедурыИФункцииОтвечающиеЗаПоискКонтактов

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

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

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

// Параметры:
//  Форма       - ФормаКлиентскогоПриложения - форма, для которой определяется таблица.
//  ИмяЭлемента - Строка - имя элемента форма.
// Возвращаемое значение:
//  ТаблицаФормы
//
Функция ТаблицаФормыПоИмени(Форма, ИмяЭлемента) 
	
	Возврат Форма.Элементы[ИмяЭлемента];
	
КонецФункции

// Параметры:
//  Адрес  - Строка - содержит адрес электронной почты из которого извлекается доменный адрес.
//
// Возвращаемое значение:
//   Строка   - полученный доменный адрес.
//
Функция ПолучитьДоменныйАдресДляПоиска(Адрес)
	
	Строка = Адрес;
	Позиция = СтрНайти(Строка, "@");
	Возврат ?(Позиция = 0, "", Сред(Строка, Позиция+1));
	
КонецФункции

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

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

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

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

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

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

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

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

// Параметры:
//  СтрокаТаблицы - ДанныеФормыЭлементКоллекции
//
// Возвращаемое значение:
//  Структура:
//    * Наименование          - Строка
//    * НаименованиеВладельца - Строка
//
Функция СтрокаТаблицыКонтакты(СтрокаТаблицы)
	
	Возврат СтрокаТаблицы;
	
КонецФункции

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

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

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

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

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

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

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

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

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

// Формирует шаблон условия для запроса на соответствие получаемого поля в запросе типу возможного контакта.
//
// Возвращаемое значение:
//  Строка
//
Функция ШаблонУсловияНаСсылкиКонтактовДляЗапроса()
	
	Результат =  "КонтактыВзаимодействия.ИмяПоля ССЫЛКА Справочник.Пользователи"; // @query-part
	Для каждого ОписаниеКонтакта Из ВзаимодействияКлиентСервер.ОписанияКонтактов() Цикл
		Если ОписаниеКонтакта.Имя = "Пользователи" Тогда
			Продолжить;
		КонецЕсли;
		
		ШаблонУсловия = "ИЛИ КонтактыВзаимодействия.ИмяПоля ССЫЛКА Справочник.Пользователи"; // @query-part
		ШаблонУсловия = СтрЗаменить(ШаблонУсловия, "Пользователи", ОписаниеКонтакта.Имя);
		
		Результат = Результат + Символы.ПС + ШаблонУсловия;
	КонецЦикла;
	
	Результат = СтрЗаменить(Результат, "ИмяПоля", "%ИмяПоля%");
	Возврат Результат;
	
КонецФункции

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

	Результат = ПолнотекстовыйПоискКонтактовПоСтроке(СтрокаПоиска, НайденныеКонтакты, ДляАдреснойКниги);
	Если ПустаяСтрока(Результат) Тогда
		НайтиПоEmail(СтрокаПоиска, Ложь, НайденныеКонтакты);
	КонецЕсли;
	Возврат Результат;
	
КонецФункции

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

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

	КонецЦикла;
	
	Если ТекстыЗапроса.Количество() = 0 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ТекстЗапроса = СтрСоединить(ТекстыЗапроса, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС) + "
		|УПОРЯДОЧИТЬ ПО
		|	Ссылка,
		|	АдресЭП"; // @query-part-1, @query-part-2
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("СтрокаПоиска", "%@" + ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе(ИмяДомена) + "%");	
	Возврат Запрос.Выполнить().Выгрузить();
	
КонецФункции

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

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

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

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

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

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

#Область ПроцедурыИФункцииПолученияДанныхКонтактовВзаимодействийИПредметовВзаимодействий

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

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

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

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

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

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

#Область ПроцедурыИФункцииРаботыСВзаимодействиями

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

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

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

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

// Параметры:
//  Контакты - Массив 
//
// Возвращаемое значение:
//  Булево
//
Функция КонтактыЗаполнены(Контакты) Экспорт
	
	Возврат (ЗначениеЗаполнено(Контакты) И (Контакты.Количество() > 0));
	
КонецФункции

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

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

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

// Формирует строку-представление списка участников взаимодействия.
//
// Параметры:
//  Объект - ДокументОбъект - документ, на основании табличной части участники которого формируется строка.
//
Процедура СформироватьСписокУчастников(Объект) Экспорт
	
	Если  ТипЗнч(Объект) = Тип("ДокументОбъект.СообщениеSMS") Тогда
		ИмяТаблицы = "Адресаты";
	Иначе 
		ИмяТаблицы = "Участники";
	КонецЕсли;
	
	Объект.СписокУчастников = "";
	Для Каждого Участник Из Объект[ИмяТаблицы] Цикл
		Объект.СписокУчастников = Объект.СписокУчастников + ?(Объект.СписокУчастников = "", "", "; ") + Участник.ПредставлениеКонтакта;
	КонецЦикла;
	
КонецПроцедуры

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Процедура ДобавитьВложениеПисьмоИсходящееПисьмо(МассивВложений, Письмо); 

	СтруктураВложение = Новый Структура;
	
	ДанныеИнтернетПочтовогоСообщения = ИнтернетПочтовоеСообщениеИзПисьма(Письмо);
	
	Если ДанныеИнтернетПочтовогоСообщения.ИнтернетПочтовоеСообщение = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Представление = ПредставлениеПисьма(ДанныеИнтернетПочтовогоСообщения.ИнтернетПочтовоеСообщение.Тема,
	                                    ДанныеИнтернетПочтовогоСообщения.ДатаПисьма);
	ИмяФайла = Представление + ".eml";
	
	СтруктураВложение.Вставить("Кодировка", Письмо.Кодировка);
	СтруктураВложение.Вставить("АдресВоВременномХранилище",
	                           ПоместитьВоВременноеХранилище(ДанныеИнтернетПочтовогоСообщения.ИнтернетПочтовоеСообщение, 
	                                                         Новый УникальныйИдентификатор()));
	СтруктураВложение.Вставить("ТипСодержимого","message/rfc822");
	СтруктураВложение.Вставить("Представление", ИмяФайла);
	
	МассивВложений.Добавить(СтруктураВложение);
	
КонецПроцедуры 

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

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

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

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

	Возврат СтруктураВозврата;

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

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

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

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

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

Процедура ДобавитьПолучателейВПочтовоеСообщениеПоВыборке(ТаблицаАдресатов, Выборка)
	
	Пока Выборка.Следующий() Цикл
		
		ДобавитьПолучателяВПочтовоеСообщение(ТаблицаАдресатов, Выборка.Адрес, Выборка.Представление)
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ДобавитьПолучателяВПочтовоеСообщение(ТаблицаАдресатов, Адрес, Представление)
	
	ПолучательПисьма                 = ТаблицаАдресатов.Добавить(Адрес);
	ПолучательПисьма.ОтображаемоеИмя = Представление;
	
КонецПроцедуры

Процедура ДобавитьВложенияПисьмаВПочтовоеСообщение(Сообщение, ВыборкаВложения)
	
	Пока ВыборкаВложения.Следующий() Цикл
		
		Имя   = ВыборкаВложения.ПолноеНаименование 
		        + ?(ВыборкаВложения.Расширение = "", "", "." + ВыборкаВложения.Расширение);
		Данные = РаботаСФайлами.ДвоичныеДанныеФайла(ВыборкаВложения.Ссылка);
		
		ВложениеПисьма = Сообщение.Вложения.Добавить(Данные, Имя);

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

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

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

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

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

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

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

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

#Область ОбработчикиОбновления

Процедура ОтключитьПодсистемуВМоделиСервиса() Экспорт

	Если ОбщегоНазначения.РазделениеВключено() Тогда
		
		Константы.ИспользоватьПочтовыйКлиент.Установить(Ложь);
		Константы.ИспользоватьПризнакРассмотрено.Установить(Ложь);
		Константы.ИспользоватьПрочиеВзаимодействия.Установить(Ложь);
		Константы.ОтправлятьПисьмаВФорматеHTML.Установить(Ложь);
		
	КонецЕсли;

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

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

#Область РаботаСЭлементамиИРеквизитамиФормСписковИДокументов

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

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

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

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

// Параметры:
//  Форма     - ФормаКлиентскогоПриложения - форма, для которой выполняется инициализация реквизитов, содержит:
//   * Команды - КомандыФормы - содержат в том числе:
//    ** ПредметСписок - КомандаФормы
//    ** Предмет       - КомандаФормы
//  Параметры - Структура:
//    * ТолькоПочта - Булево
//
Процедура ИнициализироватьФормуСпискаВзаимодействий(Форма, Параметры) Экспорт

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

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

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

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

#Область РаботаСПредметамиВзаимодействий

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

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

#Область ФормированиеПисьма

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

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

// Параметры:
//  ПараметрыФормирования - Структура - параметры формирования документа HTML:
//   * Письмо  - ДокументСсылка.ЭлектронноеПисьмоВходящее
//             - ДокументСсылка.ЭлектронноеПисьмоИсходящее - письмо для которого будет проведена оценка.
//   * ТипТекста  - ПеречислениеСсылка.ТипыТекстовЭлектронныхПисем - тип текста письма.
//   * Текст  - Строка - текста письма.
//   * ТекстHTML  - Строка - текста письма в формате HTML.
//   * ТипТекстаПреобразование  - ПеречислениеСсылка.ТипыТекстовЭлектронныхПисем - тип текста в который преобразуется
//                                                                                 письмо.
//   * Кодировка  - Строка - кодировка письма.
//   * ОбработатьКартинки - Булево - признак того что картинки будут вложены в HTML.
//  ЕстьВнешниеРесурсы - Булево - возвращаемое значение, Истина, если письмо содержит элементы, загружаемые из Интернета.
//
// Возвращаемое значение:
//   Строка   - обработанный текст электронного письма.
//
Функция СформироватьДокументHTMLНаОснованииПисьма(ПараметрыФормирования, ЕстьВнешниеРесурсы = Неопределено) Экспорт
	
	Письмо = ПараметрыФормирования.Письмо;
	ТипТекста = ПараметрыФормирования.ТипТекста;
	Текст = ПараметрыФормирования.Текст;
	ТекстHTML = ПараметрыФормирования.ТекстHTML;
	ТипТекстаПреобразование = ?(ПараметрыФормирования.ТипТекстаПреобразование = Неопределено,
		ПараметрыФормирования.ТипТекста, ПараметрыФормирования.ТипТекстаПреобразование);
	Кодировка = ПараметрыФормирования.Кодировка;
	ОбработатьКартинки = ПараметрыФормирования.ОбработатьКартинки;
	ОтключитьВнешниеРесурсы = ПараметрыФормирования.ОтключитьВнешниеРесурсы;
		
	Если ТипТекста <> ТипТекстаПреобразование 
		И ТипТекста <> Перечисления.ТипыТекстовЭлектронныхПисем.ПростойТекст Тогда
		
		ТекстВходящегоПисьма = ПолучитьОбычныйТекстИзHTML(ТекстHTML);
		ДокументHTML = ПолучитьДокументHTMLИзОбычногоТекста(ТекстВходящегоПисьма);
		
	ИначеЕсли ТипТекста = Перечисления.ТипыТекстовЭлектронныхПисем.ПростойТекст 
		ИЛИ (ТипТекста.Пустая() И СокрЛП(ТекстHTML) = "") Тогда
		
		ДокументHTML = ПолучитьДокументHTMLИзОбычногоТекста(Текст);
		
	Иначе
		
		КодировкаПисьма = Кодировка;
		Если ПустаяСтрока(КодировкаПисьма) Тогда
			ПозицияАтрибутаКодировки = СтрНайти(ТекстHTML, "charset");
			Если ПозицияАтрибутаКодировки <> 0 Тогда
				Инд = 0;
				Пока КодСимвола(Сред(ТекстHTML,ПозицияАтрибутаКодировки + 8 + Инд,1)) <> 34 Цикл
					КодировкаПисьма = КодировкаПисьма + Сред(ТекстHTML,ПозицияАтрибутаКодировки + 8 + Инд,1);
					Инд = Инд + 1;
				КонецЦикла
			Иначе
				КодировкаПисьма = "utf8";
			КонецЕсли;
		КонецЕсли;
		
		Если ТипЗнч(Письмо) = Тип("Структура") Тогда
			ТаблицаФайлов = Письмо.Вложения;
		Иначе
			ТаблицаФайлов = ПолучитьВложенияПисьмаСНеПустымИД(Письмо);
		КонецЕсли;
		
		ТекстКОбработке = ТекстHTML;
		
		НетТела = (СтрЧислоВхождений(НРег(ТекстКОбработке), "<body") = 0);
		НетЗаголовка = (СтрЧислоВхождений(НРег(ТекстКОбработке), "<html") = 0);
		Если НетТела И НетЗаголовка Тогда
			ТекстКОбработке = "<body>" + ТекстКОбработке + "</body>"
		КонецЕсли;
		Если НетЗаголовка Тогда
			ТекстКОбработке = "<html>" + ТекстКОбработке + "</html>"
		КонецЕсли;
		
		НомерПопытки = 1;
		ТекстПисьма = СодержимоеТегаHTML(ТекстКОбработке, "html", Истина, НомерПопытки);
		Пока СтрНайти(НРег(ТекстПисьма), "<body") = 0 
			И Не ПустаяСтрока(ТекстПисьма) Цикл
			НомерПопытки = НомерПопытки + 1;
			ТекстПисьма = СодержимоеТегаHTML(ТекстКОбработке, "html", Истина, НомерПопытки);
		КонецЦикла;
		
		Если ТаблицаФайлов.Количество() Тогда
			ДокументHTML = ЗаменитьИдентификаторыКартинокНаПутьКФайлам(ТекстПисьма, ТаблицаФайлов, КодировкаПисьма, ОбработатьКартинки);
		Иначе
			ДокументHTML = ПолучитьОбъектДокументHTMLИзТекстаHTML(ТекстПисьма, КодировкаПисьма);
		КонецЕсли;
		
	КонецЕсли;
	
	ЕстьВнешниеРесурсы = РаботаСПочтовымиСообщениями.ЕстьВнешниеРесурсы(ДокументHTML);
	РаботаСПочтовымиСообщениями.ОтключитьНебезопасноеСодержимое(ДокументHTML, ЕстьВнешниеРесурсы И ОтключитьВнешниеРесурсы);
	
	Возврат ДокументHTML;
	
КонецФункции
	
// Параметры:
//  Письмо  - ДокументСсылка.ЭлектронноеПисьмоВходящее
//          - ДокументСсылка.ЭлектронноеПисьмоИсходящее - письмо для которого будет проведена оценка.
//
// Возвращаемое значение:
//   Строка   - обработанный текст электронного письма.
//
Функция ОбработатьТекстHTML(Письмо, ОтключитьВнешниеРесурсы = Истина, ЕстьВнешниеРесурсы = Неопределено) Экспорт
	
	СтруктураРеквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Письмо,"ТекстHTML,Кодировка");
	ТекстHTML = СтруктураРеквизиты.ТекстHTML;
	Кодировка = СтруктураРеквизиты.Кодировка;
	
	Если Не ПустаяСтрока(ТекстHTML) Тогда
		
		// Добавим тег HTML если он отсутствует. Такие письма могут приходить к примеру с Gmail. 
		// Необходимо для корректного отображения в элементе формы.
		Если СтрЧислоВхождений(ТекстHTML,"<html") = 0 Тогда
			ТекстHTML = "<html>" + ТекстHTML + "</html>"
		КонецЕсли;
		
		ОтфильтроватьСодержимоеТекстаHTML(ТекстHTML, Кодировка, ОтключитьВнешниеРесурсы, ЕстьВнешниеРесурсы);
		
		ТаблицаФайлов = ПолучитьВложенияПисьмаСНеПустымИД(Письмо);
		
		Если ТаблицаФайлов.Количество() Тогда
			КоличествоЧастейHtml = СтрЧислоВхождений(ТекстHTML, "<html");
			Если КоличествоЧастейHtml > 1 Тогда
				ЧастиHtml = Новый Массив;
				НомерЧастиHtml = 1;
				Пока НомерЧастиHtml <= КоличествоЧастейHtml Цикл
					ЧастьHtml = СодержимоеТегаHTML(ТекстHTML, "html", Истина, НомерЧастиHtml);
					ЧастиHtml.Добавить(ЧастьHtml);
					НомерЧастиHtml = НомерЧастиHtml + 1;
				КонецЦикла;
				ТекстHTML = СтрСоединить(ЧастиHtml, Символы.ПС + "<br>");
			Иначе
				ТекстHTML = СодержимоеТегаHTML(ТекстHTML, "html", Истина);
			КонецЕсли;
			ДокументHTML = ЗаменитьИдентификаторыКартинокНаПутьКФайлам(ТекстHTML, ТаблицаФайлов, Кодировка);
			
			Возврат ПолучитьТекстHTMLИзОбъектаДокументHTML(ДокументHTML);
		КонецЕсли;
	КонецЕсли;
	
	Возврат ТекстHTML;
	
КонецФункции

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

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

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

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

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

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

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

	СтрокаКВозврату = "";
	
	Для Каждого Получатель Из ТаблицаПолучателей Цикл
		
		СтрокаКВозврату = СтрокаКВозврату + "'" 
		         + ?(ПустаяСтрока(Получатель.Представление), Получатель.Адрес, Получатель.Представление + "<"+ Получатель.Адрес+">") + "'"+ ", ";
		
	КонецЦикла;
	
	Если Не ПустаяСтрока(СтрокаКВозврату) Тогда
		
		СтрокаКВозврату = Лев(СтрокаКВозврату,СтрДлина(СтрокаКВозврату) - 2);
		
	КонецЕсли;
	
	Возврат СтрокаКВозврату;

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

// Формирует элемент HTML шапки исходящего электронного письма.
//
// Параметры:
//  ЭлементРодитель - ЭлементHTML - родительский элемент HTML, для которого будет добавлен элемент данных шапки.
//  ШапкаПисьма - Структура - выборка по данным письма.
//  ТолькоПоПредставлениюОтправителя - Булево - определяет необходимо ли включать адрес отправителя или только
//                                              представление.
//
Функция СформироватьЭлементДанныхШапкиПисьма(ЭлементРодитель, ШапкаПисьма, ТолькоПоПредставлениюОтправителя = Ложь)
	
	ДокументВладелец = ЭлементРодитель.ДокументВладелец;
	
	ЭлементТаблица = ДокументВладелец.СоздатьЭлемент("table");
	УстановитьАтрибутЭлементаHTML(ЭлементТаблица,"border", "0");
	
	ОтправительПредставление = ШапкаПисьма.ОтправительПредставление 
		+ ?(ТолькоПоПредставлениюОтправителя Или ПустаяСтрока(ШапкаПисьма.ОтправительАдрес),
	    	"",
	    	"[" + ШапкаПисьма.ОтправительАдрес +"]");
	
	ДобавитьСтрокуВТаблицу(ЭлементТаблица, "From: ", ОтправительПредставление);
	ДобавитьСтрокуВТаблицу(ЭлементТаблица, "Sent: ", Формат(ШапкаПисьма.Дата,"ДЛФ=D'"));
	
	ТаблицаПолучателейПисьма = ?(ТипЗнч(ШапкаПисьма.ПолучателиПисьма) = Тип("ТаблицаЗначений"),
		ШапкаПисьма.ПолучателиПисьма, ШапкаПисьма.ПолучателиПисьма.Выгрузить());
	ДобавитьСтрокуВТаблицу(ЭлементТаблица, "To: ", ПолучитьПредставленияПолучателейВходящегоПисьма(ТаблицаПолучателейПисьма));
	
	ТаблицаПолучателейКопий = ?(ТипЗнч(ШапкаПисьма.ПолучателиКопий) = Тип("ТаблицаЗначений"),
		ШапкаПисьма.ПолучателиКопий, ШапкаПисьма.ПолучателиКопий.Выгрузить());
	Если ТаблицаПолучателейКопий.Количество() > 0 Тогда
		ДобавитьСтрокуВТаблицу(ЭлементТаблица, "cc: ", ПолучитьПредставленияПолучателейВходящегоПисьма(ТаблицаПолучателейКопий));
	КонецЕсли;
	
	Тема = ?(ПустаяСтрока(ШапкаПисьма.Тема), НСтр("ru = '<Без Темы>'"), ШапкаПисьма.Тема);
	ДобавитьСтрокуВТаблицу(ЭлементТаблица, "Subject: ", Тема);
	
	Возврат ЭлементТаблица;
	
КонецФункции

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

// Параметры:
//  ДокументHTML - ДокументHTML - документ HTML в котором будет выполняться замена.
//  ТаблицаСоответствий - ТаблицаЗначений - таблица соответствий имен файлов и идентификаторов.
//
Процедура ЗаменитьИменаКартинокНаИдентификаторыПочтовыхВложенийВHTML(ДокументHTML, ТаблицаСоответствий) Экспорт
	
	ТаблицаСоответствий.Индексы.Добавить("ИмяФайла");
	Для каждого Картинка Из ДокументHTML.Картинки Цикл
		АтрибутИсточникКартинки = Картинка.Атрибуты.ПолучитьИменованныйЭлемент("src");
		
		НайденнаяСтрока = ТаблицаСоответствий.Найти(АтрибутИсточникКартинки.ТекстовоеСодержимое,"ИмяФайла");
		Если НайденнаяСтрока <> Неопределено Тогда
			НовыйАтрибутКартинки = АтрибутИсточникКартинки.КлонироватьУзел(Ложь);
			НовыйАтрибутКартинки.ТекстовоеСодержимое = "cid:" + НайденнаяСтрока.ИдентификаторФайлаДляHTML;
			Картинка.Атрибуты.УстановитьИменованныйЭлемент(НовыйАтрибутКартинки);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Функция СформироватьЭлементИмяПользователяУчетнойЗаписи(ЭлементРодитель,Выборка)
	
	ЭлементШрифт = ДобавитьЭлементСАтрибутами(ЭлементРодитель, "Font", Новый Структура("size,face", "3", "Tahoma"));
	ДобавитьТекстовыйУзел(ЭлементШрифт,Выборка.ИмяПользователяУчетнойЗаписи, Истина);
	
	Возврат ЭлементШрифт;
	
КонецФункции

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

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

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

// Параметры:
//  ТекстHTML  - Строка
//
// Возвращаемое значение:
//   ДокументHTML   - созданный документ HTML.
//
Функция ПолучитьОбъектДокументHTMLИзТекстаHTML(ТекстHTML, Кодировка = Неопределено) Экспорт
	
	Построитель = Новый ПостроительDOM;
	ЧтениеHTML = Новый ЧтениеHTML;
	
	НовыйТекстHTML = ТекстHTML;
	ПозицияОткрытиеXML = СтрНайти(НовыйТекстHTML,"<?xml");
	
	Если ПозицияОткрытиеXML > 0 Тогда
		
		ПозицияЗакрытиеXML = СтрНайти(НовыйТекстHTML,"?>");
		Если ПозицияЗакрытиеXML > 0 Тогда
			
			НовыйТекстHTML = ЛЕВ(НовыйТекстHTML,ПозицияОткрытиеXML - 1) + ПРАВ(НовыйТекстHTML,СтрДлина(НовыйТекстHTML) - ПозицияЗакрытиеXML -1);
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если Кодировка = Неопределено Тогда
		
		ЧтениеHTML.УстановитьСтроку(ТекстHTML);
		
	Иначе
		
		Попытка
		
			ЧтениеHTML.УстановитьСтроку(ТекстHTML, Кодировка);
		
		Исключение
			
			ЧтениеHTML.УстановитьСтроку(ТекстHTML);
			
		КонецПопытки;
		
	КонецЕсли;
	
	Возврат Построитель.Прочитать(ЧтениеHTML);
	
КонецФункции

// Параметры:
//  Текст  - Строка - текст из которого будет создан документ HTML.
//
// Возвращаемое значение:
//   ДокументHTML   - созданный документ HTML.
//
Функция ПолучитьДокументHTMLИзОбычногоТекста(Текст) Экспорт
	
	ДокументHTML = Новый ДокументHTML;
	
	ЭлементТело = ДокументHTML.СоздатьЭлемент("body");
	ДокументHTML.Тело = ЭлементТело;
	
	ЭлементБлок = ДокументHTML.СоздатьЭлемент("p");
	ЭлементТело.ДобавитьДочерний(ЭлементБлок);
	
	ЭлементШрифт = ЭлементШрифт(ДокументHTML, "2", "Tahoma");
	
	КоличествоСтрок = СтрЧислоСтрок(Текст);
	Для Инд = 1 По КоличествоСтрок Цикл
		ДобавитьТекстовыйУзел(ЭлементШрифт, СтрПолучитьСтроку(Текст, Инд), Ложь, ?(Инд = КоличествоСтрок, Ложь, Истина));
	КонецЦикла;
	
	ЭлементБлок.ДобавитьДочерний(ЭлементШрифт);
	
	Возврат ДокументHTML;
	
КонецФункции

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

// Создает атрибут элемента HTML и устанавливает его текстовое содержимое.
//
// Параметры:
//  ЭлементHTML  - ЭлементHTML - элемент для которого устанавливается атрибут.
//  Имя  - Строка - имя атрибута HTML.
//  ТекстовоеСодержимое  - Строка - текстовое содержимое атрибута.
//
Процедура УстановитьАтрибутЭлементаHTML(ЭлементHTML, Имя, ТекстовоеСодержимое)
	
	АтрибутHTML = ЭлементHTML.ДокументВладелец.СоздатьАтрибут(Имя);
	АтрибутHTML.ТекстовоеСодержимое = ТекстовоеСодержимое;
	ЭлементHTML.Атрибуты.УстановитьИменованныйЭлемент(АтрибутHTML);
	
КонецПроцедуры

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

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

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

// Параметры:
//  ЭлементРодитель  - ЭлементHTML - элемент,к которому будет добавлен дочерний элемент.
//  ВставляемыйЭлемент  - ЭлементHTML - вставляемый элемент HTML.
//  МассивДочернихЭлементовРодителя  - Массив - массив дочерних элементов родительского элемента.
//
Процедура ВставитьЭлементHTMLПервымДочернимЭлементом(ЭлементРодитель, ВставляемыйЭлемент, МассивДочернихЭлементовРодителя)
	
	Если МассивДочернихЭлементовРодителя.Количество() > 0 Тогда
		ЭлементРодитель.ВставитьПеред(ВставляемыйЭлемент, МассивДочернихЭлементовРодителя[0]);
	Иначе
		ЭлементРодитель.ДобавитьДочерний(ВставляемыйЭлемент);
	КонецЕсли;
	
КонецПроцедуры

Процедура ДобавитьСтрокуВТаблицу(ЭлементРодитель, ЗначениеКолонки1 = Неопределено, ЗначениеКолонки2 = Неопределено, ЗначениеКолонки3 = Неопределено)

	ДокументВладелец = ЭлементРодитель.ДокументВладелец;
	ЭлементСтрокаТаблицы = ДокументВладелец.СоздатьЭлемент("tr");
	Если ЗначениеКолонки1 <> Неопределено Тогда
		ДобавитьЯчейкуВТаблицу(ЭлементСтрокаТаблицы, ЗначениеКолонки1, Истина);
	КонецЕсли;
	Если ЗначениеКолонки2 <> Неопределено Тогда
		ДобавитьЯчейкуВТаблицу(ЭлементСтрокаТаблицы, ЗначениеКолонки2);
	КонецЕсли;
	Если ЗначениеКолонки3 <> Неопределено Тогда
		ДобавитьЯчейкуВТаблицу(ЭлементСтрокаТаблицы, ЗначениеКолонки3);
	КонецЕсли;
	
	ЭлементРодитель.ДобавитьДочерний(ЭлементСтрокаТаблицы);

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

Процедура ДобавитьЯчейкуВТаблицу(ЭлементСтрока, ЗначениеЯчейки, ВыделятьЖирным = Ложь)
	
	ЭлементЯчейка = ЭлементСтрока.ДокументВладелец.СоздатьЭлемент("td");
	ЭлементШрифт = ЭлементШрифт(ЭлементСтрока.ДокументВладелец, "2", "Tahoma"); 
	
	Если ВыделятьЖирным Тогда
		ЭлементЖирный = ЭлементШрифт.ДокументВладелец.СоздатьЭлемент("b");
		ЭлементЖирный.ТекстовоеСодержимое = ЗначениеЯчейки;
		ЭлементШрифт.ДобавитьДочерний(ЭлементЖирный);
	Иначе 
		ЭлементШрифт.ТекстовоеСодержимое = ЗначениеЯчейки;
	КонецЕсли;
	
	ЭлементЯчейка.ДобавитьДочерний(ЭлементШрифт);
	ЭлементСтрока.ДобавитьДочерний(ЭлементЯчейка);
	
КонецПроцедуры

Процедура ДополнитьТелоПисьмаПодваломВложения(ДокументHTML, Вложения) Экспорт

	ЭлементТелоПисьма = ЭлементТелоПисьма(ДокументHTML);
	ЭлементТелоПисьма.ДобавитьДочерний(ЭлементГоризонтальныйРазделитель(ЭлементТелоПисьма));
	
	ЭлементШрифт = ДобавитьЭлементСАтрибутами(ЭлементТелоПисьма,
	                                          "Font",
	                                          Новый Структура("size,face","2", "Tahoma"));
	
	СтрокаКоличествоВложений = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Вложений: %1.'"), Вложения.Количество());
	ДобавитьТекстовыйУзел(ЭлементШрифт, СтрокаКоличествоВложений, Истина, Истина);
	
	Для Каждого Вложение Из Вложения Цикл 
		
		ПредставлениеВложения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 (%2).'"), Вложение.ИмяФайла, Вложение.РазмерПредставление);
		ДобавитьТекстовыйУзел(ЭлементШрифт, ПредставлениеВложения, , Истина);
		
	КонецЦикла;
	
	ЭлементТелоПисьма.ДобавитьДочерний(ЭлементШрифт);
	
КонецПроцедуры

Функция ЭлементГоризонтальныйРазделитель(ЭлементРодитель)
	
	СтруктураАтрибутов = Новый Структура;
	СтруктураАтрибутов.Вставить("size", "2");
	СтруктураАтрибутов.Вставить("width", "100%");
	СтруктураАтрибутов.Вставить("align", "center");
	СтруктураАтрибутов.Вставить("tabindex", "-1");
	
	Возврат  ДобавитьЭлементСАтрибутами(ЭлементРодитель, "hr", СтруктураАтрибутов);
	
КонецФункции

Функция ЭлементТелоПисьма(ДокументHTML)
	
	Если ДокументHTML.Тело = Неопределено Тогда
		ЭлементТелоПисьма = ДокументHTML.СоздатьЭлемент("body");
		ДокументHTML.Тело = ЭлементТелоПисьма;
	Иначе
		ЭлементТелоПисьма = ДокументHTML.Тело;
	КонецЕсли;
	
	Возврат ЭлементТелоПисьма;
	
КонецФункции

Функция ЭлементШрифт(ДокументHTML, Размер, ИмяШрифта)
	
	ЭлементШрифт = ДокументHTML.СоздатьЭлемент("Font");
	УстановитьАтрибутЭлементаHTML(ЭлементШрифт,"size", Размер);
	УстановитьАтрибутЭлементаHTML(ЭлементШрифт,"face", ИмяШрифта);
	
	Возврат ЭлементШрифт;
	
КонецФункции

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

#Область РаботаСНастройками

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

Процедура СохранитьНастройкуТекущегоПользователя(КлючОбъекта, Значение, КлючНастроек = Неопределено)
	
	ОбщегоНазначения.ХранилищеОбщихНастроекСохранить(
		КлючОбъекта,
		КлючНастроек,
		Значение);
		
КонецПроцедуры

Функция НастройкиРаботыСПочтой() Экспорт
	
	Настройка = ПолучитьНастройкуТекущегоПользователя("РаботаСПочтой", "НастройкиПользователя", Новый Структура);
	Если ТипЗнч(Настройка) <> Тип("Структура") Тогда
		Настройка = Новый Структура;
	КонецЕсли;
	Возврат Настройка;
	
КонецФункции

Процедура СохранитьНастройкиРаботыСПочтой(Значение) Экспорт
	
	СохранитьНастройкуТекущегоПользователя("РаботаСПочтой", Значение, "НастройкиПользователя");
	
КонецПроцедуры 

////////////////////////////////////////////////////////////////////
// Сообщения SMS

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

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

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

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

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

	Возврат РезультатОтправки.ОтправленныеСообщения.Количество();
	
КонецФункции

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

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

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

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

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

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

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

////////////////////////////////////////////////////////////////////
// Работа с папками электронных писем.

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

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

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

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

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

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

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

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

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

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

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

				Если Не РезультатПисьма.Пустой() Тогда
					ВыборкаПисьма = РезультатПисьма.Выбрать();
					Пока ВыборкаПисьма.Следующий() Цикл
						
						НоваяСтрокаТаблицы = ТаблицаСоответствий.Добавить();
						НоваяСтрокаТаблицы.Папка = Выборка.ПомещатьВПапку;
						НоваяСтрокаТаблицы.Письмо = ВыборкаПисьма.Ссылка;
						
						ИндексЭлементаМассиваКУдалению = Письма.Найти(ВыборкаПисьма.Ссылка);
						Если ИндексЭлементаМассиваКУдалению <> Неопределено Тогда
							Письма.Удалить(ИндексЭлементаМассиваКУдалению);
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
				
				Если Письма.Количество() = 0 Тогда
					Возврат ТаблицаСоответствий;
				КонецЕсли;

			КонецЦикла;
			
		КонецЦикла;
	КонецЕсли;
	
	Если Письма.Количество() > 0 Тогда
		ОпределитьПапкиДляПисемПоУмолчанию(Письма, ТаблицаСоответствий);
	КонецЕсли;
	
	Возврат ТаблицаСоответствий;
	
КонецФункции

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

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

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

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

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

#Область РасчетСостояний

// Рассчитывает состояния предметов взаимодействий.
//
// Параметры:
//  ТаблицаПапок  - ТаблицаЗначений
//                - Неопределено - таблица папок, которые необходимо рассчитать.
//             Если Неопределено, то рассчитываются состояния всех папок.
//
Процедура РассчитатьРассмотреноПоПапкам(ТаблицаПапок) Экспорт

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

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

// Рассчитывает состояния контактов взаимодействий.
//
// Параметры:
//  ТаблицаПредметов  - ТаблицаЗначений
//                    - Неопределено - таблица контактов, которые необходимо рассчитать.
//                      Если Неопределено, то рассчитываются состояния всех контактов.
//
Процедура РассчитатьРассмотреноПоКонтактам(ДанныеДляРасчета) Экспорт

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

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

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

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

// Рассчитывает состояния предметов взаимодействий.
//
// Параметры:
//  ТаблицаПредметов  - ТаблицаЗначений
//                    - Неопределено - таблица предметов, которые необходимо рассчитать.
//                      Если Неопределено, то рассчитываются состояния всех предметов.
//
Процедура РассчитатьРассмотреноПоПредметам(ДанныеДляРасчета) Экспорт

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

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

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

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

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

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

	Возврат ДополнительныеСвойства.Свойство("РассчитыватьРассмотрено", РассчитыватьРассмотрено)
		И РассчитыватьРассмотрено;

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

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

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

// Параметры:
//  МассивВзаимодействий  - Массив - массив, для которого устанавливается признак.
//  ЗначениеПризнака      - Булево - значение признака Рассмотрено.
//  ЕстьИзменения         - Булево - признак того, что хотя бы у одного взаимодействия было изменено значение
//                                   Рассмотрено.
//
Процедура УстановитьПризнакРассмотрено(МассивВзаимодействий, ЗначениеПризнака, ЕстьИзменения) Экспорт

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

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

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

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

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

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

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

#Область Прочее

// Параметры:
//  ПолеВводаФормы  - ПолеФормы - элемент формы, к которому относится список выбора.
//  Интервал        - Число - интервал в секундах, с которым необходимо заполнить список, по умолчанию час.
//
Процедура ЗаполнитьСписокВыбораВремени(ПолеВводаФормы, Интервал = 3600) Экспорт

	НачалоРабочегоДня      = '00010101000000';
	ОкончаниеРабочегоДня   = '00010101235959';

	СписокВремен = ПолеВводаФормы.СписокВыбора;
	СписокВремен.Очистить();

	ВремяСписка = НачалоРабочегоДня;
	Пока НачалоЧаса(ВремяСписка) <= НачалоЧаса(ОкончаниеРабочегоДня) Цикл
		Если НЕ ЗначениеЗаполнено(ВремяСписка) Тогда
			ПредставлениеВремени = "00:00";
		Иначе
			ПредставлениеВремени = Формат(ВремяСписка, НСтр("ru = 'ДФ=ЧЧ:мм'"));
		КонецЕсли;

		СписокВремен.Добавить(ВремяСписка, ПредставлениеВремени);

		ВремяСписка = ВремяСписка + Интервал;
	КонецЦикла;

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

// Формирует текст запроса динамического списка взаимодействий в зависимости от вида панели навигации
// и типа переданного параметра.
//
// Параметры:
//  ЗначениеОтбора  - СправочникСсылка
//                  - ДокументСсылка - значение отбора панели навигации.
//
// Возвращаемое значение:
//   Строка   - текст запроса динамического списка.
//
Функция ТекстЗапросаСпискаВзаимодействий(ЗначениеОтбора = Неопределено) Экспорт
	
	ТекстЗапроса ="
	|ВЫБРАТЬ
	|	ВЫБОР
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.Встреча
	|			ТОГДА ВЫБОР
	|					КОГДА ЖурналДокументовВзаимодействия.ПометкаУдаления
	|						ТОГДА 10
	|					ИНАЧЕ 0
	|				КОНЕЦ
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.ЗапланированноеВзаимодействие
	|			ТОГДА ВЫБОР
	|					КОГДА ЖурналДокументовВзаимодействия.ПометкаУдаления
	|						ТОГДА 11
	|					ИНАЧЕ 1
	|				КОНЕЦ
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.ТелефонныйЗвонок
	|			ТОГДА ВЫБОР
	|					КОГДА ЖурналДокументовВзаимодействия.ПометкаУдаления
	|						ТОГДА 12
	|					ИНАЧЕ 2
	|				КОНЕЦ
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.ЭлектронноеПисьмоВходящее
	|			ТОГДА ВЫБОР
	|					КОГДА ЖурналДокументовВзаимодействия.ПометкаУдаления
	|						ТОГДА 13
	|					ИНАЧЕ 3
	|				КОНЕЦ
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.ЭлектронноеПисьмоИсходящее
	|			ТОГДА ВЫБОР
	|					КОГДА ЖурналДокументовВзаимодействия.ПометкаУдаления
	|						ТОГДА 14
	|					ИНАЧЕ ВЫБОР
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СтатусыИсходящегоЭлектронногоПисьма.Черновик)
	|								ТОГДА 15
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СтатусыИсходящегоЭлектронногоПисьма.Исходящее)
	|								ТОГДА 16
	|							ИНАЧЕ 4
	|						КОНЕЦ
	|				КОНЕЦ
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.СообщениеSMS
	|			ТОГДА ВЫБОР
	|					КОГДА ЖурналДокументовВзаимодействия.ПометкаУдаления
	|						ТОГДА 22
	|					ИНАЧЕ ВЫБОР
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СостоянияДокументаСообщениеSMS.Черновик)
	|								ТОГДА 17
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СостоянияДокументаСообщениеSMS.Исходящее)
	|								ТОГДА 18
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СостоянияДокументаСообщениеSMS.Доставляется)
	|								ТОГДА 19
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СостоянияДокументаСообщениеSMS.ЧастичноДоставлено)
	|								ТОГДА 21
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СостоянияДокументаСообщениеSMS.НеДоставлено)
	|								ТОГДА 23
	|							КОГДА ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма = ЗНАЧЕНИЕ(Перечисление.СостоянияДокументаСообщениеSMS.Доставлено)
	|								ТОГДА 24
	|							ИНАЧЕ 17
	|						КОНЕЦ
	|				КОНЕЦ
	|	КОНЕЦ КАК НомерКартинки,
	|	ЖурналДокументовВзаимодействия.Ссылка,
	|	ЖурналДокументовВзаимодействия.Дата,
	|	ЖурналДокументовВзаимодействия.ПометкаУдаления КАК ПометкаУдаления,
	|	ЖурналДокументовВзаимодействия.Номер,
	|	ЖурналДокументовВзаимодействия.Проведен,
	|	ЖурналДокументовВзаимодействия.Автор,
	|	ЖурналДокументовВзаимодействия.ВзаимодействиеОснование,
	|	ЖурналДокументовВзаимодействия.Входящий,
	|	ЖурналДокументовВзаимодействия.Тема,
	|	ЖурналДокументовВзаимодействия.Ответственный КАК Ответственный,
	|	ЕСТЬNULL(ПредметыВзаимодействий.Рассмотрено, ЛОЖЬ) КАК Рассмотрено,
	|	ЕСТЬNULL(ПредметыВзаимодействий.РассмотретьПосле, ДАТАВРЕМЯ(1, 1, 1)) КАК РассмотретьПосле,
	|	ЖурналДокументовВзаимодействия.Участники,
	|	ЖурналДокументовВзаимодействия.Тип,
	|	ЖурналДокументовВзаимодействия.УчетнаяЗапись,
	|	ВЫБОР
	|		КОГДА ЕСТЬNULL(ЖурналДокументовВзаимодействия.ЕстьВложения, НаличиеФайлов.ЕстьФайлы) ЕСТЬ NULL
	|			ТОГДА ЛОЖЬ
	|		КОГДА ЕСТЬNULL(ЖурналДокументовВзаимодействия.ЕстьВложения, НаличиеФайлов.ЕстьФайлы)
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК ЕстьВложения,
	|	ЖурналДокументовВзаимодействия.Важность,
	|	ВЫБОР
	|		КОГДА ЖурналДокументовВзаимодействия.Важность = ЗНАЧЕНИЕ(Перечисление.ВариантыВажностиВзаимодействия.Высокая)
	|			ТОГДА 2
	|		КОГДА ЖурналДокументовВзаимодействия.Важность = ЗНАЧЕНИЕ(Перечисление.ВариантыВажностиВзаимодействия.Низкая)
	|			ТОГДА 0
	|		ИНАЧЕ 1
	|	КОНЕЦ КАК ВажностьНомерКартинки,
	|	&РеквизитПредмет КАК Предмет,
	|	ТИПЗНАЧЕНИЯ(ПредметыВзаимодействий.Предмет) КАК ТипПредмета,
	|	ЕСТЬNULL(ПредметыВзаимодействий.ПапкаЭлектронногоПисьма, ЗНАЧЕНИЕ(Справочник.ПапкиЭлектронныхПисем.ПустаяСсылка)) КАК Папка,
	|	ВЫБОР
	|		КОГДА ЖурналДокументовВзаимодействия.Ссылка ССЫЛКА Документ.ЭлектронноеПисьмоВходящее
	|			ТОГДА ЖурналДокументовВзаимодействия.Дата
	|		ИНАЧЕ ЖурналДокументовВзаимодействия.ПолученоОтправлено
	|	КОНЕЦ КАК ПолученоОтправлено,
	|	ЖурналДокументовВзаимодействия.Размер,
	|	ЖурналДокументовВзаимодействия.СтатусИсходящегоПисьма
	|ИЗ
	|	ЖурналДокументов.Взаимодействия КАК ЖурналДокументовВзаимодействия
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПредметыПапкиВзаимодействий КАК ПредметыВзаимодействий
	|		ПО ЖурналДокументовВзаимодействия.Ссылка = ПредметыВзаимодействий.Взаимодействие
	|		И &ТекстСоединенияТаблицаКонтактов
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НаличиеФайлов КАК НаличиеФайлов
	|		ПО ЖурналДокументовВзаимодействия.Ссылка = НаличиеФайлов.ОбъектСФайлами
	|{ГДЕ
	|	ЖурналДокументовВзаимодействия.Ссылка КАК Поиск
	|	,&ОтборКонтакт}";
	
	Если ЗначениеОтбора = Неопределено Тогда
		ТекстПредмет                    = "ЕСТЬNULL(ПредметыВзаимодействий.Предмет, НЕОПРЕДЕЛЕНО)";
		ТекстОтборКонтакт               = "";
		ТекстСоединениеТаблицаКонтактов = "";
	ИначеЕсли ВзаимодействияКлиентСервер.ЯвляетсяПредметом(ЗначениеОтбора) ИЛИ ВзаимодействияКлиентСервер.ЯвляетсяВзаимодействием(ЗначениеОтбора) Тогда
		ТекстПредмет                    = "ЕСТЬNULL(ВЫРАЗИТЬ(ПредметыВзаимодействий.Предмет КАК " + ЗначениеОтбора.Метаданные().ПолноеИмя() + "), НЕОПРЕДЕЛЕНО)";
		ТекстОтборКонтакт               = "";
		ТекстСоединениеТаблицаКонтактов = "";
	Иначе
		ТекстПредмет                    = "ЕСТЬNULL(ПредметыВзаимодействий.Предмет, НЕОПРЕДЕЛЕНО)";
		ТекстОтборКонтакт               = ",
		                                   |КонтактыВзаимодействий.Контакт";
		ТекстСоединениеТаблицаКонтактов = "{ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КонтактыВзаимодействий КАК КонтактыВзаимодействий
		                                   |ПО ЖурналДокументовВзаимодействия.Ссылка = КонтактыВзаимодействий.Взаимодействие}";
	КонецЕсли;
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&РеквизитПредмет", ТекстПредмет);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ",&ОтборКонтакт", ТекстОтборКонтакт);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "И &ТекстСоединенияТаблицаКонтактов", ТекстСоединениеТаблицаКонтактов);

	Возврат ТекстЗапроса; 

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

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

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

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

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

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

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

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

// Управляет отображением пометок в подменю быстрого отбора.
// 
// Параметры:
//  Форма - ФормаКлиентскогоПриложения - форма, для которой устанавливаются пометки в подменю.
//
Процедура ОбработатьПодменюОтборПоТипуВзаимодействий(Форма) Экспорт

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

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

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

Функция СписокДоступныхТиповПредметов() Экспорт
	
	СписокВыбораТипаПредмета = Новый СписокЗначений;

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

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

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

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

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

// Параметры:
//  ИмяСправочника    - Строка - имя справочника, для которого осуществляется проверка.
//  ИмяТабличнойЧасти - Строка - имя табличной части, наличие которой проверяется.
//
// Возвращаемое значение:
//  Булево - Истина, если табличная часть есть.
//
// Пример:
//  Если Не НаличиеТабличнойЧастиУСправочника(ИмяСправочника,"КонтактнаяИнформация") Тогда
//  	Возврат;
//  КонецЕсли;
//
Функция НаличиеТабличнойЧастиУСправочника(ИмяСправочника, ИмяТабличнойЧасти)
	
	Возврат (Метаданные.Справочники[ИмяСправочника].ТабличныеЧасти.Найти(ИмяТабличнойЧасти) <> Неопределено);
	
КонецФункции 

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

#Область ШаблоныСообщений

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

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

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

#Область ОпределениеТипаСсылки

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

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

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

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

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

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

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

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

Функция СписокСтатусов() Экспорт
	
	СписокСтатусов = Новый СписокЗначений;
	СписокСтатусов.Добавить("Все", НСтр("ru = 'Все'"));
	СписокСтатусов.Добавить("КРассмотрению", НСтр("ru = 'К рассмотрению'"));
	СписокСтатусов.Добавить("Отложенные", НСтр("ru = 'Отложенные'"));
	СписокСтатусов.Добавить("Рассмотренные", НСтр("ru = 'Рассмотренные'"));
	
	Возврат СписокСтатусов;
	
КонецФункции

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

Функция КартинкаСтраницыПодписи(ПоказыватьКартинку) Экспорт

	Возврат ?(ПоказыватьКартинку, БиблиотекаКартинок.КоличествоРассмотрено, Новый Картинка);

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

Функция ПредставлениеПисьма(ТемаПисьма, ДатаПисьма) Экспорт
	
	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 от %2'"), 
		ВзаимодействияКлиентСервер.ТемаВзаимодействия(ТемаПисьма), Формат(ДатаПисьма, "ДЛФ=D"));
	
КонецФункции

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

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

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

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

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

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

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

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

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

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

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

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

#Область РаботаСЭлементамиИРеквизитамиФормВзаимодействий

// Параметры:
//  Форма - ФормаКлиентскогоПриложения - форма, для которой устанавливается условное оформление.
//
Процедура УстановитьУсловноеОформлениеВзаимодействия(Форма) Экспорт

	Элемент = Форма.УсловноеОформление.Элементы.Добавить();

	ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
	ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных("ПредставлениеКонтакта");

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

	Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ЦветФонаВыделенияПоля);

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

// Параметры:
//  СписокВыбора - СписокЗначений - список, который будет заполнен значения выбора.
//
Процедура ЗаполнитьСписокВыбораДляРассмотретьПосле(СписокВыбора) Экспорт
	
	СписокВыбора.Очистить();
	СписокВыбора.Добавить(15*60,    НСтр("ru = 'Через 15 мин.'"));
	СписокВыбора.Добавить(30*60,    НСтр("ru = 'Через 30 мин.'"));
	СписокВыбора.Добавить(60*60,    НСтр("ru = 'Через 1 час'"));
	СписокВыбора.Добавить(3*60*60,  НСтр("ru = 'Через 3 часа'"));
	СписокВыбора.Добавить(24*60*60, НСтр("ru = 'Завтра'"));
	
КонецПроцедуры

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

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

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

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

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

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

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

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

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

Функция ОбъединитьПисьма(ПервоеПисьмоДокументHTML, ВтороеПисьмоДокументHTML, ШапкаВторогоПисьма) Экспорт
	
	ТелоВторогоПисьма = ВтороеПисьмоДокументHTML.Тело;
	УзлыHTMLВторогоПисьма = ДочерниеУзлыСодержащиеHTML(ТелоВторогоПисьма);
	
	ЭлементDIV = ДобавитьЭлементСАтрибутами(ТелоВторогоПисьма, "div", 
		Новый Структура("style", "border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt"));
	
	Для каждого ДочернийУзел Из УзлыHTMLВторогоПисьма Цикл
		ЭлементDIV.ДобавитьДочерний(ДочернийУзел);
	КонецЦикла;
	
	АтрибутыРазделителя = Новый Структура;
	АтрибутыРазделителя.Вставить("size", "2");
	АтрибутыРазделителя.Вставить("width", "100%");
	АтрибутыРазделителя.Вставить("align", "center");
	АтрибутыРазделителя.Вставить("tabindex", "-1");
	
	ЭлементРазделитель = ДобавитьЭлементСАтрибутами(ЭлементDIV, "hr", АтрибутыРазделителя);
	ВставитьЭлементHTMLПервымДочернимЭлементом(ЭлементDIV, ЭлементРазделитель, УзлыHTMLВторогоПисьма);
	
	ШапкаПисьма = СформироватьЭлементДанныхШапкиПисьма(ЭлементDIV, ШапкаВторогоПисьма, 
		ШапкаВторогоПисьма.ИмяОбъектаМетаданных = "ЭлектронноеПисьмоИсходящее");
	ВставитьЭлементHTMLПервымДочернимЭлементом(ЭлементDIV, ШапкаПисьма, УзлыHTMLВторогоПисьма);
	
	УзлыТелаПисьма = ДочерниеУзлыСодержащиеHTML(ПервоеПисьмоДокументHTML.Тело);
	Для Каждого ДочернийУзел Из УзлыТелаПисьма Цикл
		ТелоВторогоПисьма.ВставитьПеред(ВтороеПисьмоДокументHTML.ИмпортироватьУзел(ДочернийУзел, Истина), ЭлементDIV);
	КонецЦикла;
	
	СтилиCSS = ПервоеПисьмоДокументHTML.ПолучитьЭлементыПоИмени("style");
	Для каждого СтильCSS Из СтилиCSS Цикл
		ЭлементыЗаголовка = ВтороеПисьмоДокументHTML.ПолучитьЭлементыПоИмени("head");
		Если ЭлементыЗаголовка.Количество() = 0 Тогда
			ЭлементЗаголовка = ВтороеПисьмоДокументHTML.СоздатьЭлемент("head");
			ВтороеПисьмоДокументHTML.ПолучитьЭлементыПоИмени("html")[0].ВставитьПеред(ЭлементЗаголовка, ТелоВторогоПисьма);
		Иначе
			ЭлементЗаголовка = ЭлементыЗаголовка[0];
		КонецЕсли;	
		ЭлементЗаголовка.ДобавитьДочерний(ВтороеПисьмоДокументHTML.ИмпортироватьУзел(СтильCSS, Истина));
	КонецЦикла;	
	
	Возврат ВтороеПисьмоДокументHTML;
	
КонецФункции

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

#Область РаботаСОбъектомДокументHTML

// Получает массив дочерних узлов элемента HTML, содержащих HTML.
//
// Параметры:
//  Элемент  - ЭлементHTML
//
// Возвращаемое значение:
//   Массив
//
Функция ДочерниеУзлыСодержащиеHTML(Элемент)

	Результат = Новый Массив;
	Для каждого ДочернийУзел Из Элемент.ДочерниеУзлы Цикл
		Если ТипЗнч(ДочернийУзел) = Тип("ЭлементБлокHTML")
			ИЛИ ТипЗнч(ДочернийУзел) = Тип("ЭлементHTML")
			ИЛИ ТипЗнч(ДочернийУзел) = Тип("ТекстDOM")
			ИЛИ ТипЗнч(ДочернийУзел) = Тип("КомментарийDOM")
			ИЛИ ТипЗнч(ДочернийУзел) = Тип("ЭлементТаблицаHTML")
			ИЛИ ТипЗнч(ДочернийУзел) = Тип("ЭлементФорматированногоТекстаHTML") Тогда
			
			Результат.Добавить(ДочернийУзел);
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;

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

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

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