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