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

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

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

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

Симптомы и поведение системы при отладке

Проанализируем типичный сценарий проявления проблемы:

  1. При проведении документа из формы списка вызывается процедура ОбработкаПроведения модуля объекта. Наборы записей регистров очищаются, заполняются новыми данными и записываются в информационную базу. В модуле набора записей регистра события ПередЗаписью и ПриЗаписи отрабатывают штатно (дважды: при первичной очистке и при фиксации новых записей).
  2. При интерактивном проведении из управляемой формы документа сначала все идет по такому же сценарию, однако сразу после завершения процедуры ОбработкаПроведения и выхода из серверных событий записи формы происходит третья итерация: в модуль набора записей регистра снова передается управление в процедуру ПередЗаписью с параметром Замещение = Истина, и движения полностью очищаются.
  3. Если проанализировать стек вызовов при третьей (лишней) записи, мы увидим всего одну строчку: событие ПередЗаписью соответствующего регистра. В стеке отсутствуют вызовы модулей форм, общих модулей или процедур подписок на события. Отладчиком невозможно поймать код конфигурации, инициирующий эту очистку, так как вызов инициируется внутренними механизмами платформы.
  4. Если создать новую управляемую форму документа или удалить текущую (позволив платформе генерировать автоформу), проведение начинает отрабатывать корректно. При этом в модуле проблемной формы может вообще отсутствовать какой-либо код.

Механизм возникновения проблемы в управляемых формах

Выясним причину такого поведения платформы. В управляемом приложении основной реквизит формы документа Объект имеет тип ДанныеФормыСтруктура. Внутри этого объекта существует подчиненная коллекция Объект.Движения.

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

Если же для ветки Объект.Движения или для конкретного набора записей регистра внутри этой ветки свойство Использовать всегда было установлено в значение Истина, происходит следующее:

  1. При открытии формы платформа считывает данные документа и заполняет структуру формы. Если документ новый или на момент открытия движений не было, коллекция движений в контексте формы оказывается пустой.
  2. При нажатии кнопки «Провести и закрыть» или «Провести» расширение формы преобразует данные формы в прикладной объект (механизм ДанныеФормыВЗначение) и выполняет стандартную транзакцию проведения. В модуле объекта процедура ОбработкаПроведения формирует и записывает реальные движения в базу данных.
  3. После выполнения серверных процедур записи документа платформа принудительно синхронизирует состояние реквизитов формы с базой данных. Так как в контексте самой формы набор записей регистра оставался пустым (автоматического обратного перечитывания сформированных движений в коллекцию формы не произошло), системный механизм управляемой формы записывает этот пустой набор поверх только что сформированных движений с признаком Замещение = Истина.

Именно поэтому в стеке вызовов отображается только событие модуля набора записей: запись выполняется платформенным кодом ядра 1С в рамках синхронизации данных управляемой формы.

Пошаговое решение проблемы

Разберем по шагам, как локализовать и исправить данную ошибку в конфигураторе:

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

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

Рассмотрим, откуда берется эта настройка. Чаще всего свойство Использовать всегда оказывается активным в двух ситуациях:

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

Посмотрим на рекомендации по правильной работе с движениями документов в управляемом интерфейсе:

  1. Не храните движения в реквизитах формы. Включение свойства Использовать всегда для наборов движений приводит к постоянной тяжелой сериализации таблиц движений между клиентом и сервером при каждом контекстном вызове, что существенно замедляет работу формы и увеличивает потребление оперативной памяти.
  2. Используйте стандартную панель навигации. Для просмотра сформированных проводок и движений открывайте стандартные списки записей регистра с отбором по регистратору через командный интерфейс формы документа либо используйте общие формы просмотра движений.
  3. Принудительное обновление контекста. Если по архитектурным соображениям коллекция движений действительно должна присутствовать непосредственно в реквизитах формы документа, то в обработчике формы ПослеЗаписиНаСервере необходимо принудительно обновлять данные формы из реального объекта базы данных:
    
    &НаСервере
    Процедура ПослеЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
        // Синхронизируем сформированные в ОбработкаПроведения движения с контекстом формы
        ЗначениеВДанныеФормы(ТекущийОбъект, Объект);
    КонецПроцедуры
    
    Это исключит затирание актуальных движений устаревшими пустыми данными формы.
← На главную