Как запросом получить недельные данные из месячных записей в 1С?

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

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

Математическое пропорциональное распределение

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

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

Рассмотрим пример расчета на цифрах. План на август — 10 единиц (в месяце 31 день). Если мы хотим узнать план на неделю из 5 рабочих дней, мы делим 10 на 31 и умножаем на 5. То есть формула выглядит так: 10 / 31 * 5.

Использование таблицы производственного календаря

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

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

Данный подход позволяет очень точно разбить период, при этом функция НАЧАЛОПЕРИОДА отработает корректно независимо от того, с какого дня начался месяц.

Генерация дат через виртуальную таблицу

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

Перемножив эти таблицы перекрестным соединением (CROSS JOIN), мы получаем последовательность чисел от 0 до необходимого предела. Далее, используя функцию ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, Число), мы получаем непрерывный набор дат. Полученный набор дней аналогичным образом сворачивается по неделям.

Использование итогов с дополнением периодов

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

В тексте запроса мы можем написать:

ИТОГИ ПО Период ПЕРИОДАМИ(НЕДЕЛЯ, &НачДата, &КонДата)

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

Как обрабатывать стыки месяцев («рваные» недели)?

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

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

  1. Дробление недели: Неделя искусственно разбивается на два периода. Первая строка: с 28.08 по 31.08 (берет пропорцию от августовского плана). Вторая строка: с 01.09 по 03.09 (берет пропорцию от сентябрьского плана).
  2. Слияние весов: Неделя остается единой. Сумма плана за эту неделю складывается из веса дней августа плюс вес дней сентября.

Использование типовых подсистем (ERP, КА, УТ 11)

В завершение разберем ситуацию, когда вам вообще не нужно писать код. В современных конфигурациях, таких как 1С:Управление торговлей, 1С:Комплексная автоматизация и 1С:ERP, подсистема планирования умеет делать такое распределение штатно.

Если вы настроите Сценарий планирования с периодичностью «Неделя», система позволит заполнять планы по данным источника с периодичностью «Месяц». При настройке правил заполнения можно указать профили распределения по дням или рабочим графикам. Платформа сама раскидает месячные суммы по неделям, избавив разработчика от необходимости конструировать сложные SQL-запросы вручную.

← На главную