Зачем использовать Движения.Очистить() при проведении документа в 1С

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

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

Особенности работы коллекции Движения и метода Очистить()

Важно понимать разницу между объектами в оперативной памяти и физическими записями в базе данных. Вызов метода Движения.Очистить() удаляет элементы из коллекции записей в **оперативной памяти**. Однако сам по себе этот метод **не удаляет** сформированные ранее движения из таблиц базы данных (СУБД).

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


// Очистка наборов в оперативной памяти
Движения.Очистить();

// Чтобы изменения попали в БД, платформе нужно дать команду на запись
Движения.Записывать = Истина;

Если используется запись конкретного регистра, код может выглядеть следующим образом:


Движения.Продажи.Очистить();
Движения.Продажи.Записать();

Различие старой и новой методик проведения

Причиной появления явного кода очистки перед формированием новых движений часто является следование **старой методике проведения** (актуальной для обычного приложения или ранних версий платформы):

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

Свойства документа: Управление автоматическим удалением движений

Поведение платформы при распроведении и перепроведении документа регулируется свойствами объекта конфигурации в ветке **«Движения»**:

  1. Удалять автоматически при отмене проведения: Значение по умолчанию. При перепроведении документа платформа не удаляет старые движения из БД перед началом транзакции, а перезаписывает их поверх в момент завершения процедуры проведения. В случае отмены проведения движения удаляются автоматически.
  2. Удалять автоматически: Платформа очищает и записывает пустые наборы движений в БД до входа в процедуру ОбработкаПроведения. Это упрощает написание кода, но увеличивает количество операций с БД, создавая лишнюю нагрузку на СУБД и повышая риск блокировок.
  3. Не удалять автоматически: Платформа полностью перекладывает управление движениями на разработчика. Старые движения сохраняются в БД, пока разработчик сам не вызовет метод очистки и записи. Это необходимо при построечной записи движений или сложных алгоритмах проведения.

Запись движений напрямую в регистры и их очистка

Рассмотрим еще одну частую причину, почему разработчики вручную обрабатывают отмену проведения в событии ОбработкаУдаленияПроведения. Существуют записи, которые создаются не через стандартную коллекцию Движения документа, а посредством прямой записи в менеджер записи или набор записей регистра.

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

В этом случае при отмене проведения или пометке документа на удаление автоматическая очистка платформы не сработает. Разработчик должен явно удалить такие записи в модуле объекта:


Процедура ОбработкаУдаленияПроведения(Отказ)
    
    // Удаление специфических записей, созданных прямой записью
    НаборЗаписей = РегистрыСведений.НапоминанияПользователей.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Объект.Установить(Ссылка);
    НаборЗаписей.Записать(); // Записываем пустой набор для удаления
    
КонецПроцедуры

Влияние явной записи на блокировки и производительность

Рассмотрим, почему не рекомендуется без необходимости вызывать Движения.Записать() в начале или в середине процедуры проведения:

  1. Увеличение времени транзакции: Ранняя запись движений блокирует физические таблицы регистров в СУБД на всё время выполнения остального кода процедуры проведения.
  2. Риск взаимных блокировок (Deadlocks): При автоматической записи движений платформой по завершении транзакции 1С гарантирует строго определенный порядок обращения к таблицам регистров. Если разработчик записывает наборы движений вручную в произвольном порядке из разных документов, резко возрастает вероятность возникновения взаимных блокировок при параллельной работе пользователей.

Итоги и рекомендации

Выяснив механизмы работы платформы, сформулируем основные правила:

  1. В современных управляемых приложениях и при стандартных настройках документа вызывать Движения.Очистить() в начале процедуры ОбработкаПроведения **не требуется**.
  2. Если необходимо исключить влияние старых движений текущего документа на запрос остатков, используйте новую методику проведения или исключайте текущий документ в параметрах запроса с помощью условия Ссылка <> &Ссылка.
  3. Явное использование Движения.<ИмяРегистра>.Очистить() оправдано при пошаговом/этапном формировании движений или при реализации сложных алгоритмов с настройкой «Не удалять автоматически».
← На главную