В процессе сопровождения информационных систем на базе 1С 8.2 (особенно в конфигурации "Управление торговлей" 10.3) часто возникает задача оперативного информирования пользователей. Обычное использование функции Сообщить() не подходит, так как оно выводит текст в окно сообщений, которое пользователь может не заметить, а при открытии документа или выполнении регламентного действия требуется привлечь внимание всех или конкретных участников процесса. Разберем наиболее эффективные методы реализации такой системы, избегая "спама" и лишней нагрузки на сервер.
Проанализируем самый надежный и гибкий способ — создание "очереди сообщений" внутри базы данных. Этот метод позволяет не только отправлять текст, но и контролировать факт прочтения сообщения пользователем. Суть заключается в том, что информация записывается в специальную таблицу, а клиентское приложение периодически "опрашивает" эту таблицу на наличие новых записей.
Для начала создадим новый Регистр сведений, назовем его ОчередьСообщений. Нам понадобятся следующие измерения и ресурсы:
Теперь рассмотрим программную часть. Нам необходимо настроить периодическую проверку в глобальном модуле или модуле приложения. Разберем по шагам, как это реализовать через ПодключитьОбработчикОжидания.
В модуле обычного приложения (или в форме, которая всегда открыта) пропишем инициализацию:
Процедура ПриНачалеРаботыСистемы()
// Интервал в секундах, например, каждые 60 секунд
ПодключитьОбработчикОжидания("ПроверитьНовыеСообщения", 60);
КонецПроцедуры
Далее создадим саму процедуру проверки. Важно сделать запрос максимально "легким", чтобы он не блокировал работу пользователя и не создавал нагрузку на SQL-сервер при одновременном обращении 100 человек.
Процедура ПроверитьНовыеСообщения() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ОчередьСообщений.ТекстСообщения,
| ОчередьСообщений.ДатаСообщения
|ИЗ
| РегистрСведений.ОчередьСообщений КАК ОчередьСообщений
|ГДЕ
| ОчередьСообщений.Получатель = &ТекущийПользователь
| И ОчередьСообщений.Прочитано = ЛОЖЬ
|УПОРЯДОЧИТЬ ПО
| ОчередьСообщений.ДатаСообщения";
Запрос.УстановитьПараметр("ТекущийПользователь", ПараметрыСеанса.ТекущийПользователь);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующая();
// Выводим сообщение пользователю
Предупреждение(Выборка.ТекстСообщения, 10, "Важное уведомление!");
// Помечаем сообщение как прочитанное
МенеджерЗаписи = РегистрыСведений.ОчередьСообщений.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Получатель = ПараметрыСеанса.ТекущийПользователь;
МенеджерЗаписи.ДатаСообщения = Выборка.ДатаСообщения;
МенеджерЗаписи.Прочитать();
МенеджерЗаписи.Прочитано = Истина;
МенеджерЗаписи.Записать();
КонецЕсли;
КонецПроцедуры
Важный момент: Мы используем Предупреждение() с таймаутом (10 секунд), чтобы модальное окно не заблокировало работу системы, если пользователь отошел от компьютера.
Как упоминалось в обсуждении на форуме, в типовых решениях (например, ЗУП 2.5 или УПП) уже есть встроенные механизмы задач. Если в вашей конфигурации включено использование бизнес-процессов, логичнее использовать объект Задача.
Выясним причину, почему это лучше: задачи имеют встроенную форму списка, возможность переадресации и жесткую фиксацию выполнения. Чтобы реализовать уведомление при открытии документа программистом, мы можем программно создавать задачу для автора заявки или группы пользователей.
Пример кода для создания задачи при открытии документа:
Процедура ПриОткрытии()
Если ЭтоНовый() Тогда
Возврат;
КонецЕсли;
// Допустим, мы хотим уведомить автора, что его документ открыт специалистом
НоваяЗадача = Задачи.ЗадачиПользователей.СоздатьЗадачу();
НоваяЗадача.Наименование = "Ваш документ " + Строка(Ссылка) + " взят в работу";
НоваяЗадача.Исполнитель = ЭтотОбъект.Автор; // Указываем получателя
НоваяЗадача.Дата = ТекущаяДата();
НоваяЗадача.Записать();
КонецПроцедуры
Для того чтобы пользователь увидел задачу мгновенно, в конфигурации должна быть открыта форма "Список задач" с включенным обновлением, либо использован тот же обработчик ожидания, который проверяет наличие невыполненных задач.
Если требуется вывести сообщение поверх всех окон, даже если 1С свернута, можно воспользоваться возможностями операционной системы. Рассмотрим пример работы с объектом WScript.Shell. Это позволит вывести всплывающее окно средствами Windows.
Процедура ОповеститьЧерезWindows(ТекстСообщения)
Попытка
WshShell = Новый COMОбъект("WScript.Shell");
// Параметры Popup: Текст, ВремяОтображения(сек), Заголовок, ТипИконки
WshShell.Popup(ТекстСообщения, 5, "Сообщение от 1С", 64);
Исключение
// Если COM-объект недоступен, откатываемся к стандартному методу
Сообщить(ТекстСообщения);
КонецПопытки;
КонецПроцедуры
Преимущество этого метода в том, что он не создает модальности внутри 1С, которая могла бы прервать выполнение фоновых алгоритмов или расчетов.
Рассмотрим ситуацию, когда в базе одновременно работают более 100 пользователей. Постоянные запросы к базе данных могут снизить производительность. Чтобы этого избежать, проанализируем следующие советы:
Получатель и Прочитано в регистре сведений являются индексируемыми. Это позволит SQL-серверу мгновенно находить нужные записи.УровеньВажности и выводите окна только для "Критичных" событий.Выясним, какой метод выбрать. Если вам нужна простота и надежность в УТ 10.3 — выбирайте Метод 1 (Регистр сведений + Обработчик ожидания). Если ваша конфигурация уже активно использует задачи — интегрируйтесь в **Метод 2**. Для экстренных уведомлений, которые нельзя пропустить, используйте **Метод 3**.
Разберем типичную ошибку: попытку вызвать Предупреждение() прямо в коде модуля документа без проверки контекста. Помните, что в 1С 8.2 на обычных формах программное открытие формы или вывод окна из серверного контекста может привести к ошибке. Всегда проверяйте наличие доступного клиентского интерфейса.