Зачастую при автоматизации управленческого учета и бюджетирования возникает классическая задача: план продаж или закупок введен в систему помесячно (например, данные хранятся в оборотных регистрах накопления), а для оперативной работы и построения отчетов эти данные необходимо разбить на каждую неделю. Разберем по шагам, как можно решить эту задачу различными способами, используя функционал платформы 1С.
Самый базовый алгоритм, который мы проанализируем в первую очередь, заключается в вычислении «веса» одного дня и его умножении на количество дней в неделе. Если у нас есть план на месяц (допустим, 10 единиц в августе), мы можем разбить его пропорционально:
НачалоПериода, КонецПериода и РазностьДат).Рассмотрим пример расчета на цифрах. План на август — 10 единиц (в месяце 31 день). Если мы хотим узнать план на неделю из 5 рабочих дней, мы делим 10 на 31 и умножаем на 5. То есть формула выглядит так: 10 / 31 * 5.
Если мы хотим решить задачу более элегантно и привязаться к реальному календарю, воспользуемся соединением с таблицей дней. В современных конфигурациях отлично подходит регистр сведений ДанныеПроизводственногоКалендаря. Посмотрим на алгоритм:
НАЧАЛОПЕРИОДА(ДанныеКалендаря.ДатаКалендаря, НЕДЕЛЯ), которая автоматически приведет любой день к понедельнику соответствующей недели.Данный подход позволяет очень точно разбить период, при этом функция НАЧАЛОПЕРИОДА отработает корректно независимо от того, с какого дня начался месяц.
Проанализируем ситуацию, когда производственный календарь недоступен, пуст, или мы не хотим к нему привязываться. В этом случае мы можем сгенерировать даты математически прямо внутри запроса. Для этого создаются несколько временных таблиц, в которых через объединение задаются цифры от 0 до 9.
Перемножив эти таблицы перекрестным соединением (CROSS JOIN), мы получаем последовательность чисел от 0 до необходимого предела. Далее, используя функцию ДОБАВИТЬКДАТЕ(&ДатаНачала, ДЕНЬ, Число), мы получаем непрерывный набор дат. Полученный набор дней аналогичным образом сворачивается по неделям.
Рассмотрим еще один мощный штатный механизм платформы 1С — конструкцию ПЕРИОДАМИ. Это один из самых изящных способов получить непрерывную шкалу нужной периодичности.
В тексте запроса мы можем написать:
ИТОГИ ПО Период ПЕРИОДАМИ(НЕДЕЛЯ, &НачДата, &КонДата)
При обходе результата запроса (обязательно с использованием обхода по группировкам) система сама сгенерирует пустые строки для каждой недели в заданном диапазоне, даже если в исходных данных не было движений в этот период. Внутри цикла мы можем распределить месячный план по сгенерированным неделям.
При распределении данных по неделям мы неизбежно столкнемся с проблемой стыка месяцев. Неделя может начаться, например, 28 августа, а закончиться 3 сентября. Как быть в такой ситуации?
Выясним причину сложности: у нас есть данные за август и за сентябрь, и одна календарная неделя делит их между собой. Логика решения зависит от бизнес-требований:
В завершение разберем ситуацию, когда вам вообще не нужно писать код. В современных конфигурациях, таких как 1С:Управление торговлей, 1С:Комплексная автоматизация и 1С:ERP, подсистема планирования умеет делать такое распределение штатно.
Если вы настроите Сценарий планирования с периодичностью «Неделя», система позволит заполнять планы по данным источника с периодичностью «Месяц». При настройке правил заполнения можно указать профили распределения по дням или рабочим графикам. Платформа сама раскидает месячные суммы по неделям, избавив разработчика от необходимости конструировать сложные SQL-запросы вручную.