Как рассчитать среднее число продаж за последние три месяца в 1С

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

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

Разбор основной задачи

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

Проектирование запроса к регистру продаж

Первое, на что стоит обратить внимание — это правильное обращение к виртуальной таблице ПродажиОбороты. Опытные разработчики знают, что получение всех оборотов с последующей фильтрацией в секции ГДЕ — это ошибка, приводящая к падению производительности. Разберем, как правильно передать параметры.

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


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    ПродажиОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(
        ДОБАВИТЬКДАТЕ(&ДатаКонца, МЕСЯЦ, -3),
        &ДатаКонца,
        ,
    ) КАК ПродажиОбороты

Важно понимать разницу между "тремя месяцами" и "кварталом". Как справедливо отмечено в обсуждении, если мы укажем периодичность КВАРТАЛ, система может разбить данные по календарным интервалам (например, отдельно за 4-й квартал прошлого года и 1-й квартал текущего), что не даст нам нужной суммы для деления. Нам нужен именно скользящий период.

Связь документа с регистром и обработка NULL

При соединении документа с регистром продаж мы используем ЛЕВОЕ СОЕДИНЕНИЕ. Это критически важно, так как по товару в заказе могло не быть продаж вовсе, но он все равно должен остаться в списке. Однако левое соединение порождает значения NULL там, где данных в регистре нет.

Рассмотрим пример правильного соединения и обработки пустых значений:


ВЫБРАТЬ
    ВнутреннийЗаказТовары.Номенклатура КАК Номенклатура,
    ВнутреннийЗаказТовары.Количество КАК Заказано,
    ЕСТЬNULL(ПродажиОбороты.КоличествоОборот, 0) / 3 КАК СреднееЗа3Месяца
ИЗ
    Документ.ВнутреннийЗаказ.Товары КАК ВнутреннийЗаказТовары
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
        ПО ВнутреннийЗаказТовары.Номенклатура = ПродажиОбороты.Номенклатура
ГДЕ
    ВнутреннийЗаказТовары.Ссылка = &Ссылка

Обратите внимание на функцию ЕСТЬNULL. Без неё любая попытка поделить пустое значение на 3 приведет к тому, что в колонке среднего значения будет пустота, что некорректно с точки зрения пользователя.

Оптимизация: использование временных таблиц

Если в документе ВнутреннийЗаказ содержится большое количество строк, прямое соединение с виртуальной таблицей может замедлить работу. Проанализируем более профессиональный подход — использование временных таблиц:

  1. Сначала мы выбираем все уникальные товары из конкретного документа во временную таблицу ВТ_ТоварыЗаказа.
  2. Затем мы обращаемся к регистру Продажи.Обороты, устанавливая в параметрах виртуальной таблицы отбор по номенклатуре из нашей временной таблицы.
  3. В финальном запросе соединяем подготовленные данные.

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

Настройка параметров в Системе компоновки данных (СКД)

Чтобы отчет работал динамически от текущей даты без принудительного ввода параметров пользователем, выясним, как настроить выражения в СКД. Перейдем на закладку "Параметры" и для ДатаКонца укажем выражение ТекущаяДата().

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

ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&КонецПериода, "МЕСЯЦ"), "МЕСЯЦ", -2)

Такой подход позволит избежать ситуации, когда расчет идет от середины текущего месяца, что может искажать "среднее" значение из-за неполного периода.

Нюансы точности и округления

При делении количества на 3 мы почти всегда будем получать дробное число. Для корректного отображения в запросе можно использовать функцию ВЫРАЗИТЬ, например: ВЫРАЗИТЬ(Результат КАК ЧИСЛО(15, 2)).

Однако в СКД рекомендуется другой способ. Выясним причину: если мы округлим значение прямо в запросе, то при расчете общих итогов по группировкам может возникнуть погрешность округления. Лучше оставить число в первозданном виде, а на вкладке "Наборы данных" или "Оформление" в поле "Оформление" задать форматную строку ЧЦ=15; ЧДЦ=2. Это обеспечит визуальную точность без потери данных для расчетов.

Учет дефицита товара (Out-of-stock)

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

Для продвинутого решения задачи рекомендуется анализировать не просто обороты продаж, но и остатки на каждый день периода. Если КоличествоОстаток был равен 0, этот день не должен участвовать в расчете "среднего", так как продаж не могло быть физически. Это превращает задачу из простого деления на 3 в расчет "средних продаж в дни наличия товара".

Итоги реализации

Мы разберем по шагам итоговый алгоритм создания механизма:

  1. Создаем запрос к табличной части Товары документа ВнутреннийЗаказ.
  2. Присоединяем ПродажиОбороты по полю Номенклатура.
  3. Обязательно используем ЕСТЬNULL для обработки отсутствующих продаж.
  4. В параметрах виртуальной таблицы ограничиваем период с помощью ДОБАВИТЬКДАТЕ.
  5. В СКД настраиваем автоматическое заполнение дат через выражения ТекущаяДата().
  6. Настраиваем формат вывода числа через свойства поля компоновки.

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

← На главную