Как открыть форму справочника у конкретного пользователя при выполнении регламентного задания

Программист 1С v8.3 (Управляемые формы) 1С:Комплексная автоматизация Управленческий учет IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает архитектурная дилемма: серверный процесс (например, регламентное задание) должен инициировать действие на стороне клиента. Типичный пример — интеграция с АТС, когда при поступлении входящего звонка система должна мгновенно открыть карточку контрагента у менеджера, которому адресован вызов. Сложность заключается в том, что сервер не может напрямую «командовать» клиентским приложением. Рассмотрим подробно, как решить эту задачу, используя проверенные методы и современные возможности платформы.

Проблема разделения контекстов: почему сервер не видит клиента

Прежде чем перейти к решениям, проанализируем ситуацию. Регламентное задание выполняется в фоновом сеансе на сервере. У этого сеанса нет графического интерфейса. В то же время менеджер работает в своем клиентском сеансе (тонкий клиент или веб-клиент). Прямого канала связи «Сервер -> Клиент» в классической архитектуре HTTP-запросов не существует. Клиент всегда является инициатором обращения к серверу. Поэтому нам необходимо создать механизм, при котором клиент будет узнавать о событиях на сервере.

Метод 1: Использование обработчика ожидания и регистра сведений

Это классический и наиболее надежный метод, который подходит для любой конфигурации. Суть заключается в использовании «посредника» — регистра сведений, и механизма регулярного опроса этого регистра со стороны клиента.

Шаг 1: Создание структуры данных

Разберем, какой регистр нам понадобится. Создадим непериодический регистр сведений ОчередьСобытийТелефонии со следующими полями:

Шаг 2: Запись события на сервере

В коде регламентного задания, когда определен звонящий и менеджер, выполняем запись в регистр:


МенеджерСсылка = ОпределитьМенеджераПоНомеру(ВходящийНомер);
НоваяЗапись = РегистрыСведений.ОчередьСобытийТелефонии.СоздатьМенеджерЗаписи();
НоваяЗапись.Пользователь = МенеджерСсылка;
НоваяЗапись.ДанныеЗвонка = НайденныйКонтрагент;
НоваяЗапись.ДатаСобытия = ТекущаяДатаСеанса();
НоваяЗапись.Отработано = Ложь;
НоваяЗапись.Записать();

Шаг 3: Настройка клиента (Модуль управляемого приложения)

Теперь нам нужно заставить клиентское приложение периодически проверять наличие новых записей. Разберем код в модуле управляемого приложения:


Процедура ПриНачалеРаботыСистемы()
    // Подключаем проверку каждые 5 секунд
    ПодключитьОбработчикОжидания("ПроверитьВходящиеЗвонки", 5);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьВходящиеЗвонки()
    ДанныеДляОткрытия = ПроверитьНаличиеЗвонкаНаСервере();
    Если ДанныеДляОткрытия <> Неопределено Тогда
        ПараметрыФормы = Новый Структура("Ключ", ДанныеДляОткрытия);
        ОткрытьФорму("Справочник.Контрагенты.ФормаОбъекта", ПараметрыФормы);
    КонецЕсли;
КонецПроцедуры

Шаг 4: Серверная проверка (Общий модуль)

Важно помнить, что запрос должен быть максимально «легким», так как он будет выполняться всеми пользователями каждые 5 секунд. Выясним причину возможного замедления: если пользователей сотни, постоянные запросы к БД создадут нагрузку. Поэтому используем индексированные поля.


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

Метод 2: Система взаимодействия (Collaboration System)

Если ваша платформа версии 8.3.10 и выше, проанализируем более современный подход — Систему взаимодействия. Это встроенный механизм, который позволяет серверу отправлять Push-уведомления клиенту без постоянных опросов базы данных.

Преимущества системы взаимодействия:

  1. Мгновенность: Сообщение доставляется клиенту сразу после отправки сервером.
  2. Производительность: Нет нужды в обработчиках ожидания, которые нагружают сервер запросами каждые несколько секунд.
  3. Нативность: Это штатный механизм платформы для общения между сеансами.

Реализация по шагам:

1. В регламентном задании вместо записи в регистр мы отправляем сообщение конкретному пользователю:


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

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

2. На стороне клиента в модуле управляемого приложения подписываемся на получение сообщения:


&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
    СистемаВзаимодействия.ПодключитьОбработчикПолученияСообщения(
        Новый ОписаниеОповещения("ОбработкаЗвонка", ЭтотОбъект)
    );
КонецПроцедуры

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

Рекомендации по User Experience (UX)

Рассмотрим важный этический момент автоматизации: внезапное открытие окон. Если менеджер в момент звонка заполняет сложный документ или пишет письмо клиенту, внезапно открывшаяся форма справочника может перехватить фокус ввода, что приведет к ошибкам или раздражению сотрудника.

Как сделать лучше:

Итоги

Мы проанализировали два основных пути решения задачи. Для старых систем или систем без настроенного сервера взаимодействия отлично подходит вариант с регистром сведений и обработчиком ожидания. Для современных внедрений на актуальных версиях платформы настоятельно рекомендуем использовать Систему взаимодействия, так как это снижает нагрузку на базу данных и обеспечивает мгновенную реакцию интерфейса на входящие события.

← На главную