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