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

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

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

Рассмотрим подробнее причины такого поведения платформы 1С и проанализируем проверенные способы решения этой задачи.

Причины поведения платформы и вызова клиентских процедур

Выясним, почему стандартные сообщения закрываются вместе с формой:

  1. Привязка сообщений к контексту формы: Вызовы стандартных механизмов сообщений в управляемом приложении привязываются к окну конкретной формы. Как только транзакция проведения успешно завершается, форма выполняет команду закрытия и полностью уничтожает связанную с ней панель сообщений.
  2. Разделение контекстов исполнения: Процедура ОбработкаПроведения выполняется на стороне сервера. Из серверного контекста невозможно вызвать интерактивные клиентские диалоги (например, ПоказатьВопрос или ПоказатьПредупреждение), так как сервер не имеет прямого доступа к пользовательскому интерфейсу. Кроме того, документ может проводиться не из формы, а программно (в фоновом задании, при групповой обработке или обмене данными), где пользователя нет вовсе.

Вариант 1. Использование всплывающих системных оповещений

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

Разберем по шагам, как передать сигнал из события проведения на сервере в модуль формы на клиенте:

  1. В модуле объекта в событии ОбработкаПроведения при обнаружении нужного условия сохраняем текст уведомления во временную структуру ДополнительныеСвойства объекта.
  2. В модуле формы в серверном событии ПослеЗаписиНаСервере переносим сообщение из ДополнительныеСвойства в структуру ПараметрыЗаписи.
  3. В модуле формы в клиентском событии ПослеЗаписи вызываем метод ПоказатьОповещениеПользователю().

Посмотрим на пример реализации данного алгоритма:

Код в модуле объекта:


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

КонецПроцедуры

Код в модуле формы документа:


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

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

Вариант 2. Задание вопроса или предупреждения ДО проведения (Модуль формы)

Если перед проведением необходимо запросить подтверждение пользователя или принудительно показать ему предупреждающий диалог, всю интерактивную логику следует выносить до начала транзакции записи — в клиентское событие формы ПередЗаписью.

Рассмотрим порядок действий для асинхронной модели работы управляемых форм:

  1. В обработчике ПередЗаписью проверяем, что запись выполняется именно в режиме проведения (ПараметрыЗаписи.РежимЗаписи = РежимЗаписиДокумента.Проведение).
  2. Выполняем быстрый серверный вызов без контекста для проверки наличия необходимых остатков или условий.
  3. Если условие выполняется (например, стока нет), устанавливаем параметр Отказ = Истина, что отменяет стандартную запись и предотвращает закрытие формы.
  4. С помощью ОписаниеОповещения выводим асинхронный диалог ПоказатьВопрос() или ПоказатьПредупреждение().
  5. В процедуре обработки ответа пользователя, если пользователь согласен продолжить проведение, устанавливаем вспомогательный флаг (или специальный параметр в ПараметрыЗаписи) и повторно вызываем метод формы Записать(ПараметрыЗаписи).

Проанализируем пример реализации интерактивного подтверждения в модуле формы:


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

КонецПроцедуры

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

КонецПроцедуры

&НаСервереБезКонтекста
Функция ПроверитьОстаткиНаСервере()
	// Логика проверки остатков на сервере
	Возврат Истина; 
КонецФункции

Альтернативные способы записи информации

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

← На главную