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


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

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

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

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

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

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

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

// Устарела. Следует использовать ОжидатьЗавершение с параметром ПараметрыОжидания.ВыводитьОкноОжидания = Истина.
// Заполняет структуру параметров значениями по умолчанию.
// 
// Параметры:
//  ПараметрыОбработчикаОжидания - Структура - заполняется значениями по умолчанию. 
//
// 
Процедура ИнициализироватьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания) Экспорт
	
	ПараметрыОбработчикаОжидания = Новый Структура;
	ПараметрыОбработчикаОжидания.Вставить("МинимальныйИнтервал", 1);
	ПараметрыОбработчикаОжидания.Вставить("МаксимальныйИнтервал", 15);
	ПараметрыОбработчикаОжидания.Вставить("ТекущийИнтервал", 1);
	ПараметрыОбработчикаОжидания.Вставить("КоэффициентУвеличенияИнтервала", 1.4);
	
КонецПроцедуры

// Устарела. Следует использовать ОжидатьЗавершение с параметром ПараметрыОжидания.ВыводитьОкноОжидания = Истина.
// Заполняет структуру параметров новыми расчетными значениями.
// 
// Параметры:
//  ПараметрыОбработчикаОжидания - Структура - заполняется расчетными значениями. 
//
// 
Процедура ОбновитьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания) Экспорт
	
	ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.ТекущийИнтервал * ПараметрыОбработчикаОжидания.КоэффициентУвеличенияИнтервала;
	Если ПараметрыОбработчикаОжидания.ТекущийИнтервал > ПараметрыОбработчикаОжидания.МаксимальныйИнтервал Тогда
		ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.МаксимальныйИнтервал;
	КонецЕсли;
		
КонецПроцедуры

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

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

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

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

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

////////////////////////////////////////////////////////////////////////////////
// Обработчики событий подсистем конфигурации.

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

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

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

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

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

Функция ДлительнаяОперацияОтменена(ДлительнаяОперация)
	
	Возврат ДлительнаяОперация.ОтменятьПриЗакрытииФормыВладельца
	    И ДлительнаяОперация.ФормаВладелец <> Неопределено
		И Не ДлительнаяОперация.ФормаВладелец.Открыта();
	
КонецФункции

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

Процедура УточнитьИнтервалОбработчикаОжидания(Интервал, АктивныеДлительныеОперации, ОбсужденияАктивны)
	
	ТекущаяДата = ТекущаяДата(); // АПК:143 Дата сеанса не используется для проверки интервалов времени
	НовыйИнтервал = 120;
	
	ИнтервалКонтроляОбсуждений = ИнтервалКонтроляОбсуждений();
	Если ОбсужденияАктивны И НовыйИнтервал < ИнтервалКонтроляОбсуждений Тогда
		НовыйИнтервал = ИнтервалКонтроляОбсуждений;
	КонецЕсли;
	
	Для Каждого Операция Из АктивныеДлительныеОперации Цикл
		Если Не ОбсужденияАктивны Или Операция.Значение.ПолученоОповещениеОЗавершении Тогда
			НовыйИнтервал = Макс(Мин(НовыйИнтервал, Операция.Значение.Контроль - ТекущаяДата), 1);
		КонецЕсли;
	КонецЦикла;
	
	Если Интервал > НовыйИнтервал Тогда
		Интервал = НовыйИнтервал;
	КонецЕсли;
	
КонецПроцедуры

// Возвращаемое значение:
//  Число - число секунд контроля длительной операции
//          через общий серверный вызов, когда обсуждения
//          активны, но сообщений не поступило, например,
//          при операции дольше указанного числа секунд
//          или когда произошло аварийное завершение фонового задания и
//          сообщение через систему взаимодействия не было отправлено.
//
Функция ИнтервалКонтроляОбсуждений()
	
	Возврат ?(СерверныеОповещенияКлиент.СостояниеПолучения().УведомленияКлиентаДоступны, 180, 30);
	
КонецФункции

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

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

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

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

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

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

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

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

Процедура ПроверитьПараметрыОжидатьЗавершение(Знач ДлительнаяОперация, Знач ОповещениеОЗавершении, Знач ПараметрыОжидания)
	
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("ДлительныеОперацииКлиент.ОжидатьЗавершение",
		"ДлительнаяОперация", ДлительнаяОперация, Тип("Структура"));
	
	Если ОповещениеОЗавершении <> Неопределено Тогда
		ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("ДлительныеОперацииКлиент.ОжидатьЗавершение",
			"ОповещениеОЗавершении", ОповещениеОЗавершении, Тип("ОписаниеОповещения"));
	КонецЕсли;
	
	Если ПараметрыОжидания <> Неопределено Тогда
		
		ТипыСвойств = Новый Структура;
		Если ПараметрыОжидания.ФормаВладелец <> Неопределено Тогда
			ТипыСвойств.Вставить("ФормаВладелец", Тип("ФормаКлиентскогоПриложения"));
		КонецЕсли;
		ТипыСвойств.Вставить("ТекстСообщения", Тип("Строка"));
		ТипыСвойств.Вставить("Заголовок",      Тип("Строка"));
		ТипыСвойств.Вставить("ВыводитьОкноОжидания", Тип("Булево"));
		ТипыСвойств.Вставить("ВыводитьПрогрессВыполнения", Тип("Булево"));
		ТипыСвойств.Вставить("ВыводитьСообщения", Тип("Булево"));
		ТипыСвойств.Вставить("Интервал", Тип("Число"));
		ТипыСвойств.Вставить("ОповещениеПользователя", Тип("Структура"));
		ТипыСвойств.Вставить("ПолучатьРезультат", Тип("Булево"));
		
		ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("ДлительныеОперацииКлиент.ОжидатьЗавершение",
			"ПараметрыОжидания", ПараметрыОжидания, Тип("Структура"), ТипыСвойств);
			
		СообщениеПроверки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Параметр %1 должен быть больше или равен 1'"), "ПараметрыОжидания.Интервал");
		
		ОбщегоНазначенияКлиентСервер.Проверить(ПараметрыОжидания.Интервал = 0 Или ПараметрыОжидания.Интервал >= 1,
			СообщениеПроверки, "ДлительныеОперацииКлиент.ОжидатьЗавершение");
			
		СообщениеПроверки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Если параметр %1 установлен в %2, то параметр %3 не поддерживается'"),
			"ПараметрыОжидания.ВыводитьОкноОжидания",
			"Истина",
			"ПараметрыОжидания.ОповещениеОПрогрессеВыполнения");
			
		ОбщегоНазначенияКлиентСервер.Проверить(Не (ПараметрыОжидания.ОповещениеОПрогрессеВыполнения <> Неопределено И ПараметрыОжидания.ВыводитьОкноОжидания), 
			СообщениеПроверки, "ДлительныеОперацииКлиент.ОжидатьЗавершение");
			
	КонецЕсли;

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

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

// Для подключения расширением для тестирования.
Процедура ВывестиОповещениеПользователю(Текст, ДействиеПриНажатии, Пояснение,
			Картинка, СтатусОповещения, КлючУникальности, ВладелецФормы)
	
	ПоказатьОповещениеПользователя(Текст, ДействиеПриНажатии, Пояснение,
		Картинка, СтатусОповещения, КлючУникальности);
	
КонецПроцедуры

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