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