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

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

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

Разберем основной механизм: событие ПередЗаписью

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

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


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    // РежимЗаписи имеет тип РежимЗаписиДокумента
    // Возможные значения: Запись, Проведение, ОтменаПроведения
КонецПроцедуры

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

Использование коллекции ДополнительныеСвойства

Часто логику требуется выполнить именно в событии ПриЗаписи, когда мы уже уверены, что данные физически попали в таблицы БД, или в ОбработкеПроведения. Но как «протащить» знание о том, что это было именно проведение, из процедуры ПередЗаписью в ПриЗаписи?

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

  1. В модуле объекта перехватываем режим в событии ПередЗаписью.
  2. Сохраняем его в структуру ДополнительныеСвойства.
  3. В событии ПриЗаписи извлекаем это значение и анализируем его.

Посмотрим на пример кода в модуле объекта:


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

    // Сохраняем режим записи, чтобы использовать его позже
    ДополнительныеСвойства.Вставить("РежимЗаписиДляЛогики", РежимЗаписи);
    
КонецПроцедуры

Процедура ПриЗаписи(Отказ)
    
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

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

КонецПроцедуры

Нюансы работы в управляемых и обычных формах

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

Если вы работаете в Обычных формах (например, в УПП 1.3), вы можете проверить кнопку, которую нажал пользователь. Однако помните: если документ будет записан программно (обработкой), код в форме не сработает. Поэтому золотое правило разработки 1С гласит: критически важную бизнес-логику (расчеты, движения, статусы) всегда нужно размещать в модуле объекта.

Почему нельзя изменять объект в ОбработкеПроведения?

Рассмотрим важный технический момент, упомянутый в обсуждении. Многие начинающие разработчики пытаются менять реквизиты самого документа (например, ставить отметку «Проверен менеджером») внутри процедуры ОбработкаПроведения.

Важно знать: В управляемом приложении и на современных версиях платформы 8.3 объект в ОбработкеПроведения фактически уже записан в основную таблицу базы данных. Если вы измените значение реквизита ЭтотОбъект.Комментарий = "Проведено" внутри этой процедуры, изменения не сохранятся в БД, так как транзакция записи самого объекта уже завершена, и далее фиксируются только движения по регистрам.

Для изменения данных самого документа используйте связку ПередЗаписью + ДополнительныеСвойства или выполняйте изменения до момента вызова Записать().

Как отличить первое проведение от перепроведения?

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


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

Подведем итоги

Для надежного определения режима записи документа выполним следующие шаги:

  1. Используйте событие ПередЗаписью в модуле объекта для анализа параметра РежимЗаписи.
  2. Если логика требует работы с уже записанной ссылкой, передавайте флаг проведения через ДополнительныеСвойства в событие ПриЗаписи.
  3. Старайтесь избегать размещения бизнес-логики в модулях формы, чтобы она корректно отрабатывала при программной записи или обмене данными.
  4. Помните о проверке ОбменДанными.Загрузка, чтобы ваш код не мешал при переносе данных между базами.

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

← На главную