Как в 1С разрешить сохранение документа без заполнения реквизитов, но проверять их при проведении?

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

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

Рассмотрим детально, как реализовать такую логику, разберем типичные ошибки новичков и проанализируем наиболее эффективные методы программирования в системе 1С:Предприятие 8.3.

Способ 1. Использование события ПередЗаписью в модуле объекта

Самый простой и прямолинейный способ — перехватить процесс записи в модуле объекта и проанализировать, в каком режиме она выполняется. У события ПередЗаписью есть параметр РежимЗаписи, который принимает значения системного перечисления РежимЗаписиДокумента (Запись, Проведение или ОтменаПроведения).

Проанализируем пример кода, который позволяет сохранить документ, но блокирует проведение при незаполненном складе:


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

Важный нюанс: В этом примере мы используем объект СообщениеПользователю вместо функции Предупреждение(). Почему это критично? Модуль объекта исполняется на стороне сервера, где интерактивные окна (диалоги) недоступны. Использование Предупреждение() в этом месте приведет к аварийному завершению работы программы.

Способ 2. Обработка проверки заполнения (современный стандарт)

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

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

Разберем, как это сделать:

  1. Установите у реквизитов в метаданных свойство Проверка заполнения в значение «Не проверять». Мы будем управлять проверкой программно.
  2. В модуле объекта напишем следующий код:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    // Выясним режим записи. 
    // Нюанс: напрямую в этом обработчике РежимЗаписи недоступен.
    // Если проверка вызвана при проведении, платформа передает это состояние.
    
    Если Ссылка.Пустая() ИЛИ ЭтотОбъект.Проведен = Ложь Тогда
        // Если нам нужно проверять только при проведении, 
        // мы можем использовать дополнительное свойство, переданное из формы,
        // либо анализировать текущий контекст.
    КонецЕсли;

    // Традиционный подход: добавляем реквизиты в массив только при необходимости
    // Но так как нам нужно разделение "Запись/Проведение", 
    // лучше использовать расширение формы или ПередЗаписью.
КонецПроцедуры

Способ 3. Передача режима через ДополнительныеСвойства

Поскольку в ОбработкаПроверкиЗаполнения нет прямого параметра РежимЗаписи, профессиональные разработчики используют коллекцию ДополнительныеСвойства. Это «почтовый ящик» внутри объекта, который позволяет передавать данные между разными событиями.

Рассмотрим реализацию по шагам:

Шаг 1. В модуле объекта в событии ПередЗаписью сохраняем режим:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    ДополнительныеСвойства.Вставить("ТекущийРежимЗаписи", РежимЗаписи);
КонецПроцедуры

Шаг 2. В обработчике проверки используем это значение:


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

Анализ типичной ошибки: «Не установлен отбор по регистратору»

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

Выясним причину ошибки: когда вы меняете режим проведения «на лету» для нового объекта, который еще не записан в базу данных, система пытается выполнить действия с регистрами (движениями), для которых нужен уникальный идентификатор (ссылка) и установленный регистратор. Поскольку объект еще не существует в физической таблице БД, возникает конфликт отборов.

Правильное решение: Никогда не меняйте РежимЗаписи вручную, если в этом нет исключительной необходимости. Для остановки процесса используйте Отказ = Истина. Это корректно прервет транзакцию и выведет сообщение пользователю, не нарушая логику работы платформы с регистрами.

Особенности работы на Управляемых формах

Если вы работаете в интерфейсе «Такси», помните о разделении контекста. Проверки, написанные в &НаКлиенте в модуле формы, сработают быстро, но их легко обойти при программном создании документа. Проверки в модуле объекта (на сервере) — это «последний рубеж» обороны, который гарантирует целостность данных в базе.

Рассмотрим рекомендации по оформлению кода:

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

← На главную