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

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

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

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

Рассмотрим ситуацию: у нас есть документ, который фиксирует общий объем продаж номенклатуры за весь месяц (например, 1-го числа каждого месяца). Нам необходимо «разбить» это количество по неделям года. Основная трудность заключается в том, что неделя не всегда укладывается в рамки одного календарного месяца. Наша цель — рассчитать средние продажи в день и корректно суммировать их для каждой недели, учитывая долю дней, приходящуюся на разные месяцы.

Алгоритм решения через временные таблицы в запросе

Рассмотрим пошагово, как реализовать этот расчет программно в тексте запроса. Этот метод основан на соединении данных документа с календарем.

Шаг 1. Формирование временной таблицы календарных дней.

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


ВЫБРАТЬ
    Календарь.Дата КАК ДеньПланов,
    НАЧАЛОПЕРИОДА(Календарь.Дата, МЕСЯЦ) КАК МесяцКалендаря,
    НАЧАЛОПЕРИОДА(Календарь.Дата, НЕДЕЛЯ) КАК НеделяКалендаря
ПОМЕСТИТЬ ВТ_Календарь
ИЗ
    РегистрСведений.ДанныеПроизводственногоКалендаря КАК Календарь
ГДЕ
    Календарь.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
;

Шаг 2. Расчет среднедневных продаж в месяце.

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


ВЫБРАТЬ
    Док.Номенклатура КАК Номенклатура,
    НАЧАЛОПЕРИОДА(Док.Дата, МЕСЯЦ) КАК ПериодМесяц,
    Док.Количество / РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(Док.Дата, МЕСЯЦ), КОНЕЦПЕРИОДА(Док.Дата, МЕСЯЦ), ДЕНЬ) + 1 КАК ПродажаВДень
ПОМЕСТИТЬ ВТ_ПродажиСредние
ИЗ
    Документ.ПродажиЗаМесяц.Состав КАК Док
ГДЕ
    Док.Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
;

Шаг 3. Соединение дней с продажами и финальная группировка.

Теперь мы соединяем каждый день из ВТ_Календарь с рассчитанными средними значениями из ВТ_ПродажиСредние. Связующим звеном выступает начало месяца. После соединения мы группируем результат по полю НеделяКалендаря и суммируем среднедневные показатели.


ВЫБРАТЬ
    Календарь.НеделяКалендаря КАК ПериодНеделя,
    Продажи.Номенклатура КАК Номенклатура,
    СУММА(Продажи.ПродажаВДень) КАК КоличествоЗаНеделю
ИЗ
    ВТ_Календарь КАК Календарь
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ПродажиСредние КАК Продажи
    ПО Календарь.МесяцКалендаря = Продажи.ПериодМесяц
СГРУППИРОВАТЬ ПО
    Календарь.НеделяКалендаря,
    Продажи.Номенклатура
;

Этот подход автоматически решает проблему «стыковых» недель. Если неделя захватывает три дня января и четыре дня февраля, запрос возьмет 3 раза «среднедневное за январь» и 4 раза «среднедневное за февраль» и объединит их в одной группировке по неделе.

Оптимизация: учет рабочих дней

В реальном бизнесе продажи часто распределяются неравномерно. Если компания не работает по выходным, логичнее распределять месячный объем только по рабочим дням. Выясним, как изменить запрос для этого случая. При расчете ПродажаВДень во втором шаге нужно делить не на общее количество дней в месяце, а на количество записей в календаре с видом Рабочий. При соединении в третьем шаге также следует добавить фильтр ГДЕ Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий).

Решение через Систему компоновки данных (СКД)

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

Методика работы в СКД:

  1. Добавим в запрос поля НАЧАЛОПЕРИОДА(Дата, НЕДЕЛЯ) и НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ).
  2. В настройках СКД на закладке «Роли» для поля периода укажем соответствующий тип (День, Неделя или Месяц).
  3. Используем функции ВычислитьВыражение для обращения к иерархии периодов. Это позволит системе автоматически агрегировать данные.

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

Технические нюансы и «подводные камни»

Проанализируем несколько важных моментов, которые могут повлиять на результат:

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

← На главную