Почему «Отказ = Истина» не заменяет «Возврат» в 1С: разбираем работу обработчика ПередЗаписью

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

Разработка в среде 1С:Предприятие часто ставит перед начинающими программистами вопросы, связанные с механизмами платформы и управлением ходом выполнения программы. Один из классических вопросов звучит так: зачем присваивать «Отказ = Истина», если можно просто написать «Возврат»?

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

В чем принципиальная разница между «Отказ» и «Возврат»?

Для того чтобы понять логику работы платформы, давайте разграничим назначение этих двух операторов:

Проанализируем три сценария использования этих операторов в обработчике события ПередЗаписью.

Сценарий 1. Только «Возврат» без установки «Отказ = Истина»

Рассмотрим следующий пример кода:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если Не ЗначениеЗаполнено(Организация) Тогда
        Возврат; 
    КонецЕсли;
    // Какая-то логика, которая не должна выполняться без организации
    РассчитатьПараметрыДокумента();
КонецПроцедуры

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

Сценарий 2. Только «Отказ = Истина» без использования «Возврат»

Посмотрим на такой вариант написания кода:


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

Что произойдет на практике: платформа зафиксирует, что запись производить нельзя (поскольку Отказ стал равен Истина). Но выполнение текущего кода процедуры не прекратится! Строка РассчитатьПараметрыДокумента() будет выполнена. Если этот метод завязан на то, что организация обязана быть заполнена, программа упадет с критической ошибкой выполнения (например, «Значение не является значением объектного типа»).

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


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

Здесь платформа выполнит обе проверки, выведет пользователю два сообщения и в итоге отменит запись.

Сценарий 3. Сочетание «Отказ = Истина» и «Возврат»

Это классический и наиболее надежный способ прерывания операции, если дальнейшее выполнение кода не имеет смысла при обнаружении первой же критической ошибки:


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

Что произойдет на практике: платформа получит флаг отмены операции, выполнение кода текущего обработчика мгновенно прекратится, и запись объекта в базу данных будет заблокирована.

Почему стандартная проверка заполнения реквизита не срабатывает при обычной записи?

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

В архитектуре 1С заложена строгая бизнес-логика разделения документов на «черновики» и «проведенные» документы:

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

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

Где правильно делать проверку заполнения реквизитов?

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

Разберем по шагам, почему это критически важно:

  1. Транзакционность и производительность СУБД. Обработчик ПередЗаписью выполняется непосредственно *внутри транзакции записи* в базу данных. Если в этот момент выставить Отказ = Истина, транзакция прерывается и происходит её откат (Rollback). Откат транзакции — очень ресурсоемкая операция для СУБД (MS SQL, PostgreSQL), которая временно блокирует таблицы базы данных и снижает общую производительность всей системы при работе сотен пользователей. Специализированный обработчик ОбработкаПроверкиЗаполнения отрабатывает до открытия транзакции, исключая лишнюю нагрузку на сервер.
  2. Разделение интерактивной и программной записи. Ваша конфигурация может обмениваться данными с другими системами, загружать документы из файлов excel или API. При программном создании документов обработчик ОбработкаПроверкиЗаполнения по умолчанию не вызывается (если это специально не указано в коде загрузки). Это позволяет без проблем импортировать «грязные» или частично заполненные данные для последующей ручной обработки. Если же проверки жестко прописаны в ПередЗаписью модуля объекта, программный обмен будет постоянно прерываться ошибками записи.

Пример использования правильного обработчика в модуле объекта:


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

Важные правила работы с параметром «Отказ» по стандартам 1С

При написании кода всегда придерживайтесь следующих стандартов, чтобы избежать труднодиагностируемых ошибок:

← На главную