Как исключить выполнение алгоритмов при автоматическом перепроведении документа во время записи?

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

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

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

Разбор механизма перепроведения

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

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

Решение 1: Использование структуры ДополнительныеСвойства

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

Рассмотрим, как это реализовать по шагам:

  1. В модуле формы перехватываем момент записи.
  2. Добавляем в объект специальный признак (флаг).
  3. В модуле объекта или в дальнейших процедурах формы проверяем этот флаг.

Пример кода в модуле формы:


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

Теперь в модуле объекта, в процедуре ОбработкаПроведения, мы можем проверить наличие этого свойства. Если оно установлено, мы понимаем, что проведение вызвано «искусственно» свойством формы, и можем пропустить выполнение тяжелых алгоритмов.


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

Решение 2: Программное изменение свойств формы

Если религия или требования проекта запрещают менять свойство ПриЗаписиПерепроводить в конфигураторе, мы можем сделать это программно при создании формы. Это позволит полностью контролировать процесс записи.

Проанализируем пример кода в модуле формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Отключаем автоматическое перепроведение программно
    ЭтаФорма.ПриЗаписиПерепроводить = ИспользованиеПерепроведенияПриЗаписи.НеИспользовать;
КонецПроцедуры

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

Решение 3: Управление через ПараметрыЗаписи на клиенте

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

Выясним, как это выглядит в коде:


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

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

Решение 4: Программный вызов записи без перепроведения

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


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

Решение 5: Использование расширений (для объектов на поддержке)

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

Мы можем создать расширение и добавить в него обработчик &Перед("ОбработкаПроведения"). В этом обработчике мы можем проанализировать состояние объекта. Например, если мы не хотим выполнять код, если документ уже был проведен и данные не изменились существенным образом.


&Перед("ОбработкаПроведения")
Процедура Расш_ОбработкаПроведения(Отказ, РежимПроведения)
    // Проверяем, не является ли это повторным проведением без изменения важных данных
    Если ЭтотОбъект.Проведен И Не ЭтотОбъект.Модифицированность() Тогда
        // Здесь можно установить флаг пропуска
    КонецЕсли;
КонецПроцедуры

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

Разберем, какой метод выбрать в зависимости от условий:

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

← На главную