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