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