Как проверить и сравнить режим записи документа в обработчике ПередЗаписью в 1С 8.3?

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

В процессе разработки в среде 1С:Предприятие 8.3 одной из наиболее частых задач является проверка режима записи документа. Разработчику необходимо точно знать, выполняется ли в данный момент простое сохранение документа (запись) или же документ проводится (проведение). От этого зависит корректность выполнения бизнес-логики: проверка заполнения реквизитов, контроль остатков, формирование дополнительных движений и проведение других транзакционных проверок.

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

В чем заключается суть проблемы и «ловушка отладчика»

Типичная ситуация: разработчик пытается проверить, выполняется ли проведение документа в обработчике события ПередЗаписью, и пишет следующий код:


Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда    
    // Выполняем действия, специфичные для проведения
КонецЕсли;

При запуске в режиме отладки выясняется, что программа просто игнорирует это условие и переходит к ветке КонецЕсли. Самое интересное происходит, когда мы ставим точку останова на строке условия: в табло отладчика переменная РежимЗаписи отображает значение «Проведение». Кажется, что равенство должно выполняться, но платформа упрямо возвращает Ложь. Почему так происходит?

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

Разбор контекстов: Модуль Объекта против Модуля Формы

Давайте детально проанализируем сигнатуры обработчиков событий в обоих модулях, чтобы навсегда исключить путаницу.

1. Работа в Модуле Объекта (на сервере)

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

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

Обратите внимание на параметры:

  1. Отказ — Булево. Если установить в значение Истина, запись будет отменена.
  2. РежимЗаписи — Системное перечисление типа РежимЗаписиДокумента (значения: Запись, Проведение, ОтменаПроведения).
  3. РежимПроведения — Системное перечисление типа РежимПроведенияДокумента (значения: Неоперативный, Оперативный).

В модуле объекта сравнение работает напрямую и без каких-либо нюансов. Мы можем использовать следующий классический код:


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

2. Работа в Модуле Формы (на клиенте)

В модуле управляемой формы событие ПередЗаписью отрабатывает в самом начале интерактивного процесса записи на клиенте. Сигнатура этого обработчика выглядит совсем иначе:


&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)

Второй параметр здесь — это ПараметрыЗаписи, имеющий тип Структура. Платформа упаковывает туда все свойства, связанные с текущим действием записи. Напрямую сравнивать структуру с перечислением нельзя. Чтобы получить режим записи, нам нужно обратиться к конкретному свойству этой структуры.

Безопасное извлечение режима записи в Модуле Формы

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

Рассмотрим пример надежного и безопасного написания кода в модуле формы документа:


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

Этот код гарантирует отсутствие критических ошибок выполнения типа «Поле объекта не обнаружено» и корректно отрабатывает во всех интерактивных сценариях.

Неочевидное поведение: Свойство «ПриЗаписиПерепроводить»

Разработчики часто сталкиваются со следующей логической проблемой: пользователь открывает уже проведенный документ, вносит незначительные изменения в текстовое поле (например, в комментарий) и нажимает кнопку «Записать» (дискета на панели). При этом разработчик ожидает, что выполнится простая запись без проведения, но в коде параметр все равно принимает значение РежимЗаписиДокумента.Проведение.

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

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

Сравнение с обычными формами

Для понимания эволюции платформы вспомним, как эта задача решалась в старых обычных формах (1С 8.1 и 8.2). В событии формы обычного клиента ПередЗаписью(Отказ) вообще не передавались параметры, отражающие режим записи. Разработчикам приходилось анализировать нажатые кнопки на форме, использовать глобальные переменные модуля или полностью переносить всю проверку в модуль объекта. В управляемых формах 1С 8.3 структура ПараметрыЗаписи элегантно решила эту проблему, предоставив полный контроль над процессом записи еще до отправки данных на сервер.

← На главную