При разработке в среде 1С:Предприятие часто возникает задача оперативного уведомления пользователя о каком-либо событии. Это может быть поступление оплаты, изменение статуса заказа или системное оповещение. Начинающие разработчики часто пытаются использовать объект СообщениеПользователю, однако сталкиваются с тем, что сообщение видит только тот, кто инициировал код (например, при записи документа). Это происходит потому, что каждый сеанс пользователя в 1С изолирован, и объект СообщениеПользователю выводит информацию исключительно в текущий контекст исполнения.
Для того чтобы «достучаться» до другого активного сеанса, нам необходимо использовать механизмы межсеансового взаимодействия. В этой статье мы подробно разберем несколько эффективных способов реализации этой задачи: от современных штатных инструментов платформы до классических методов, проверенных временем.
Проанализируем самый современный и рекомендуемый фирмой «1С» способ — Систему взаимодействия. Этот механизм позволяет пользователям обмениваться сообщениями, файлами и совершать звонки непосредственно в интерфейсе программы. Главное преимущество для разработчика заключается в том, что платформа берет на себя всю транспортную часть доставки уведомления.
Рассмотрим, как программно отправить сообщение конкретному пользователю через этот механизм. Для этого нам понадобится создать обсуждение (если оно еще не создано) и добавить в него сообщение. Выясним причину, по которой это удобно: сообщение появится у адресата мгновенно в виде всплывающего окна или индикатора на «колокольчике» в системной панели 1С.
Пример программного кода для отправки уведомления:
// Получаем пользователя-адресата
ПользовательСсылка = Справочники.Пользователи.НайтиПоНаименованию("Белкина Анастасия Георгиевна");
ИдентификаторПользователя = СистемаВзаимодействия.ПолучитьИдентификаторПользователя(ПользовательСсылка.ИдентификаторПользователяИнформационнойБазы);
// Формируем список участников (отправитель и получатель)
Участники = Новый Массив;
Участники.Добавить(ИдентификаторПользователя);
Участники.Добавить(СистемаВзаимодействия.ПолучитьИдентификаторТекущегоПользователя());
// Создаем новое обсуждение или находим существующее
ПараметрыОтбора = Новый ПараметрыОтбораОбсужденийСистемыВзаимодействия;
ПараметрыОтбора.Ключ = "УведомлениеОбОплате_" + ПользовательСсылка.УникальныйИдентификатор();
Обсуждение = СистемаВзаимодействия.СоздатьОбсуждение();
Обсуждение.Ключ = ПараметрыОтбора.Ключ;
Обсуждение.Участники = Участники;
Обсуждение.Записать();
// Отправляем сообщение
НовоеСообщение = СистемаВзаимодействия.СоздатьСообщение(Обсуждение.Идентификатор);
НовоеСообщение.Текст = "Поступила оплата от контрагента " + КонтрагентНаименование;
НовоеСообщение.Записать();
Важный нюанс: Для работы этого метода в информационной базе должна быть настроена и подключена Система взаимодействия (требуется сервер системы взаимодействия, локальный или облачный от 1С).
Если Система взаимодействия не настроена, проанализируем универсальный метод, который работает в любой конфигурации. Суть метода заключается в создании «почтового ящика» в базе данных, куда отправитель кладет сообщение, а получатель периодически проверяет его наличие.
Разберем реализацию по шагам:
ОчередьУведомлений. Добавим измерения Пользователь (тип СправочникСсылка.Пользователи) и ресурсы ТекстСообщения (тип Строка), ДатаСобытия (тип Дата).ПередЗаписью документа) мы записываем данные в этот регистр для нужного пользователя.Посмотрим на пример реализации клиентской части в модуле управляемого приложения:
Процедура ПриНачалеРаботыСистемы()
// Подключаем обработчик ожидания с интервалом 60 секунд
ПодключитьОбработчикОжидания("ПроверитьНовыеУведомления", 60);
КонецПроцедуры
Процедура ПроверитьНовыеУведомления() Экспорт
// Вызываем серверную функцию для проверки регистра
ТекстОповещения = ПроверитьНаличиеСообщенийНаСервере();
Если ЗначениеЗаполнено(ТекстОповещения) Тогда
// Используем встроенное визуальное оповещение платформы
ПоказатьОповещениеПользователя("Внимание!", , ТекстОповещения, БиблиотекаКартинок.ИнформационныйСборка);
КонецЕсли;
КонецПроцедуры
На стороне сервера необходимо предусмотреть механизм, который не только считывает сообщение, но и удаляет его (или помечает как прочитанное), чтобы пользователь не получал одно и то же уведомление каждую минуту. Рассмотрим пример функции:
&НаСервереБезКонтекста
Функция ПроверитьНаличиеСообщенийНаСервере()
ТекущийПользователь = Пользователи.ТекущийПользователь();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ОчередьУведомлений.ТекстСообщения КАК Текст
|ИЗ
| РегистрСведений.ОчередьУведомлений КАК ОчередьУведомлений
|ГДЕ
| ОчередьУведомлений.Пользователь = &Пользователь
|УПОРЯДОЧИТЬ ПО
| ОчередьУведомлений.ДатаСобытия ВОЗР";
Запрос.УстановитьПараметр("Пользователь", ТекущийПользователь);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующая();
Текст = Выборка.Текст;
// Удаляем прочитанное сообщение
МенеджерЗаписи = РегистрыСведений.ОчередьУведомлений.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Пользователь = ТекущийПользователь;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.Удалить();
КонецЕсли;
Возврат Текст;
КонецЕсли;
Возврат "";
КонецФункции
Если ваша конфигурация построена на базе БСП (а это почти все современные типовые решения), рассмотрим готовый механизм «Заметки и напоминания». Нам не нужно изобретать велосипед — достаточно программно создать запись в регистре напоминаний.
Проанализируем ситуацию: нам нужно отправить напоминание пользователю. В БСП для этого используется общий модуль НапоминанияПользователя. Вызов метода создания напоминания выглядит следующим образом:
// Структура параметров для создания напоминания
Напоминание = Новый Структура;
Напоминание.Вставить("Пользователь", НужныйПользователь);
Напоминание.Вставить("ВремяСобытия", ТекущаяДата());
Напоминание.Вставить("Описание", "Срочно проверьте оплату по счету №" + Объект.Номер);
Напоминание.Вставить("СпособУстановкиВремени", Перечисления.СпособыУстановкиВремениНапоминания.ВЗаданноеВремя);
НапоминанияПользователя.СоздатьНапоминание(Напоминание);
Преимущество этого метода в том, что БСП сама управляет формами уведомлений, их откладыванием и повторным показом. Пользователь увидит стандартное окно «Напоминания», которое ему уже знакомо по работе с типовой конфигурацией.
Выясним причину, по которой иногда прибегают к системным методам. Если пользователь свернул 1С или работает в терминальном сеансе, он может не заметить внутренние уведомления программы. В таком случае можно использовать команду операционной системы msg.
Рассмотрим пример кода, который вызывает внешнюю утилиту Windows для вывода сообщения на рабочий стол пользователя:
// Команда: msg [имя_пользователя] /server:[имя_сервера] "Текст сообщения"
ИмяПользователяОС = "Petrov_AA"; // Имя пользователя в системе
ТекстСообщения = "Документ утвержден!";
КомандаСистемы = "msg " + ИмяПользователяОС + " " + ТекстСообщения;
ЗапуститьПриложение(КомандаСистемы, , Истина);
Ограничения метода: Для работы данной команды требуется соответствующая настройка прав доступа в Windows (разрешение на удаленный вызов процедур RPC) и включенная служба терминалов. В современных версиях Windows (10/11) этот функционал по умолчанию может быть ограничен в целях безопасности.
Подводя итог нашему анализу, можно выделить следующие рекомендации по выбору метода:
СообщениеПользователю в надежде, что его увидит кто-то, кроме текущего пользователя. Этот объект предназначен исключительно для обратной связи с активным оператором в рамках его текущего действия.Мы рассмотрели основные способы передачи уведомлений между сеансами. Выбор конкретного решения зависит от ваших технических условий и требований к скорости доставки сообщения.