14.03.2016

1С Регламентированный производственный календарь

Порой, бывает крайне необходимо  получить информацию является ли тот или иной день рабочим. Мне, например, это требуется для выгрузки данных поставщикам. Так как, зачастую, в техническом задании говорится что-нибудь на вроде: "вы должны выгружать данные каждый первый рабочий день недели за предыдущую неделю и каждый первый рабочий день месяца за предыдущий месяц". Звучит, конечно странновато, но задание есть задание и не нам его оспаривать.
Итак, в УТ есть замечательный регистр сведений "РегламентированныйПроизводственныйКалендарь". Выглядит он примерно вот так:
Регламентированный производственный календарь

И этот регистр содержит
всю необходимую нам информацию.
Чтобы узнать является ли день началом периода накидаем небольшой запрос:

Функция ДатаЯвляетсяНачаломПериода(лДата,лПериод)
лЗапрос = Новый Запрос();
лЗапрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
|    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря
|ПОМЕСТИТЬ ВТ_РабочиеДниМесяца
|ИЗ
|    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК |РегламентированныйПроизводственныйКалендарь
|ГДЕ
|    РегламентированныйПроизводственныйКалендарь.ВидДня = |ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
|    И РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ |НАЧАЛОПЕРИОДА(&Дата,"+лПериод+") И КОНЕЦПЕРИОДА(&Дата, "+лПериод+")
|;
|   |///////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|    ВЫБОР
|        КОГДА ВТ_РабочиеДниМесяца.ДатаКалендаря = &Дата
|            ТОГДА ИСТИНА
|        ИНАЧЕ ЛОЖЬ
|    КОНЕЦ КАК РабочаяДатаЯвляетсяНачаломМесяца
|ИЗ
|    ВТ_РабочиеДниМесяца КАК ВТ_РабочиеДниМесяца
|;
|
|///////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТ_РабочиеДниМесяца";
лЗапрос.УстановитьПараметр("Дата",НачалоДня(лДата));
лВыборка = лЗапрос.Выполнить().Выбрать();
Если лВыборка.Следующий() Тогда
Возврат лВыборка.РабочаяДатаЯвляетсяНачаломМесяца;
КонецЕсли;
Возврат Ложь;
КонецФункции

Собственно, в функцию мы передаем дату и тип периода, началом которого дата должна являться. В начале организуем временную таблицу, в которую берем первую рабочую дату между началом и концом периода. Отбор по рабочей дате осуществляем по виду дня, равному ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий). лПериод - сюда входит одно из следующих значений: Год, Квартал, Месяц, Неделя, День, Час, Секунда. Соответственно, если переданный в параметр &Дата день, равен первому рабочему дню из выбранного периода, то запрос выдаст истину. Т.е. все что нам остается, это передавать каждый божий день в параметр &Дата и смотреть какой результат вернет запрос. В конце запроса мы уничтожаем временную таблицу, чтобы она не висела у нас в оперативной памяти.
Ниже листинг который можно записать, например, в регламентное задание и запускать его каждый день:


лТекущаяДата = НачалоДня(ТекущаяДата());
лНомерДняНедели = ДеньНедели(лТекущаяДата);
лНомерДняМесяца = День(лТекущаяДата);
лНачалоПериода = Неопределено;
лКонецПериода = Неопределено;
Если ДатаЯвляетсяНачаломПериода(лТекущаяДата,"НЕДЕЛЯ") Тогда
лНачалоПериода = НачалоНедели(лТекущаяДата-лНомерДняНедели*24*59*59);
лКонецПериода = КонецНедели(лТекущаяДата-лНомерДняНедели*24*59*59);
КонецЕсли;
Если ДатаЯвляетсяНачаломПериода(лТекущаяДата,"МЕСЯЦ") Тогда
лНачалоПериода = НачалоМесяца(лТекущаяДата-лНомерДняМесяца*24*59*59);
лКонецПериода = КонецМесяца(лТекущаяДата-лНомерДняМесяца*24*59*59);
КонецЕсли;
Если лНачалоПериода <> Неопределено И лКонецПериода <> Неопределено Тогда
//делаем выгрузку
КонецЕсли;
Тут видим, что если день является началом выбранного периода, то мы задаем две переменные начала и конца периода, которые потом можно использовать для выгрузки. Если же день не рабочий, или не является началом периода, то эти переменные останутся неопределенными и основной блок кода по выгрузке не будет выполнен, т.е. регламентное задание завершится практически моментально и не сильно затруднит систему. Еще момент, в качестве переменной лТекущаяДата берем начало дня, т.к. НАЧАЛОПЕРИОДА в запросе по неделям и месяцам возвращает дату с нулевым временем.

Комментариев нет:

Отправить комментарий