Как в СКД рассчитать выручку по этапам строительства в 1С:Управление торговлей 11?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Промышленность, строительство и АПК
← На главную

В практике разработки на платформе 1С:Предприятие часто возникает задача распределения показателей (например, выручки, затрат или оплат) по определенным периодам, которые не кратны стандартным (месяц, квартал), а определяются записями в регистре сведений. Типичный пример — расчет выручки за каждый этап строительства, когда даты начала этапов хранятся в истории изменений, а данные о продажах — в регистрах накопления. Разберем подробно, как реализовать такой отчет в системе компоновки данных (СКД) для конфигурации "Управление торговлей 11".

Постановка задачи и анализ структуры данных

Рассмотрим исходные данные. У нас имеется регистр сведений ИсторияЭтаповСтроительства, в котором фиксируется дата начала каждого этапа для конкретного клиента. Нам необходимо сопоставить эти интервалы с данными регистра накопления ВыручкаИСебестоимостьПродаж. Основная сложность заключается в том, что в регистре сведений есть только дата начала этапа, а для получения оборотов за период нам нужна и дата окончания.

Проанализируем шаги, которые нам необходимо предпринять:

  1. Преобразовать список дат начала этапов в таблицу интервалов (Начало — Конец).
  2. Соединить полученные интервалы с данными о продажах.
  3. Настроить отчет в СКД для корректного отображения итогов.

Способ 1. Классический запрос с соединением таблицы самой с собой (Self-Join)

Если ваша платформа версии ниже 8.3.21, это основной способ получения даты окончания периода. Идея заключается в том, чтобы для каждой записи из регистра сведений найти "следующую" по времени запись для того же клиента. Дата следующей записи и будет являться датой окончания текущего этапа.

Рассмотрим структуру запроса подробнее:


ВЫБРАТЬ
    ЭтапыСлева.Клиент КАК Клиент,
    ЭтапыСлева.Этап КАК Этап,
    ЭтапыСлева.Период КАК ДатаНачала,
    МИНИМУМ(ЕСТЬNULL(ЭтапыСправа.Период, ДАТАВРЕМЯ(3999, 12, 31))) КАК ДатаОкончания
ПОМЕСТИТЬ ВТ_Интервалы
ИЗ
    РегистрСведений.ИсторияЭтаповСтроительства КАК ЭтапыСлева
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИсторияЭтаповСтроительства КАК ЭтапыСправа
        ПО ЭтапыСлева.Клиент = ЭтапыСправа.Клиент
            И ЭтапыСлева.Период < ЭтапыСправа.Период
СГРУППИРОВАТЬ ПО
    ЭтапыСлева.Клиент,
    ЭтапыСлева.Этап,
    ЭтапыСлева.Период
;

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

Разберем важные нюансы этого запроса. Во-первых, мы используем ЛЕВОЕ СОЕДИНЕНИЕ. Это критически важно для обработки последнего (текущего) этапа. Если использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ, то для последнего этапа не найдется записи "справа" (где дата больше), и текущий этап просто исчезнет из отчета. Во-вторых, функцией ЕСТЬNULL мы подставляем "дату конца времен" (31.12.3999) для текущего открытого этапа, чтобы захватить все продажи по сегодняшний день.

Способ 2. Использование оконных функций (Платформа 8.3.21+)

Если вы работаете на современной версии платформы, расчет интервалов можно значительно упростить и ускорить с помощью функции LEAD. Она позволяет заглянуть в следующую строку выборки без тяжелого соединения таблицы с самой собой.

Проанализируем пример использования оконной функции:


ВЫБРАТЬ
    История.Клиент,
    История.Этап,
    История.Период КАК ДатаНачала,
    LEAD(История.Период, 1, ДАТАВРЕМЯ(3999, 12, 31)) OVER (PARTITION ПО История.Клиент УПОРЯДОЧИТЬ ПО История.Период) КАК ДатаОкончания
ПОМЕСТИТЬ ВТ_Интервалы_Оконные
ИЗ
    РегистрСведений.ИсторияЭтаповСтроительства КАК История

Здесь PARTITION BY (в языке 1С — ПО) разделяет данные по клиентам, а ORDER BY (УПОРЯДОЧИТЬ ПО) гарантирует правильную последовательность этапов. Это решение работает гораздо быстрее на больших объемах данных, так как платформа выполняет обход таблицы один раз.

Способ 3. Связи наборов данных в СКД

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

Набор данных 1 (Запрос): Получает интервалы этапов (используя любой из способов выше).

Набор данных 2 (Запрос): Получает обороты из виртуальной таблицы ВыручкаИСебестоимостьПродаж.Обороты. В тексте запроса второго набора мы НЕ указываем период в параметрах виртуальной таблицы явно, либо используем стандартные параметры.

На закладке "Связи наборов данных" мы настраиваем связь:

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

Важные технические особенности УТ 11

При работе с регистром ВыручкаИСебестоимостьПродаж необходимо учитывать специфику типовой конфигурации:

1. Выбор валюты.

В регистре хранятся суммы в нескольких валютах: управленческого учета, регламентированного учета и валюте взаиморасчетов. Обязательно уточните у бизнес-аналитиков, какая именно сумма должна попадать в отчет (обычно это поле СуммаВыручки для управленческого учета).

2. Учет возвратов.

Регистр является оборотным, и возвраты в нем отражаются сторнирующими записями (уменьшают оборот). Однако, если возврат произошел в периоде, когда этап уже сменился, выручка уменьшится по новому этапу. Если это критично, необходимо анализировать первичные документы или связывать возвраты с документами продажи.

3. Аналитика "Заказ клиента" или "Договор".

Строительство часто ведется в рамках конкретного договора или заказа. Если у одного клиента несколько строек одновременно, простого соединения по полю Партнер будет недостаточно — вы соберете выручку "в одну кучу". В этом случае в регистр сведений "История этапов" и в условия соединения запроса обязательно нужно добавить разрез Договор или Заказ.

4. Оптимизация и индексация.

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

Резюме

Для реализации отчета по выручке за этапы строительства мы рассмотрели три подхода: от классического self-join до современных оконных функций и механизмов связей СКД. Наиболее эффективным для поддержки и расширения является метод с использованием связей наборов данных, так как он позволяет легко добавлять новые показатели из других регистров (например, оплаты или себестоимость), просто добавляя новые наборы данных и связывая их по тем же временным интервалам.

← На главную