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