Загрузка данных
// Возвращает сообщения обращения с картинками в виде строк Base64 и файлами каждого сообщения.
//
// Параметры:
// ЗапросПарам - HTTPСервисЗапрос - запрос с параметром id.
//
// Возвращаемое значение:
// HTTPСервисОтвет - результат в существующем формате метода GetComment.
//
Функция GetComment(ЗапросПарам) Экспорт
Попытка
Ответ = Новый HTTPСервисОтвет(200);
ID = ЗапросПарам.ПараметрыЗапроса.Получить("id");
Если ID = Неопределено Тогда
Ошибка404(Ответ, "Параметр ID не заполнен");
ЗаписатьЛоги(404, "Параметр ID не заполнен", "getComment");
Возврат Ответ;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИТ_ОбщениеПоДокументам.Обращение.Номер КАК incidentId,
| ИТ_ОбщениеПоДокументам.Комментарий КАК text,
| ИТ_ОбщениеПоДокументам.Дата КАК date,
| ИТ_ОбщениеПоДокументам.ВходящееПисьмо.СтруктураКартинок КАК attachments,
| ПРЕДСТАВЛЕНИЕССЫЛКИ(ИТ_ОбщениеПоДокументам.Установил) КАК author,
| ИТ_ОбщениеПоДокументам.ФорматированныйКомментарий КАК ФорматированныйКомментарий,
| ВЫРАЗИТЬ(ИТ_ОбщениеПоДокументам.UUID КАК СТРОКА(36)) КАК UUIDКомментария,
| ЕСТЬNULL(
| ИТ_ОбщениеПоДокументам.ВходящееПисьмо,
| ЗНАЧЕНИЕ(Документ.ЭлектронноеПисьмоВходящее.ПустаяСсылка)) КАК ВходящееПисьмоСообщения
|ИЗ
| РегистрСведений.ИТ_ОбщениеПоДокументам КАК ИТ_ОбщениеПоДокументам
|ГДЕ
| ИТ_ОбщениеПоДокументам.Обращение.Номер = &Номер
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ДокументЭлектронноеПисьмо.ИспользуемыйДокументНомер,
| ДокументЭлектронноеПисьмо.ВходящееПисьмо.Текст,
| ДокументЭлектронноеПисьмо.ВходящееПисьмо.Дата,
| ДокументЭлектронноеПисьмо.ВходящееПисьмо.СтруктураКартинок,
| ПРЕДСТАВЛЕНИЕССЫЛКИ(ДокументЭлектронноеПисьмо.ВходящееПисьмо.ОтправительКонтакт),
| NULL,
| ВЫРАЗИТЬ("""" КАК СТРОКА(36)),
| ДокументЭлектронноеПисьмо.ВходящееПисьмо
|ИЗ
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ДействияВходящихПисемПоОбращениям.ВходящееПисьмо КАК ВходящееПисьмо,
| ДействияВходящихПисемПоОбращениям.ИспользуемыйДокумент.Номер КАК ИспользуемыйДокументНомер
| ИЗ
| РегистрСведений.ДействияВходящихПисемПоОбращениям КАК ДействияВходящихПисемПоОбращениям
| ГДЕ
| ДействияВходящихПисемПоОбращениям.Регистрация
| И ДействияВходящихПисемПоОбращениям.ИспользуемыйДокумент.Номер = &Номер) КАК ДокументЭлектронноеПисьмо
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИТ_СтруктурыДанныхПисемВходящейПочты КАК ИТ_СтруктурыДанныхПисемВходящейПочты
| ПО (ИТ_СтруктурыДанныхПисемВходящейПочты.ВходящееПисьмо = ДокументЭлектронноеПисьмо.ВходящееПисьмо)";
Запрос.УстановитьПараметр("Номер", ID);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Количество() <> 0 Тогда
СтруктураОбщения = Новый Структура;
СтруктураОбщения.Вставить("incidentId", ID);
СтруктураОбщения.Вставить("messages", Новый Массив);
ДанныеФайловСообщений = Новый Массив;
UUIDСообщений = Новый Массив;
ВходящиеПисьмаСообщений = Новый Массив;
Пока Выборка.Следующий() Цикл
Обращение = ПолучитьОбщенияОбращения();
ЗаполнитьЗначенияСвойств(Обращение, Выборка, , "attachments");
ДобавитьКартинкиФорматированногоКомментария(Выборка.ФорматированныйКомментарий, Обращение.attachments);
// Почтовое хранилище остается резервным источником для сообщений без встроенных картинок.
Если Обращение.attachments.Количество() = 0 Тогда
ВложениеВыборки = Выборка.attachments;
Если ТипЗнч(ВложениеВыборки) = Тип("ХранилищеЗначения") Тогда
Вложения = ВложениеВыборки.Получить();
ИначеЕсли ТипЗнч(ВложениеВыборки) = Тип("Массив") Тогда
Вложения = ВложениеВыборки;
Иначе
Вложения = Неопределено;
КонецЕсли;
Если Вложения <> Неопределено Тогда
Для Каждого ВложениеКартинка Из Вложения Цикл
КартинкаСтрока = ПодготовитьТекстПисьмаИСтруктуруКартинок(ВложениеКартинка.Значение);
Если КартинкаСтрока <> "" Тогда
Обращение.attachments.Добавить(КартинкаСтрока);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
СтруктураОбщения.messages.Добавить(Обращение);
ДанныеФайловСообщений.Добавить(Новый Структура(
"UUIDКомментария,ВходящееПисьмо",
Выборка.UUIDКомментария,
Выборка.ВходящееПисьмоСообщения));
Если Не ПустаяСтрока(Выборка.UUIDКомментария)
И UUIDСообщений.Найти(Выборка.UUIDКомментария) = Неопределено Тогда
UUIDСообщений.Добавить(Выборка.UUIDКомментария);
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.ВходящееПисьмоСообщения)
И ВходящиеПисьмаСообщений.Найти(Выборка.ВходящееПисьмоСообщения) = Неопределено Тогда
ВходящиеПисьмаСообщений.Добавить(Выборка.ВходящееПисьмоСообщения);
КонецЕсли;
КонецЦикла;
ФайлыПоUUIDСообщений = ПолучитьФайлыПоUUIDСообщенийОбращения(UUIDСообщений);
ФайлыПоПисьмамСообщений = ПолучитьФайлыПоПисьмамСообщенийОбращения(
ВходящиеПисьмаСообщений);
Для ИндексСообщения = 0 По СтруктураОбщения.messages.ВГраница() Цикл
ДанныеФайлов = ДанныеФайловСообщений[ИндексСообщения];
ФайлыСообщения = Новый Массив;
UUIDДобавленныхФайлов = Новый Соответствие;
ДобавитьФайлыСообщенияОбращения(
ФайлыСообщения,
UUIDДобавленныхФайлов,
ФайлыПоUUIDСообщений.Получить(ДанныеФайлов.UUIDКомментария));
ДобавитьФайлыСообщенияОбращения(
ФайлыСообщения,
UUIDДобавленныхФайлов,
ФайлыПоПисьмамСообщений.Получить(ДанныеФайлов.ВходящееПисьмо));
СтруктураОбщения.messages[ИндексСообщения].Вставить("Files", ФайлыСообщения);
КонецЦикла;
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, СтруктураОбщения);
СтрокаОтвета = Запись.Закрыть();
Ответ.УстановитьТелоИзСтроки(СтрокаОтвета);
ЗаписатьЛоги(200, "Успешный запрос", "getComment");
Иначе
Ошибка404(Ответ, СтрШаблон("Обращение с номером %1 не найдено или не найдены сообщения в обращении", ID));
ЗаписатьЛоги(404, СтрШаблон("Обращение с номером %1", ID), "getComment");
КонецЕсли;
Исключение
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(ПолучитьJSONОшибка(ОписаниеОшибки()));
ЗаписатьЛоги(200, ОписаниеОшибки(), "getComment");
КонецПопытки;
Возврат Ответ;
КонецФункции
// Возвращает файлы, явно связанные с сообщениями по UUID комментария.
Функция ПолучитьФайлыПоUUIDСообщенийОбращения(UUIDСообщений)
ФайлыПоUUIDСообщений = Новый Соответствие;
Если UUIDСообщений.Количество() = 0 Тогда
Возврат ФайлыПоUUIDСообщений;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СвязиФайлов.ИДОбщения КАК UUIDСообщения,
| ПрикрепленныеФайлы.UUID КАК UUID,
| ПрикрепленныеФайлы.Название КАК Название
|ИЗ
| РегистрСведений.ФайлыОбщенияПрикрепленныеВИтилиум КАК СвязиФайлов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ПрикрепленныеФайлы КАК ПрикрепленныеФайлы
| ПО СвязиФайлов.ИДФайлаСтрокой = ПрикрепленныеФайлы.UUID
|ГДЕ
| СвязиФайлов.ИДОбщения В (&UUIDСообщений)";
Запрос.УстановитьПараметр("UUIDСообщений", UUIDСообщений);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаФайлов = РезультатЗапроса.Выбрать();
Пока ВыборкаФайлов.Следующий() Цикл
ОписанияФайлов = ФайлыПоUUIDСообщений.Получить(ВыборкаФайлов.UUIDСообщения);
Если ОписанияФайлов = Неопределено Тогда
ОписанияФайлов = Новый Массив;
ФайлыПоUUIDСообщений.Вставить(ВыборкаФайлов.UUIDСообщения, ОписанияФайлов);
КонецЕсли;
ОписанияФайлов.Добавить(Новый Структура(
"UUID,Name",
ВыборкаФайлов.UUID,
ВыборкаФайлов.Название));
КонецЦикла;
Возврат ФайлыПоUUIDСообщений;
КонецФункции
// Возвращает файлы, явно связанные с входящими письмами сообщений.
Функция ПолучитьФайлыПоПисьмамСообщенийОбращения(ВходящиеПисьма)
ФайлыПоПисьмамСообщений = Новый Соответствие;
Если ВходящиеПисьма.Количество() = 0 Тогда
Возврат ФайлыПоПисьмамСообщений;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПрикрепленныеФайлы.ЭлектронноеПисьмо КАК ВходящееПисьмо,
| ПрикрепленныеФайлы.UUID КАК UUID,
| ПрикрепленныеФайлы.Название КАК Название
|ИЗ
| РегистрСведений.ПрикрепленныеФайлы КАК ПрикрепленныеФайлы
|ГДЕ
| ПрикрепленныеФайлы.ЭлектронноеПисьмо В (&ВходящиеПисьма)";
Запрос.УстановитьПараметр("ВходящиеПисьма", ВходящиеПисьма);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаФайлов = РезультатЗапроса.Выбрать();
Пока ВыборкаФайлов.Следующий() Цикл
ОписанияФайлов = ФайлыПоПисьмамСообщений.Получить(ВыборкаФайлов.ВходящееПисьмо);
Если ОписанияФайлов = Неопределено Тогда
ОписанияФайлов = Новый Массив;
ФайлыПоПисьмамСообщений.Вставить(ВыборкаФайлов.ВходящееПисьмо, ОписанияФайлов);
КонецЕсли;
ОписанияФайлов.Добавить(Новый Структура(
"UUID,Name",
ВыборкаФайлов.UUID,
ВыборкаФайлов.Название));
КонецЦикла;
Возврат ФайлыПоПисьмамСообщений;
КонецФункции
// Добавляет описания файлов в результат без повторов одного UUID.
Процедура ДобавитьФайлыСообщенияОбращения(ФайлыСообщения, UUIDДобавленныхФайлов, ОписанияФайлов)
Если ОписанияФайлов = Неопределено Тогда
Возврат;
КонецЕсли;
Для Каждого ОписаниеФайла Из ОписанияФайлов Цикл
Если UUIDДобавленныхФайлов.Получить(ОписаниеФайла.UUID) = Неопределено Тогда
ФайлыСообщения.Добавить(ОписаниеФайла);
UUIDДобавленныхФайлов.Вставить(ОписаниеФайла.UUID, Истина);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Добавляет встроенные рисунки комментария; обращения к внешним URL не выполняются.
//
// Параметры:
// ХранилищеКомментария - ХранилищеЗначения, Null - сохраненный форматированный комментарий.
// Вложения - Массив из Строка - выходные изображения в Base64.
//
Процедура ДобавитьКартинкиФорматированногоКомментария(ХранилищеКомментария, Вложения)
Если ТипЗнч(ХранилищеКомментария) <> Тип("ХранилищеЗначения") Тогда
Возврат;
КонецЕсли;
ФорматированныйКомментарий = ХранилищеКомментария.Получить();
Если ТипЗнч(ФорматированныйКомментарий) <> Тип("ФорматированныйДокумент") Тогда
Возврат;
КонецЕсли;
Для Каждого ЭлементКомментария Из ФорматированныйКомментарий.ПолучитьЭлементы() Цикл
Если ТипЗнч(ЭлементКомментария) <> Тип("КартинкаФорматированногоДокумента") Тогда
Продолжить;
КонецЕсли;
ЗначениеКартинки = ЭлементКомментария.Картинка;
ДанныеКартинки = Неопределено;
Если ТипЗнч(ЗначениеКартинки) = Тип("Картинка") Тогда
ДанныеКартинки = ЗначениеКартинки.ПолучитьДвоичныеДанные();
ИначеЕсли ТипЗнч(ЗначениеКартинки) = Тип("Строка") Тогда
ПозицияДанных = СтрНайти(НРег(ЗначениеКартинки), ";base64,");
Если НРег(Лев(ЗначениеКартинки, СтрДлина("data:image/"))) = "data:image/" И ПозицияДанных > 0 Тогда
ДанныеBase64 = Сред(ЗначениеКартинки, ПозицияДанных + СтрДлина(";base64,"));
ДанныеBase64 = СтрЗаменить(ДанныеBase64, "_", "/");
ДанныеBase64 = СтрЗаменить(ДанныеBase64, "-", "+");
ДанныеBase64 = СтрЗаменить(ДанныеBase64, " ", "");
// Base64URL может не содержать padding; платформа требует полных блоков по 4 символа.
НедостающиеСимволы = (4 - СтрДлина(ДанныеBase64) % 4) % 4;
ДанныеBase64 = ДанныеBase64 + Лев("===", НедостающиеСимволы);
ДанныеКартинки = Base64Значение(ДанныеBase64);
КонецЕсли;
КонецЕсли;
Если ДанныеКартинки <> Неопределено Тогда
Если ДанныеКартинки.Размер() > 0 Тогда
Вложения.Добавить(Base64Строка(ДанныеКартинки));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры