При разработке бизнес-логики часто возникает задача: выполнить проверку данных по расписанию (например, через 2 часа после загрузки банковской выписки или ежедневно в 12:00) и вывести предупреждение конкретным пользователям. Начинающие разработчики часто пытаются решить эту задачу напрямую через регламентные задания, сталкиваясь с невозможностью интерактивного взаимодействия с клиентом.
Разберем архитектурные ограничения платформы 1С:Предприятие 8.3 и рассмотрим правильные варианты реализации отложенных и периодических оповещений.
Проанализируем контекст выполнения: регламентные и фоновые задания всегда выполняются на стороне сервера в отдельном неинтерактивном сеансе. В этом контексте не существует пользовательского интерфейса: нельзя вызвать метод ПоказатьОповещениеПользователя, открыть форму или показать окно с помощью функции Предупреждение.
Даже в файловой информационной базе регламентное задание запускается в отдельном потоке или фоновом сеансе. Поэтому основное архитектурное правило звучит так: серверные проверки должны быть отделены от клиентского отображения.
Рассмотрим основные способы решения задачи:
Рассмотрим классический и универсальный алгоритм, не зависящий от наличия БСП в конфигурации. Разделим логику на две части: фиксацию необходимости проверки на сервере и периодический опрос на клиенте.
Шаг 1. Создание регистра сведений
Создадим непериодический регистр сведений ОчередьОповещений со следующей структурой:
Пользователь (тип СправочникСсылка.Пользователи).ДатаОповещения (тип Дата), ТекстСообщения (тип Строка), СсылкаНаОбъект (тип ДокументСсылка или Произвольный), Оповещен (тип Булево).При загрузке выписки или выполнении серверного регламентного задания рассчитываем время показа и записываем строку в регистр:
// Серверный код добавления задания в очередь
Запись = РегистрыСведений.ОчередьОповещений.СоздатьМенеджерЗаписи();
Запись.Пользователь = ТекущийПользователь;
Запись.ДатаОповещения = ТекущаяДатаСеанса() + 7200; // Через 2 часа
Запись.ТекстСообщения = "Необходимо выставить ЭСЧФ по загруженным выпискам";
Запись.Оповещен = Ложь;
Запись.Записать();
Шаг 2. Подключение обработчика ожидания на клиенте
Клиентский сеанс должен периодически опрашивать регистр на наличие активных уведомлений для текущего пользователя. Подключение обработчика следует выполнять в МодульУправляемогоПриложения в обработчике события ПриНачалеРаботыСистемы.
Обратите внимание на распространенную ошибку: если передавать имя процедуры строкой, она обязана быть экспортируемой и находиться либо в модуле управляемого приложения, либо в глобальном общем клиентском модуле. В современных версиях платформы рекомендуется использовать объект ОписаниеОповещения.
Разберем пример подключения в модуле управляемого приложения:
Процедура ПриНачалеРаботыСистемы()
// Подключаем опрос каждые 60 секунд
Оповещение = Новый ОписаниеОповещения("ПроверитьНаличиеОповещений", ЭтотОбъект);
ПодключитьОбработчикОжидания(Оповещение, 60);
КонецПроцедуры
Процедура ПроверитьНаличиеОповещений() Экспорт
// Получаем и отображаем уведомления
МассивОповещений = ОповещенияСервер.ПолучитьАктуальныеОповещения();
Для Каждого Стр Из МассивОповещений Цикл
ПоказатьОповещениеПользователя(
"Внимание!",
Стр.СсылкаНаОбъект,
Стр.ТекстСообщения,
БиблиотекаКартинок.Информация
);
КонецЦикла;
КонецПроцедуры
На сервере в модуле ОповещенияСервер получаем записи, у которых ДатаОповещения <= ТекущаяДатаСеанса() и Оповещен = Ложь, после чего устанавливаем признак обработки или удаляем запись из регистра.
Если в конфигурации внедрена Библиотека стандартных подсистем (БСП), то создавать собственный механизм очереди и таймеров не требуется. Для этого используется регистр сведений НапоминанияПользователя.
Регламентное задание или обработка загрузки просто формирует запись в данном регистре с указанием целевого пользователя, времени срабатывания и ссылки на объект. БСП автоматически выведет стандартное окно напоминания в указанное время встроенными клиентскими средствами.
// Пример создания напоминания средствами БСП
Напоминание = РегистрыСведений.НапоминанияПользователя.СоздатьМенеджерЗаписи();
Напоминание.Пользователь = Пользователь;
Напоминание.ВремяСобытия = ТекущаяДатаСеанса() + 7200;
Напоминание.СрокНапоминания = ТекущаяДатаСеанса() + 7200;
Напоминание.Источник = ДокументСсылка;
Напоминание.Описание = "Проверить выставление ЭСЧФ";
Напоминание.Записать();
Если в информационной базе подключена СистемаВзаимодействия, отпадает необходимость периодического опроса базы через обработчики ожидания (Pull-модель). Сервер может отправить оповещение напрямую в сеанс пользователя (Push-модель).
В этом случае регламентное задание на сервере определяет список пользователей и отправляет им системное сообщение через объект СистемаВзаимодействия. Платформа самостоятельно доставит уведомление в сеанс пользователя в режиме реального времени.
При реализации оповещений учитывайте следующие нюансы работы платформы 1С:
РежимОткрытияОконФорм.БлокироватьВесьИнтерфейс, выполнение обработчиков ожидания платформой временно приостанавливается до закрытия окна.ПодключитьОбработчикОжидания (оптимально — от 60 до 300 секунд). Запрос к регистру должен выполняться по индексированным полям (Пользователь, Оповещен), чтобы минимизировать нагрузку на СУБД.