Как реализовать принудительное заполнение полей документа после вопроса пользователю

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

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

Постановка задачи и выбор метода решения

Проанализируем ситуацию: нам необходимо при попытке записи или проведения документа задать пользователю вопрос: «Является ли этот документ государственным контрактом?». В зависимости от ответа мы либо требуем заполнения полей, либо разрешаем запись «как есть».

Для решения этой задачи нам потребуется задействовать два уровня системы:

  1. Клиентский уровень (Форма документа): Здесь мы будем перехватывать событие ПередЗаписью, чтобы задать вопрос пользователю.
  2. Серверный уровень (Модуль объекта): Здесь мы будем использовать процедуру ОбработкаПроверкиЗаполнения, чтобы гарантировать целостность данных на уровне базы данных.

Шаг 1. Настройка проверки заполнения в конфигураторе

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

  1. Откроем дерево метаданных и найдем нужный документ.
  2. Перейдем на закладку «Данные».
  3. Найдем свойство «Проверка заполнения».
  4. Изменим значение с «Использовать при проведении» на «Использовать». Теперь платформа будет проверять реквизиты при любом сохранении объекта.

Шаг 2. Реализация вопроса пользователю в модуле формы

В управляемом приложении (платформа 8.3) все диалоги работают асинхронно. Это означает, что процедура ПередЗаписью не будет ждать ответа пользователя, она завершится сразу. Разберем по шагам, как правильно организовать этот процесс в модуле формы документа.

Нам понадобится вспомогательный реквизит формы (не объекта!), например, ВопросЗадан (тип Булево), чтобы избежать повторного появления вопроса при программном вызове записи.


&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)

	// Если вопрос уже был задан и ответ получен, просто выходим
	Если ЭтаФорма.ВопросЗадан Тогда
		Возврат;
	КонецЕсли;

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

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

&НаКлиенте
Процедура ПослеОтветаНаВопросОГосконтракте(Результат, ДополнительныеПараметры) Экспорт

	Если Результат = КодВозвратаДиалога.Да Тогда
		Объект.ЯвляетсяГосКонтрактом = Истина; // Реквизит объекта для хранения признака
	Иначе
		Объект.ЯвляетсяГосКонтрактом = Ложь;
	КонецЕсли;

	// Устанавливаем флаг, чтобы не зациклиться
	ЭтаФорма.ВопросЗадан = Истина;
	
	// Вызываем запись объекта программно с теми же параметрами
	Записать(ДополнительныеПараметры);
	
	// Сбрасываем флаг для возможности последующих изменений
	ЭтаФорма.ВопросЗадан = Ложь;

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

Шаг 3. Программная проверка заполнения в модуле объекта

Теперь рассмотрим ситуацию на сервере. Когда вызывается метод Записать(), платформа инициирует событие ОбработкаПроверкиЗаполнения. Нам нужно динамически добавить наши реквизиты в массив ПроверяемыеРеквизиты, если флаг госконтракта установлен.

Разберем код в модуле объекта документа:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

	// Проверяем признак, который мы установили на форме
	Если ЯвляетсяГосКонтрактом Тогда
		
		// Добавляем имена реквизитов в массив проверки
		ПроверяемыеРеквизиты.Добавить("НомерГосКонтракта");
		ПроверяемыеРеквизиты.Добавить("ДатаГосКонтракта");
		ПроверяемыеРеквизиты.Добавить("ИдентификаторГосКонтракта");
		
	КонецЕсли;

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

Проанализируем работу этого механизма: если пользователь ответил «Да», реквизиты попадают в список проверки. Если они не заполнены, 1С выведет стандартное сообщение «Поле ... не заполнено» и установит Отказ = Истина, тем самым не дав записать документ.

Шаг 4. Улучшение UX (пользовательского опыта)

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

В этом случае логика упрощается:

  1. Пользователь сам ставит галочку «Государственный контракт».
  2. С помощью условного оформления мы подсвечиваем нужные поля красным пунктиром (как обязательные), если галочка стоит.
  3. В ОбработкаПроверкиЗаполнения оставляем код из Шага 3.

Если же бизнес-процесс требует именно подтверждения при записи, рекомендуется проверять, заполнены ли уже эти поля. Если они заполнены, вопрос можно не задавать.

Особенности работы с «ЭтоНовый()»

Часто вопрос нужно задавать только при первом создании документа. В управляемых формах на клиенте мы не можем напрямую вызвать метод ЭтоНовый(). Выясним, как это обойти:

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

Пример проверки в ПередЗаписью на клиенте:


// Проверка на новый документ без лишних серверных вызовов
ЭтоНовыйДокумент = Объект.Ссылка.Пустая();
Если ЭтоНовыйДокумент Тогда
    // Логика для нового документа
КонецЕсли;

Использование дополнительных свойств записи

Чтобы передать информацию от клиента на сервер (например, результат ответа пользователя) без создания лишних реквизитов в базе данных, можно использовать ДополнительныеСвойства. Однако в процедуре ПередЗаписью на клиенте это сделать сложнее, поэтому использование флага в объекте (как ЯвляетсяГосКонтрактом) является наиболее надежным способом для 1С:ERP.

Резюме

Мы рассмотрели комплексный подход к динамической проверке заполнения. Ключевые моменты:

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

← На главную