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

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

При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с задачей: вывести список документов за произвольный период и для каждой строки документа «подтянуть» справочную информацию (например, цену), актуальную именно на момент совершения операции. Основная сложность здесь заключается в том, что виртуальная таблица СрезПоследних работает на одну конкретную дату, а нам нужно получить значения на разные даты для каждой строки. Разберем, как правильно реализовать этот механизм и избежать пустых результатов при незаполненном периоде.

Анализ проблемы: почему отчет получается пустым

Рассмотрим ситуацию, когда автор пытается использовать стандартный параметр &Период в условии ГДЕ. Если пользователь на форме отчета снимает галочку с параметра периода, система 1С по умолчанию подставляет в него пустую дату (01.01.0001), что можно увидеть через консоль запросов. В результате условие в запросе принимает вид Дата МЕЖДУ '00010101' И '00010101'. Разумеется, ни один проведенный документ в такой диапазон не попадает, и отчет выходит пустым.

Для решения этой проблемы проанализируем расширение языка запросов СКД. Чтобы сделать параметр действительно необязательным, мы должны использовать фигурные скобки {}. Это дает инструкции компоновщику макета: если параметр не задан пользователем, соответствующее условие должно быть полностью исключено из итогового SQL-запроса (по такому же принципу работают отборы по шаблону).

Пример корректного оформления условия в запросе:


ВЫБРАТЬ
    Реализация.Ссылка КАК Ссылка,
    Реализация.Дата КАК Дата,
    Реализация.СуммаДокумента КАК Сумма
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
{ГДЕ
    (Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания)}

Методическая ошибка: СрезПоследних в левом соединении

В попытках упростить отчет программисты часто пытаются соединить таблицу документов с виртуальной таблицей РегистрСведений.ЦеныНоменклатуры.СрезПоследних() в рамках одного запроса. Проанализируем, почему это не работает для получения цен на дату каждого документа.

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

Попытки добавить условие связи Реализация.Дата >= Цены.Период в соединении с виртуальной таблицей также не дадут результата, так как виртуальная таблица уже «схлопнула» данные до актуальных на текущий момент, и история цен внутри неё недоступна.

Правильное решение: Связь наборов данных через параметры

Рассмотрим самый эффективный и «чистый» способ решения задачи в СКД — использование двух наборов данных и механизма связей. Этот метод позволяет для каждой строки первого набора (документы) выполнять отдельный микро-запрос ко второму набору (цены) с подстановкой даты конкретной строки.

Шаг 1. Создаем Набор данных 1 (Запрос)

Выбираем данные из документов. Обязательно включаем поля Номенклатура, Характеристика и Дата.


ВЫБРАТЬ
    ТЧ.Ссылка КАК Документ,
    ТЧ.Ссылка.Дата КАК ДатаДокумента,
    ТЧ.Номенклатура КАК Номенклатура,
    ТЧ.Характеристика КАК Характеристика,
    ТЧ.Количество КАК Количество,
    ТЧ.Сумма КАК СуммаПродажи
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
{ГДЕ
    (ТЧ.Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания)}

Шаг 2. Создаем Набор данных 2 (Запрос)

Этот запрос будет получать цену. Важно: в параметрах виртуальной таблицы указываем параметр &ПериодЦен.


ВЫБРАТЬ
    Цены.Цена КАК ЦенаИзРегистра,
    Цены.Номенклатура КАК НоменклатураСрез,
    Цены.Характеристика КАК ХарактеристикаСрез
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ПериодЦен, {ВидЦены = &ВидЦены}) КАК Цены

Шаг 3. Настройка связи наборов данных

Переходим на закладку «Связи наборов данных». Это ключевой этап. Настроим связь следующим образом:

  1. Источник связи: Набор1.
  2. Приемник связи: Набор2.
  3. Условие связи: Номенклатура = НоменклатураСрез и Характеристика = ХарактеристикаСрез.
  4. Параметры: В колонке «Параметр» для связи выбираем ПериодЦен, а в колонке «Выражение источника» указываем ДатаДокумента.

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

Нюансы работы со временем и границей

Разберем важную техническую деталь. Если документ «Реализация» и документ «Установка цен номенклатуры» имеют одинаковый момент времени (вплоть до секунды), обычный срез последних может не увидеть новую цену. Выясним причину: по умолчанию срез последних работает по принципу «меньше или равно», но при совпадении позиций в секунде могут возникать коллизии.

Чтобы гарантированно получить цену, которая должна действовать на момент документа, в выражении связи наборов данных рекомендуется использовать небольшое смещение. Вместо просто ДатаДокумента можно написать:

ДОБАВИТЬКДАТЕ(ДатаДокумента, "СЕКУНДА", 1)

Это позволит системе «заглянуть» на одну секунду вперед и точно захватить цену, установленную в ту же секунду, что и документ.

Оптимизация работы с параметрами

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

Для основных параметров &ДатаНачала и &ДатаОкончания, если они используются внутри фигурных скобок {}, важно убедиться, что они доступны для редактирования и включены в пользовательские настройки.

Рассмотрим также использование СтандартныйПериод. Часто удобнее создать один параметр типа СтандартныйПериод, а в запросе обращаться к его границам:


{ГДЕ
    (Реализация.Дата МЕЖДУ &ПериодОтчета.ДатаНачала И &ПериодОтчета.ДатаОкончания)}

Итоги и рекомендации

Подведем итог нашему разбору. Для создания качественного отчета по ценам на дату реализации необходимо:

  1. Использовать два набора данных, связанных через параметры.
  2. Оборачивать условия по датам в фигурные скобки для обеспечения необязательности фильтров.
  3. Передавать Дату документа в параметр виртуальной таблицы СрезПоследних через механизм связей СКД.
  4. Скрывать технические параметры от пользователя для чистоты интерфейса.

Следуя этим правилам, мы получим гибкий, быстрый и методически верный отчет, который корректно отражает данные как за конкретный период, так и за всю историю ведения учета.

← На главную