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