Часто при разработке собственных документов в 1С:Предприятие разработчики сталкиваются с неприятной ситуацией: при повторном проведении документа вместо замещения старых записей в регистре накопления создаются новые. В результате остатки в системе удваиваются или даже утраиваются. Давайте подробно разберем, почему это происходит и как гарантированно избежать дублей.
Для начала вспомним, как работает платформа 1С:Предприятие. Когда вы устанавливаете свойство Записывать = Истина у объекта Движения, платформа при выполнении метода Записать() анализирует состояние набора записей в памяти:
Дублирование возникает тогда, когда набор записей считается «прочитанным», но логика программы не очищает его корректно, или когда в процессе выполнения ОбработкиПроведения происходит обращение к коллекции движений, которое провоцирует их чтение из базы данных.
Самый надежный и профессиональный метод предотвратить дублирование — это принудительная очистка набора записей перед тем, как вы начнете добавлять новые движения. Это избавляет вас от зависимости от того, были ли прочитаны движения ранее какими-либо формами или сторонними процедурами.
Разберем пример реализации в модуле объекта:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Гарантированно очищаем старые движения
Движения.ОстаткиТМЦ.Очистить();
// Устанавливаем признак записи
Движения.ОстаткиТМЦ.Записывать = Истина;
// ... ваш код формирования движений ...
Движение = Движения.ОстаткиТМЦ.Добавить();
// ... заполнение реквизитов ...
КонецПроцедуры
Этот метод является «золотым стандартом» разработки, так как он делает код предсказуемым и независимым от внешних факторов, таких как настройки формы или механизмы БСП.
Иногда дубли возникают из-за того, что данные считываются в память еще до начала проведения. Проанализируем типичные причины, по которым движения могут быть «прочитаны» заранее:
Использовать всегда для коллекции движений. Если оно установлено, движения будут считываться платформой при любых манипуляциях с объектом.ПередЗаписью или ПриЗаписи в модулях форм. Иногда там могут присутствовать вызовы, которые явно или неявно обращаются к Движения.ИмяРегистра.Прочитать().Даже если в метаданных установлено свойство «Удаление движений» — «Удалять автоматически», это работает только в том случае, если платформе «очевидно», что она должна заменить старый набор новым. При работе в управляемых формах, особенно в сложных конфигурациях, где могут быть подключены механизмы БСП, контекст выполнения может быть нарушен. Если движения были считаны в память (например, для проверки прав или отображения в форме), платформа может «потерять» связь между объектом в памяти и его состоянием в базе данных, что приведет к добавлению новых записей поверх старых.
Чтобы понять, что происходит именно в вашем случае, воспользуйтесь отладчиком:
ОбработкаПроведения.Движения.ИмяРегистра.Количество().Движения.ИмяРегистра.Очистить() значение должно стать равным 0.Следуя этим простым шагам, вы сможете не только устранить ошибку дублирования, но и сделать архитектуру вашей конфигурации более стабильной и профессиональной.