Как правильно вывести предупреждение пользователю при проведении документа в управляемых формах 1С

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

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

Почему возникает ошибка при вызове Предупреждение() на сервере?

Проанализируем ситуацию: процедура ОбработкаПроведения всегда выполняется на стороне сервера внутри транзакции базы данных. Серверный код не имеет доступа к интерфейсу пользователя. Методы Предупреждение() или современный аналог ПоказатьПредупреждение() являются клиентскими. Они требуют физического наличия монитора и пользователя перед ним, чего у сервера нет. Более того, остановка серверного процесса для ожидания реакции пользователя (модальность) недопустима, так как это блокирует ресурсы базы данных для всех остальных участников системы.

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

Способ 1. Использование объекта СообщениеПользователю

Если ваша задача — просто проинформировать пользователя о задолженности, не прерывая процесс проведения, наиболее правильным и «штатным» способом является использование объекта СообщениеПользователю. В отличие от старого метода Сообщить(), этот объект позволяет привязать текст сообщения к конкретному полю на форме.

Разберем пример кода, который можно разместить в модуле объекта:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Выполняем расчет долга
    Долг = РегистрыНакопления.Взаиморасчеты.Остаток(Новый Структура("Контрагент", Контрагент));
    
    Если Долг > 0 Тогда
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Внимание! У контрагента " + Контрагент + " имеется задолженность: " + Долг;
        // Привязываем сообщение к полю Контрагент на форме
        Сообщение.Поле = "Объект.Контрагент";
        Сообщение.УстановитьДанные(ЭтотОбъект);
        Сообщение.Сообщить();
    КонецЕсли;
    
КонецПроцедуры

Важный нюанс: Пользователи часто жалуются, что такие сообщения «незаметны», особенно если после проведения форма закрывается. Если бизнес-требование настаивает именно на всплывающем окне, нам придется использовать более сложную схему.

Способ 2. Передача данных на клиент через ДополнительныеСвойства

Чтобы вывести полноценное окно ПоказатьПредупреждение() после успешного проведения, нам нужно передать информацию о долге из серверной процедуры ОбработкаПроведения обратно на клиентскую форму. Напрямую вернуть значение из ОбработкаПроведения нельзя, поэтому мы используем промежуточное хранилище объекта — структуру ДополнительныеСвойства.

Рассмотрим алгоритм реализации по шагам:

  1. В модуле объекта (сервер): Записываем данные в свойства документа.

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    // ... логика расчета долга ...
    Если Долг > 0 Тогда
        ЭтотОбъект.ДополнительныеСвойства.Вставить("ТекстПредупреждения", "Долг клиента: " + Долг);
    КонецЕсли;
КонецПроцедуры
  1. В модуле формы (серверный обработчик): Перехватываем эти данные при записи.

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

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

Этот метод позволяет соблюсти стандарты разработки и при этом гарантированно привлечь внимание пользователя после того, как транзакция проведения будет успешно завершена.

Способ 3. Использование всплывающих уведомлений (Toast)

Если модальное окно (которое нужно закрывать кликом) кажется слишком навязчивым, можно воспользоваться методом ПоказатьОповещениеПользователя(). Это «всплывашка» в нижнем углу экрана, которая не блокирует работу, но хорошо видна.

Пример вызова из клиентской процедуры ПослеЗаписи:


ПоказатьОповещениеПользователя(
    "Внимание: Долг!", 
    "http://ссылка_на_отчет", 
    "У контрагента накоплен долг: " + СуммаДолга, 
    БиблиотекаКартинок.Важное
);

Проанализируем преимущества: такое оповещение не прерывает работу пользователя, позволяет добавить гиперссылку (например, на отчет по взаиморасчетам) и выглядит современно.

Важные предостережения при работе на сервере

Разберем ситуацию с групповым перепроведением документов. Представьте, что бухгалтер запускает перепроведение 1000 документов за месяц. Если бы система позволила вставить Предупреждение() в модуль объекта, сервер бы «завис» на первом же документе, ожидая, пока кто-то нажмет «ОК» в сессии, которая может быть даже не открыта (например, при выполнении регламентным заданием).

Рекомендации по безопасности кода:

Подводя итог: в управляемом приложении 1С разделение логики на «тихий» сервер и «интерактивный» клиент — это не ограничение, а инструмент создания стабильных и быстрых систем. Используйте ДополнительныеСвойства для передачи сигналов на форму, и ваши интерфейсы будут работать безупречно.

← На главную