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