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