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