Как вывести сообщение пользователю при создании документа на основании и почему оно уходит на форму-родитель

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

При разработке в среде 1С:Предприятие 8.3 (Управляемые формы) программисты часто сталкиваются с неочевидным поведением платформы при создании одного документа на основании другого. Типичная задача: при нажатии на кнопку "Создать на основании" проверить, проведен ли документ-источник (Документ 1), и если нет — вывести предупреждение пользователю на форме нового документа (Документ 2).

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

Выясняем причину: почему сообщение «улетает» на форму-источник

Для того чтобы понять логику платформы, проанализируем жизненный цикл создания новой управляемой формы на основании другого объекта:

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

Давайте рассмотрим три надежных способа решения этой проблемы в зависимости от ваших бизнес-требований.

---

Решение 1. Вывод предупреждения в новой форме через клиентский обработчик «ПриОткрытии»

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

Для реализации этого подхода выполним следующие шаги:

Шаг 1. Добавим в форму Документа 2 новый реквизит формы (не путать с реквизитом объекта!). Назовем его, например, ТекстПредупрежденияПриОткрытии с типом данных Строка.

Шаг 2. В серверном обработчике ПриСозданииНаСервере формы Документа 2 выполним проверку статуса проведения документа-основания и запишем текст ошибки в наш реквизит формы:


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

Шаг 3. В клиентском обработчике формы ПриОткрытии выполним анализ нашего реквизита и выведем сообщение, жестко привязав его к текущему окну с помощью свойства ИдентификаторНазначения:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	Если Не ПустаяСтрока(ТекстПредупрежденияПриОткрытии) Тогда
		
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = ТекстПредупрежденияПриОткрытии;
		
		// Ключевой момент: привязываем сообщение к идентификатору ТЕКУЩЕЙ формы
		Сообщение.ИдентификаторНазначения = ЭтаФорма.УникальныйИдентификатор;
		
		Сообщение.Сообщить();
		
	КонецЕсли;
	
КонецПроцедуры

Этот способ гарантирует, что сообщение появится в верхней части открывшегося Документа 2, не вводя пользователя в заблуждение.

---

Решение 2. Полный запрет создания на основании по стандартам разработки 1С

Зачастую бизнес-логика требует более жесткого подхода: если документ-основание не проведен, создавать новый документ на его основе категорически запрещено. В таком случае просто выводить предупреждение бессмысленно — нужно заблокировать сам процесс генерации нового объекта.

Обратим внимание, что в событии ОбработкаЗаполнения в модуле объекта отсутствует привычный параметр Отказ. Как же прервать выполнение?

Согласно официальному Стандарту разработки Фирмы "1С" (Раздел: Отказ от ввода на основании), единственным верным решением в данном сценарии является генерация системного исключения.

Рассмотрим, как правильно реализовать этот механизм в модуле объекта Документа 2:


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

Как это работает: При вызове оператора ВызватьИсключение платформа мгновенно прерывает транзакцию создания объекта на сервере. Форма Документа 2 даже не начнет создаваться, а пользователю на экране формы Документа 1 будет выведено штатное системное окно с сообщением об ошибке. Это максимально безопасный и соответствующий стандартам 1С метод проектирования бизнес-логики.

---

Решение 3. Современный подход с использованием БСП (Библиотека Стандартных Подсистем)

Проанализируем современную архитектуру типовых конфигураций (таких как 1С:ERP, КА, УТ). В них разработчики практически отказались от стандартных платформенных кнопок заполнения на основании. Вместо них используется подсистема "Подключаемые команды" БСП.

Использование этого механизма позволяет решить проблему еще более элегантно — выполнить проверку на стороне клиента ДО обращения к серверу для создания нового объекта:

  1. При нажатии кнопки создания на основании вызывается общий клиентский модуль БСП.
  2. Алгоритм проверяет свойство Проведен у выделенного в списке или открытого документа-источника прямо на клиенте (или через быстрый облегченный вызов сервера).
  3. Если документ не проведен, пользователю выводится стандартный асинхронный диалог ПоказатьПредупреждение, и процесс прерывается без инициализации тяжелых серверных процедур заполнения нового документа.

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

← На главную