При разработке новых документов в конфигурациях «1С:Предприятие 8» (например, в «Розница 1.0» или других решениях на обычных формах) программисты часто сталкиваются с ситуацией: программный код в процедуре ОбработкаПроведения написан верно, коллекция движений в отладчике заполняется, но после завершения транзакции в регистре накопления записи так и не появляются. Разберем детально, почему это происходит, как на это влияют свойства метаданных и какие методики проведения считаются актуальными.
Рассмотрим ситуацию, с которой столкнулся автор темы. В одном документе («Заказ покупателя») движения записываются автоматически, а в другом («Снятие резерва») — нет, хотя код формирования набора записей идентичен. Решение, которое помогло автору, заключается в явной установке свойства Записывать для конкретного набора движений. Проанализируем пример кода:
// Регистр накопления "Заказы покупателей"
Если НЕ Отказ Тогда
НаборДвижений = Движения.ЗаказыПокупателей;
ТаблицаДвижений = НаборДвижений.ВыгрузитьКолонки();
// Заполнение таблицы движений данными из документа
ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ТаблицаПоТоварам, ТаблицаДвижений);
// Установка параметров набора
НаборДвижений.мПериод = Дата;
НаборДвижений.мТаблицаДвижений = ТаблицаДвижений;
// Вызов метода формирования (в типовых часто используется обертка)
НаборДвижений.ВыполнитьПриход();
// КЛЮЧЕВАЯ СТРОЧКА, решающая проблему:
НаборДвижений.Записывать = Истина;
КонецЕсли;
Установка НаборДвижений.Записывать = Истина сообщает платформе, что по завершении процедуры проведения данный набор записей необходимо принудительно зафиксировать в базе данных. Но возникает резонный вопрос: почему в одном документе это работает без этой строки, а в другом — нет? Ответ кроется в настройках метаданных документа на вкладке «Движения».
В свойствах документа в дереве метаданных есть важный параметр — «Запись движений при проведении». Он может принимать два значения:
ОбработкаПроведения отслеживает, менялся ли набор записей (добавлялись ли строки, вызывался ли метод Загрузить). Если изменения были, платформа автоматически установит флаг записи в значение Истина и запишет данные в конце транзакции.Движения.ИмяРегистра.Записывать = Истина.Выясним причину разного поведения документов: скорее всего, в «Заказе покупателя» по умолчанию стояло «Записывать модифицированные», а в новом документе «Снятие резерва» — «Записывать выбранные». Именно поэтому в первом случае движения появлялись «магическим» образом, а во втором требовали явной команды.
Рассмотрим подробнее, почему разработчики фирмы «1С» рекомендуют использовать режим «Записывать выбранные». Это напрямую связано с оптимизацией работы базы данных и уменьшением количества блокировок.
При использовании старой методики («Записывать модифицированные») часто применяется свойство документа «Удаление движений» в режиме «Удалять автоматически». Это работает так: как только начинается проведение, платформа блокирует таблицы всех регистров, по которым документ может делать движения, и физически удаляет старые записи. Только после этого запускается ваш код. Если документ сложный, таблицы остаются заблокированными долгое время, что мешает другим пользователям.
Новая методика («Записывать выбранные») в сочетании с режимом «Не удалять автоматически» работает иначе:
Записывать = Истина, и старые записи (если они были) остаются или обрабатываются согласно логике программиста.Проанализируем преимущества новой методики: она позволяет избежать лишних операций DELETE в SQL, заменяя их более эффективным обновлением данных. Это существенно снижает риск возникновения Deadlocks (взаимных блокировок) при интенсивной работе пользователей.
Важно различать момент физической записи данных. Выясним, что лучше использовать внутри ОбработкаПроведения.
Если вы вызываете метод Движения.ЗаказыПокупателей.Записать(), запись в базу происходит немедленно. Это может быть необходимо, если в этом же коде далее вам нужно прочитать остатки по этому же регистру с учетом только что сделанных движений (хотя для этого лучше использовать границы или временные таблицы).
Если же вы устанавливаете Движения.ЗаказыПокупателей.Записывать = Истина, физическая запись произойдет один раз в самом конце, после выполнения всего кода ОбработкаПроведения. Это рекомендуемый способ, так как он минимизирует время удержания транзакционных блокировок таблиц базы данных. Помните: чем меньше времени данные «записываются» в середине кода, тем стабильнее работает система.
В старых типовых решениях, таких как «Розница 1.0», часто встречаются вспомогательные методы в модулях наборов записей, например ВыполнитьПриход() или ВыполнитьРасход(). Рассмотрим их роль:
Обычно это экспортные процедуры в модуле набора записей регистра, которые инкапсулируют логику заполнения колонок (Период, Регистратор, Активность). Внутри таких процедур разработчики часто забывают добавить установку флага Записывать = Истина. Поэтому, создавая новый документ «по образу и подобию» старого, всегда проверяйте не только код модулей, но и свойства объекта в дереве конфигурации.
Чтобы избежать проблем с отсутствием движений, придерживайтесь следующего алгоритма при создании или изменении документов:
Движения.ИмяРегистра.Записывать = Истина.Записать() без явной необходимости внутри транзакции проведения. Отдавайте предпочтение установке флага записи.ВыполнитьПриход()), загляните внутрь этих процедур (F12), чтобы понять, управляют ли они флагом записи самостоятельно.Понимание того, как платформа управляет коллекциями движений, позволяет не только быстро исправлять ошибки типа «пропавших записей», но и писать код, который будет работать быстро и без конфликтов в многопользовательской среде.