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