Переход с обычного приложения 1С на управляемые формы часто вызывает трудности у разработчиков, привыкших к линейному выполнению кода. Одной из самых распространенных проблем является попытка вызвать интерактивное диалоговое окно (например, предупреждение или вопрос) непосредственно из модуля объекта в процедуре ОбработкаПроведения. В управляемом приложении это приводит к ошибке: «Процедура или функция с указанным именем не определена (Предупреждение)». Выясним причину этой ошибки и разберем несколько эффективных способов решения задачи.
Проанализируем ситуацию: процедура ОбработкаПроведения всегда выполняется на стороне сервера внутри транзакции базы данных. Серверный код не имеет доступа к интерфейсу пользователя. Методы Предупреждение() или современный аналог ПоказатьПредупреждение() являются клиентскими. Они требуют физического наличия монитора и пользователя перед ним, чего у сервера нет. Более того, остановка серверного процесса для ожидания реакции пользователя (модальность) недопустима, так как это блокирует ресурсы базы данных для всех остальных участников системы.
Рассмотрим подробнее три основных подхода к решению этой задачи: использование системных сообщений, механизм передачи данных через дополнительные свойства и превентивные проверки.
Если ваша задача — просто проинформировать пользователя о задолженности, не прерывая процесс проведения, наиболее правильным и «штатным» способом является использование объекта СообщениеПользователю. В отличие от старого метода Сообщить(), этот объект позволяет привязать текст сообщения к конкретному полю на форме.
Разберем пример кода, который можно разместить в модуле объекта:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Выполняем расчет долга
Долг = РегистрыНакопления.Взаиморасчеты.Остаток(Новый Структура("Контрагент", Контрагент));
Если Долг > 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Внимание! У контрагента " + Контрагент + " имеется задолженность: " + Долг;
// Привязываем сообщение к полю Контрагент на форме
Сообщение.Поле = "Объект.Контрагент";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
Важный нюанс: Пользователи часто жалуются, что такие сообщения «незаметны», особенно если после проведения форма закрывается. Если бизнес-требование настаивает именно на всплывающем окне, нам придется использовать более сложную схему.
Чтобы вывести полноценное окно ПоказатьПредупреждение() после успешного проведения, нам нужно передать информацию о долге из серверной процедуры ОбработкаПроведения обратно на клиентскую форму. Напрямую вернуть значение из ОбработкаПроведения нельзя, поэтому мы используем промежуточное хранилище объекта — структуру ДополнительныеСвойства.
Рассмотрим алгоритм реализации по шагам:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// ... логика расчета долга ...
Если Долг > 0 Тогда
ЭтотОбъект.ДополнительныеСвойства.Вставить("ТекстПредупреждения", "Долг клиента: " + Долг);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// Извлекаем данные из свойств объекта и помещаем в параметры записи,
// которые будут доступны на клиенте
Если ТекущийОбъект.ДополнительныеСвойства.Свойство("ТекстПредупреждения") Тогда
ПараметрыЗаписи.Вставить("ТекстПредупреждения", ТекущийОбъект.ДополнительныеСвойства.ТекстПредупреждения);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
Если ПараметрыЗаписи.Свойство("ТекстПредупреждения") Тогда
Оповещение = Новый ОписаниеОповещения; // Обязательно для немодальных вызовов
ПоказатьПредупреждение(Оповещение, ПараметрыЗаписи.ТекстПредупреждения);
КонецЕсли;
КонецПроцедуры
Этот метод позволяет соблюсти стандарты разработки и при этом гарантированно привлечь внимание пользователя после того, как транзакция проведения будет успешно завершена.
Если модальное окно (которое нужно закрывать кликом) кажется слишком навязчивым, можно воспользоваться методом ПоказатьОповещениеПользователя(). Это «всплывашка» в нижнем углу экрана, которая не блокирует работу, но хорошо видна.
Пример вызова из клиентской процедуры ПослеЗаписи:
ПоказатьОповещениеПользователя(
"Внимание: Долг!",
"http://ссылка_на_отчет",
"У контрагента накоплен долг: " + СуммаДолга,
БиблиотекаКартинок.Важное
);
Проанализируем преимущества: такое оповещение не прерывает работу пользователя, позволяет добавить гиперссылку (например, на отчет по взаиморасчетам) и выглядит современно.
Разберем ситуацию с групповым перепроведением документов. Представьте, что бухгалтер запускает перепроведение 1000 документов за месяц. Если бы система позволила вставить Предупреждение() в модуль объекта, сервер бы «завис» на первом же документе, ожидая, пока кто-то нажмет «ОК» в сессии, которая может быть даже не открыта (например, при выполнении регламентным заданием).
Рекомендации по безопасности кода:
ОбменДанными.Загрузка. Если оно истинно, никакие проверки и сообщения выводить не нужно.ОбщегоНазначенияКлиентСервер.СообщитьПользователю(). Он автоматически обрабатывает различные контексты вызова.ПередЗаписью на стороне клиента. Это позволит предупредить пользователя до начала транзакции, сэкономив ресурсы сервера.Подводя итог: в управляемом приложении 1С разделение логики на «тихий» сервер и «интерактивный» клиент — это не ограничение, а инструмент создания стабильных и быстрых систем. Используйте ДополнительныеСвойства для передачи сигналов на форму, и ваши интерфейсы будут работать безупречно.