Как получить срез последних на дату каждого документа и разбить период расчета при изменении ставки в 1С?

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

При разработке отчетов и механизмов расчета задолженности или пени часто возникает необходимость получить значение из независимого периодического регистра сведений (например, ставку рефинансирования ЦБ) на дату конкретного документа. Особенность виртуальной таблицы СрезПоследних заключается в том, что в качестве параметра &Период нельзя напрямую передать поле из другой таблицы запроса (например, Документ.Дата).

Рассмотрим подробнее два основных вопроса: как корректно получить срез последних для каждой строки в запросе или СКД и как разбить интервал расчета задолженности, если ставка изменилась в середине периода.

Способ 1. Получение среза последних на каждую дату через временные таблицы в языке запросов

Поскольку параметр виртуальной таблицы СрезПоследних принимает только фиксированное значение или параметр запроса, получить срез последних напрямую для произвольного списка дат в одном простом обращении к виртуальной таблице невозможно. Чтобы решить эту задачу одним запросом, разберем стандартный алгоритм работы с реальной таблицей регистра сведений.

  1. Соединение документов с реальной таблицей регистра. Сформируем временную таблицу документов и свяжем её с физической таблицей регистра сведений по условию РегистрСведений.Период <= Документ.Дата.
  2. Поиск максимального периода. Сгруппируем полученные данные по регистратору и найдем МАКСИМУМ(РегистрСведений.Период). Это и будет дата последней актуальной записи регистра на момент проведения документа.
  3. Получение итоговых значений. Соединим таблицу с максимальными датами обратно с регистрами сведений для извлечения ресурсов (например, значения ставки).

Проанализируем пример запроса:


ВЫБРАТЬ
    Документы.Ссылка КАК Документ,
    Документы.Дата КАК ДатаДокумента
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документы
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Документы.Документ КАК Документ,
    ВТ_Документы.ДатаДокумента КАК ДатаДокумента,
    МАКСИМУМ(Ставки.Период) КАК ПериодСтавки
ПОМЕСТИТЬ ВТ_МаксимальныеДаты
ИЗ
    ВТ_Документы КАК ВТ_Документы
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтавкаРефинансированияЦБ КАК Ставки
        ПО Ставки.Период <= ВТ_Документы.ДатаДокумента
ГРУППИРОВАТЬ ПО
    ВТ_Документы.Документ,
    ВТ_Документы.ДатаДокумента
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Документ КАК Документ,
    ВТ.ДатаДокумента КАК ДатаДокумента,
    Ставки.Размер КАК СтавкаРефинансирования
ИЗ
    ВТ_МаксимальныеДаты КАК ВТ
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтавкаРефинансированияЦБ КАК Ставки
        ПО ВТ.ПериодСтавки = Ставки.Период

Способ 2. Использование связей наборов данных в СКД

В Схеме компоновки данных (СКД) эта задача решается значительно проще и изящнее без использования тяжелых соединений. Система позволяет передавать поле из главного набора данных в параметры подчиненного набора данных.

Разберем по шагам порядок настройки СКД:

  1. Создадим Набор данных - запрос (Главный набор), который получает список документов или операций с их датами.
  2. Создадим второй Набор данных - запрос (Подчиненный набор), содержащий обращение к виртуальной таблице регистра:
    
    ВЫБРАТЬ
        СтавкиРефинансированияСрезПоследних.Размер КАК Размер,
        &Дата КАК дДата
    ИЗ
        РегистрСведений.СтавкаРефинансированияЦБ.СрезПоследних(&Дата, ) КАК СтавкиРефинансированияСрезПоследних
    
  3. Перейдем на вкладку Связи наборов данных. Добавим связь:
    • Источник связи: ГлавныйНабор
    • Приемник связи: ПодчиненныйНабор
    • Условие связи: совпадение ключевых полей (если требуются дополнительные измерения)
    • Параметры: указываем параметр Период, а в колонке Выражение источника задаем поле Дата из главного набора.

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

Разбиение периода расчета при изменении ставки в середине интервала

Рассмотрим усложнение задачи: ставка рефинансирования изменилась в середине периода начисления долга/пени (например, с 1 января ставка выросла). В этом случае одна исходная строка расчета должна разбиться на два интервала: до даты смены ставки и после нее.

Для решения данной задачи применяются следующие подходы:

  1. Построение интервальной таблицы регистра сведений:

    С помощью запроса к регистру сведений формируется интервальная таблица, в которой для каждой записи о ставке определяются границы ДатаНачала и ДатаОкончания. Исходный период задолженности связывается с интервалами ставок по условию пересечения дат. Если ставка менялась внутри периода, запрос вернет несколько строк, в каждой из которых с помощью условий ВЫБОР рассчитываются точные границы подпериода и количество дней действия конкретной ставки.

  2. Подекадный или ежедневный расчет (расчет на каждый день):

    Практический опыт разработки расчетов пени и процентов показывает, что при часто изменяющихся ставках или частичных оплатах наиболее устойчивым является расчет "на каждый день". Период разбивается на отдельные календарные дни, для каждого из которых извлекается текущий остаток долга и действующая на этот день ставка ЦБ. Затем полученные ежедневные строки с одинаковыми параметрами сгруппировываются обратно в неразрывные интервалы.

← На главную