Почему не записываются движения документа в 1С и как это исправить?

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

В процессе разработки новых документов в системе «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда программный код в процедуре ОбработкаПроведения написан верно, отладчик показывает, что коллекции движений заполняются данными, но после завершения транзакции регистры остаются пустыми. Это классическая проблема, связанная с пониманием того, как платформа взаимодействует с базой данных и как управляет записью наборов записей.

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

Причина 1: Флаг программной записи набора записей

Самая распространенная причина заключается в том, что платформа 1С не записывает все наборы записей подряд по умолчанию. Для каждого регистра, по которому документ совершает движения, существует свойство Записывать. Если в коде это свойство не установлено в значение Истина, платформа «проигнорирует» подготовленные в памяти данные и не отправит их в СУБД.

Проанализируем пример кода, который решает эту проблему. Допустим, наш регистр называется ОстаткиТоваров. Рассмотрим правильную структуру заполнения:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // 1. Указываем платформе, что этот набор записей нужно будет записать в БД
    Движения.ОстаткиТоваров.Записывать = Истина;
    
    // 2. Формируем само движение
    Движение = Движения.ОстаткиТоваров.Добавить();
    Движение.Период = Дата;
    Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
    Движение.Номенклатура = СсылкаНаТовар;
    Движение.Количество = 10;
    
КонецПроцедуры

Важно понимать: установка Движения.ИмяРегистра.Записывать = Истина не выполняет мгновенную запись. Она лишь «помечает» набор записей как требующий сохранения. Физическая запись произойдет автоматически в конце процедуры проведения, но строго до того, как транзакция будет зафиксирована (Commit).

Причина 2: Свойство документа «Запись движений» в конфигураторе

Многие разработчики задаются вопросом: «Почему в одной базе движения записываются без явного указания флага в коде, а в другой — нет?». Ответ кроется в настройках самого объекта метаданных. Разберем свойства документа на вкладке «Движения» в конфигураторе.

Найдем свойство «Запись движений». Оно может принимать два значения:

  1. Записывать выбранные: В этом режиме платформа записывает только те регистры, у которых в коде явно прописано Записывать = Истина. Это рекомендуемый режим для повышения производительности, так как система не делает лишних действий.
  2. Записывать модифицированные: В этом случае платформа сама анализирует, менялся ли набор записей в ходе выполнения кода. Если вы добавили хотя бы одну строку в Движения.ИмяРегистра, флаг записи установится автоматически. Именно поэтому в некоторых конфигурациях «старый код» может работать без дополнительных команд.

Проанализируем ситуацию: если вы перенесли код из документа с режимом «Записывать модифицированные» в документ с режимом «Записывать выбранные», то движения перестанут сохраняться до тех пор, пока вы не добавите соответствующую строчку кода.

Причина 3: Избыточное использование метода Записать()

В некоторых сообщениях на форумах можно встретить совет использовать команду Движения.Записать() или Движения.ИмяРегистра.Записать() прямо внутри обработки проведения. Рассмотрим, почему это часто бывает лишним и даже вредным.

В процедуре ОбработкаПроведения платформа уже открыла транзакцию. Если вы вызываете Движения.Записать() вручную:

Помните: Платформа 1С:Предприятие 8 спроектирована так, чтобы записывать все помеченные наборы самостоятельно по окончании процедуры проведения. Использовать явный метод Записать() стоит только в специфических случаях, например, если вам нужно прочитать только что записанные данные из базы в этой же транзакции (что само по себе является спорным архитектурным решением).

Причина 4: Свойство «Удаление движений»

Выясним, как настройки удаления влияют на результат. У документа есть свойство «Удаление движений». Рассмотрим его варианты:

  1. Удалять автоматически: Перед началом проведения платформа сама очищает все движения документа по всем регистрам. Если в коде проведения возникнет ошибка, старые движения уже удалены, а новые не записаны — в итоге документ станет «пустым» по движениям.
  2. Не удалять автоматически: Платформа не трогает старые записи. Это требует от программиста ручного управления очисткой. Если вы просто добавите новые строки к существующим (не очистив набор и не установив флаг записи), вы можете получить дублирование или «кашу» в данных.

Влияние Библиотеки стандартных подсистем (БСП)

Если вы работаете в современной типовой конфигурации (например, БП 3.0 или УТ 11), вы заметите, что там часто используется механизм БСП для проведения. В таких системах запись часто происходит не напрямую, а через дополнительные инструменты:

Проанализируем механизм: в конце обработки проведения может вызываться общая процедура, которая перебирает коллекцию Движения и на основании определенных бизнес-правил (или наличия данных в ДополнительныеСвойства) проставляет флаги Записывать = Истина.

Если вы копируете только «тело» цикла формирования движений, но забываете про механизмы регистрации этих движений в структурах БСП, автоматика не сработает.

Как гарантированно очистить движения?

Иногда задача стоит наоборот: нужно, чтобы документ при определенных условиях «стер» свои движения. Простого вызова Движения.ИмяРегистра.Очистить() недостаточно. Рассмотрим правильный алгоритм:


Если УсловиеОтмены Тогда
    Движения.ОстаткиТоваров.Очистить();
    Движения.ОстаткиТоваров.Записывать = Истина;
КонецЕсли;

Только в таком случае платформа поймет: «Ага, флаг записи стоит, а коллекция пустая. Значит, мне нужно пойти в базу данных и удалить все записи, привязанные к этому регистратору».

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

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

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

Соблюдение этих простых правил азбуки разработчика 1С избавит вас от проблем с «исчезающими» движениями и обеспечит стабильную работу системы.

← На главную