При автоматизации бизнес-процессов часто возникает задача расчета плановых дат: например, определить срок выполнения заказа, учитывая только рабочие дни и исключая выходные и праздники. Давайте разберемся, как реализовать механизм добавления произвольного количества рабочих дней к заданной дате, используя данные регистра сведений ПроизводственныйКалендарь.
Основная сложность заключается в том, что календарные дни не равны рабочим. Мы не можем просто использовать функцию ДобавитьМесяц или арифметическое прибавление дней, так как система должна «перепрыгивать» через субботы, воскресенья и государственные праздники. Для решения этой задачи мы будем использовать встроенный регистр сведений, который хранит информацию о статусе каждого дня в году.
Самым надежным и распространенным способом является выполнение запроса к регистру, который содержит сведения о днях производственного календаря. В типовых конфигурациях этот регистр обычно называется ДанныеПроизводственногоКалендаря.
Рассмотрим алгоритм действий по шагам:
ПЕРВЫЕ.Посмотрим на пример кода, который позволяет получить массив рабочих дней за указанный период:
Функция ПолучитьРабочиеДни(НачалоПериода, КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецПериода);
Запрос.УстановитьПараметр("ПроизводственныйКалендарь", Справочники.ПроизводственныеКалендари.НайтиПоКоду("РФ"));
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеПроизводственногоКалендаря.Дата КАК Дата
|ИЗ
| РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеПроизводственногоКалендаря
|ГДЕ
| ДанныеПроизводственногоКалендаря.ПроизводственныйКалендарь = &ПроизводственныйКалендарь
| И ДанныеПроизводственногоКалендаря.Дата МЕЖДУ &НачалоПериода И &КонецПериода
| И ДанныеПроизводственногоКалендаря.ВидДня В (ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий),
| ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
|УПОРЯДОЧИТЬ ПО
| Дата";
Результат = Запрос.Выполнить();
Возврат Результат.Выгрузить().ВыгрузитьКолонку("Дата");
КонецФункции
Если вам нужно получить конкретную дату, прибавив X рабочих дней, можно использовать более лаконичный вариант запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ &КоличествоДней
| К.Дата
|ПОМЕСТИТЬ ВТ_Дни
|ИЗ
| РегистрСведений.ДанныеПроизводственногоКалендаря КАК К
|ГДЕ
| К.Дата > &НачальнаяДата
| И К.ВидДня В (ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий), ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
|УПОРЯДОЧИТЬ ПО
| К.Дата;
|
|ВЫБРАТЬ МАКСИМУМ(ВТ.Дата) ИЗ ВТ_Дни КАК ВТ";
При реализации данного функционала обратите внимание на следующие рекомендации:
Рабочий день — это не только тип Булево. Современные конфигурации используют перечисления, где важно учитывать и предпраздничные дни, так как они зачастую также являются рабочими.X). Это нужно для того, чтобы в выборку гарантированно попало нужное число рабочих дней с учетом всех попадающих праздников и выходных.Использование предложенных методов позволит вам точно рассчитывать сроки выполнения задач и корректно работать с производственным календарем в любой конфигурации 1С.