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

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

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

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

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

Способ 1. Управление свойством формы ПриЗаписиПерепроводить (штатный способ)

Наиболее правильный и лаконичный путь решения задачи в управляемой форме — временное отключение платформенного автоперепроведения перед штатным вызовом записи. Разберем реализацию данного способа по шагам:

  1. На клиенте устанавливаем свойство формы ПриЗаписиПерепроводить в значение Ложь.
  2. Вызываем стандартный метод формы Записать().
  3. Возвращаем свойство ПриЗаписиПерепроводить в исходное состояние Истина, чтобы дальнейшие действия пользователя выполнялись штатно.

Посмотрим на пример клиентского кода:


&НаКлиенте
Процедура ЗаписатьБезПерепроведения()
    ПриЗаписиПерепроводить = Ложь;
    Записать();
    ПриЗаписиПерепроводить = Истина;
КонецПроцедуры

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

Способ 2. Программная запись объекта на сервере через РеквизитФормыВЗначение

Если требуется полностью обойти контекст интерактивной записи формы и зафиксировать состояние реквизитов напрямую в базе данных, применим подход с получением объекта документа на сервере. Разберем, как устроен этот механизм:


&НаКлиенте
Процедура ВыполненоПриИзменении(Элемент)
    Если Объект.Выполнено Тогда
        ЗаписатьБезПроведенияНаСервере();
        Модифицированность = Ложь;
    КонецЕсли;
КонецПроцедуры

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

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

Способ 3. Использование режима загрузки данных (ОбменДанными.Загрузка)

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


&НаКлиенте
Процедура ВыполнитьСлужебнуюЗапись()
    ПараметрыЗаписи = Новый Структура("ТолькоЗапись", Истина);
    Записать(ПараметрыЗаписи);
КонецПроцедуры

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

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

Архитектурные риски и рекомендации

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

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