Почему движения документа не видны при проведении в рамках одной транзакции?

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

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

Разбор ситуации: почему данные «теряются»?

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

  1. Уровни изоляции транзакций: Хотя данные уже записаны в таблицы базы данных, они могут быть невидимы для новых запросов, если параметры запроса или уровни изоляции СУБД не позволяют «видеть» незавершенную транзакцию.
  2. Неверная граница периода: В 1С МоментВремени документа — это уникальный идентификатор. Если ваш запрос использует Границу с ВидГраницы.Исключая, то любые движения, имеющие дату и время текущего документа, будут отсечены. Это самая частая причина «исчезновения» движений в отчетах или запросах при проведении.
  3. Обращение к базе вместо памяти: Попытка прочитать данные через Ссылка.Объект или через запрос к СУБД в середине процесса проведения — это лишнее обращение к диску, которое замедляет систему и не гарантирует актуальность данных из-за кэширования объектов.

Способ решения №1: Правильная настройка параметров запроса

Если вам все же необходимо выполнить запрос, проверьте, как вы определяете временной интервал. Если используется метод УстановитьПараметр с Границей, обратите внимание на ВидГраницы.

Рассмотрим пример правильной установки параметров:


// Неправильный вариант (исключает движения текущего документа)
Запрос.УстановитьПараметр("Период", Новый Граница(Объект.МоментВремени(), ВидГраницы.Исключая));

// Правильный вариант (включает движения текущего документа)
Запрос.УстановитьПараметр("Период", Новый Граница(Объект.МоментВремени(), ВидГраницы.Включая));

Использование ВидГраницы.Включая позволит запросу «увидеть» движения, которые были записаны в этом же сеансе до выполнения выборки.

Способ решения №2: Работа с данными в оперативной памяти (рекомендуемый)

Наиболее эффективный подход в 1С — это отказ от чтения записанных движений из базы данных. Все необходимые для расчетов данные уже находятся у вас в памяти. Если процедура ФормированиеДругихДвижений требует данных, которые вы только что записали, передавайте в нее не Ссылку, а уже заполненную коллекцию движений или таблицу значений.

Рассмотрим, как это выглядит на практике:


// Вместо обращения к базе через ссылку:
// ФормированиеДругихДвижений(Ссылка); 

// Передаем данные, которые уже есть в контексте проведения:
ТаблицаДвижений = Движения.РегистрНакопления1.Выгрузить();
ФормированиеДругихДвижений(ТаблицаДвижений);

Почему это лучше:

Архитектурные советы по проведению документов

Чтобы избежать ошибок в будущем, придерживайтесь следующих правил:

  1. Рассчитывайте всё заранее: Старайтесь проводить все вычисления в оперативной памяти (используя ТаблицыЗначений, Структуры или Массивы) до того, как вы начнете записывать движения в базу.
  2. Соблюдайте последовательность: Если одни движения зависят от других, сначала сформируйте структуру всех движений, и только потом записывайте их в регистры.
  3. Избегайте Ссылка.Объект: Внутри процедуры ОбработкаПроведения у вас уже есть объект ЭтотОбъект. Обращение через Ссылка.Объект создает новый экземпляр объекта, который не будет содержать текущих, еще не записанных в базу изменений (движений). Всегда используйте ЭтотОбъект или просто Движения.
  4. Анализ движений: Если необходимо проанализировать движения, которые уже находятся в коллекции Движения, используйте метод Выгрузить(), чтобы получить ТаблицуЗначений. Это самый простой способ получить данные для дальнейших манипуляций.

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

← На главную