При разработке механизмов, завязанных на расчеты дат (например, определение банковских дней, сроков оплаты или отгрузки в «Альфа-Авто» или «УПП»), программисты часто сталкиваются с искушением прописать праздничные дни и переносы выходных непосредственно в коде (так называемый «хардкод»). Однако такой подход крайне неэффективен: каждый год даты меняются, выходят новые постановления правительства, и код приходится переписывать вручную.
Рассмотрим, как устроена работа с производственным календарем в системе 1С:Предприятие 8, где физически хранятся эти данные и как правильно организовать программный доступ к ним, чтобы ваше решение оставалось актуальным без постоянного вмешательства в конфигуратор.
В конфигурации «Управление производственным предприятием» (УПП) основным хранилищем графиков работы и выходных дней является регистр сведений «Регламентированный производственный календарь». В отличие от современных решений на базе БСП (Библиотеки стандартных подсистем), где справочник ПроизводственныеКалендари позволяет создавать множество различных календарей (для разных стран или регионов), в классической УПП календарь, как правило, один и является общим для всей системы.
Проанализируем структуру этого регистра. Каждая запись в нем соответствует одной календарной дате года. Основной интерес для нас представляет ресурс ВидДня, который может принимать следующие значения:
Многие задаются вопросом: если данных в коде нет, то откуда они берутся в регистре? Выясним причину появления актуальных дат в вашей базе. В 1С:УПП существует несколько механизмов обновления этой информации:
Посмотрим на пример кода, который часто встречается в «самописных» функциях:
Праздники = Новый СписокЗначений;
Праздники.Добавить(Дата("20240101")); // Новый год
Праздники.Добавить(Дата("20240509")); // День Победы
Переносы = Новый СписокЗначений;
Переносы.Добавить(Дата("20240427")); // Рабочая суббота
Проанализируем ситуацию: логика разделения на праздники и переносы в коде обычно продиктована тем, что праздники имеют фиксированные даты (за редким исключением), а переносы (сгорание выходного в одном месте и появление его в другом) утверждаются правительством ежегодно.
Важный момент: Если суббота объявляется рабочей, она попадает в список исключений для алгоритма, который «по умолчанию» считает все субботы выходными. Если же понедельник становится выходным из-за переноса с субботы, он также становится исключением для алгоритма «будни — рабочие». Именно поэтому использование регистра сведений РегламентированныйПроизводственныйКалендарь снимает эту головную боль: там каждый день уже имеет свой конечный статус (рабочий или нерабочий).
Вместо того чтобы вручную перечислять даты в массивах, мы рекомендуем использовать запросы к регистру или встроенные функции общих модулей. Рассмотрим пример функции, которая проверяет, является ли дата рабочим днем, обращаясь к данным системы:
Функция ЭтоРабочийДень(ПроверяемаяДата) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Календарь.ВидДня
|ИЗ
| РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
|ГДЕ
| Календарь.Дата = &Дата";
Запрос.УстановитьПараметр("Дата", НачалоДня(ПроверяемаяДата));
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
// Если данных в календаре нет, используем стандартную логику (Сб, Вс - выходные)
ДеньНедели = ДеньНедели(ПроверяемаяДата);
Возврат (ДеньНедели < 6);
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Проверяем вид дня
Если Выборка.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Рабочий
ИЛИ Выборка.ВидДня = Перечисления.ВидыДнейПроизводственногоКалендаря.Предпраздничный Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Также во многих типовых конфигурациях (включая УПП) существуют встроенные функции в общих модулях, таких как ОбщегоНазначения или специализированные модули для расчета зарплаты. Например, функция ОпределитьДатуЗавершенияСрока позволяет вычислить дату через N рабочих дней, автоматически учитывая все праздники и переносы из регистра.
Подведем итоги нашего анализа:
РегистрСведений.РегламентированныйПроизводственныйКалендарь как единственный источник истины о рабочем времени.Использование штатных механизмов 1С позволит вашему коду быть гибким и надежным, а пользователям — самостоятельно управлять графиком работ без привлечения программиста для ежегодного обновления дат.