Получение нормы времени между двумя датами из Производственного календаря

06.05.20

Разработка - Универсальные функции

Понадобилось для решения задачи автоматизировать ручной расчет сверхурочных часов по очень "замудренной" формуле, в которой нужно получить норму времени между двумя определенными датами из Производственного календаря.

Была поставлена задача автоматизировать ручной расчет сверхурочных часов по очень "замудренной" формуле, в которой нужно получить норму времени между двумя определенными датами из Производственного календаря.

 

 

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

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

Писал под свою конкретную задачу, возможно еще кому-нибудь пригодится. Камнями прошу сильно не кидаться, я самоучка, а не профессионал. Если у кого есть более "правильный" и компактный вариант, можете поделиться, буду рад.

Тестировалась на платформе 8.3.17, релиз 3.1.13.151, но думаю, что будет работать на любом релизе.

Получить норму времени из Производственного календаря.

См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    20124    dimanich70    81    

144

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    4091    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    18059    atdonya    24    

56

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    5502    ke.92@mail.ru    16    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14730    YA_418728146    7    

166

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3580    56    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18478    171    sapervodichka    112    

135
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. vkozak 07.05.20 14:49 Сейчас в теме
Забавно. Буду решать подобную задачу воспользуюсь идеей.
2. ivnik 595 07.05.20 18:46 Сейчас в теме
(1) Когда мне что-то нравиться, я обычно ставлю Плюсик и сохраняю в "Избранное", чтобы когда понадобиться, не долго искать.
3. pepper62 12.05.20 13:11 Сейчас в теме
Вот Вам немножко типового функционала с двумя вариантами. В "бою" используется первый.


&НаСервере
Функция ПолучитьНормуФактВремени(ТаблицаСотрудников, МесяцПолучения)

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


&НаСервере
Функция ПолучитьВТСотрудники(ТаблицаСотрудников)
	МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
	
	МассивСотрудников = ТаблицаСотрудников.ВыгрузитьКолонку("Сотрудник");
	
	
	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|    ТаблицаСотрудники.Сотрудник,
	|    ТаблицаСотрудники.Месяц,
	|    ТаблицаСотрудники.ДатаАктуальности,        
	|    ТаблицаСотрудники.ДатаНачала,
	|    ТаблицаСотрудники.ДатаОкончания
	|ПОМЕСТИТЬ ВТСотрудники
	|ИЗ
	|    &ТаблицаСотрудники КАК ТаблицаСотрудники");
	
	Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
	Запрос.УстановитьПараметр("ТаблицаСотрудники", ТаблицаСотрудников);
	Запрос.Выполнить();
	
	Возврат МенеджерВременныхТаблиц;
КонецФункции
Показать
Dziden; user_2010; +2 Ответить
4. ivnik 595 12.05.20 14:02 Сейчас в теме
(3) Большое Спасибо!!! Очень интересный вариант.
5. charivnick 46 09.03.22 13:18 Сейчас в теме
Все хорошо, только норма рассчитанная через УчетРабочегоВремениРасширенный, не обязательно будет соответствовать норме по
производственному календарю. Поэтому пока вариант расчета нормы, предложенный автором, единственный.
6. kvikster 87 08.04.22 23:46 Сейчас в теме
Возможно кому-то потребуются сумма часов за период:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеПроизводственногоКалендаря.ПроизводственныйКалендарь КАК ПроизводственныйКалендарь,
| СУММА(1) КАК КалендарныхДней,
| СУММА(ВЫБОР
| КОГДА ДанныеПроизводственногоКалендаря.ВидДня В (ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий), ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
| ТОГДА 1
| ИНАЧЕ 0
| КОНЕЦ) КАК РабочихДней,
| СУММА(ВЫБОР
| КОГДА ДанныеПроизводственногоКалендаря.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
| ТОГДА &Часов / 5
| КОГДА ДанныеПроизводственногоКалендаря.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный)
| ТОГДА &Часов / 5 - 1
| ИНАЧЕ 0
| КОНЕЦ) КАК РабочихЧасовДлительностьНедели
|ИЗ
| РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеПроизводственногоКалендаря
|ГДЕ
| ДанныеПроизводственногоКалендаря.Дата >= &ДатаНачала
| И ДанныеПроизводственногоКалендаря.Дата <= &ДатаОкончания
| И ДанныеПроизводственногоКалендаря.ПроизводственныйКалендарь = &ПроизводственныйКалендарь
|
|СГРУППИРОВАТЬ ПО
| ДанныеПроизводственногоКалендаря.ПроизводственныйКалендарь
|
|УПОРЯДОЧИТЬ ПО
| ПроизводственныйКалендарь";

Запрос.УстановитьПараметр("Часов", ?(ДлительностьРабочейНедели>0,ДлительностьРабочейНедели,40));
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Запрос.УстановитьПараметр("ПроизводственныйКалендарь", Объект.Календарь);

РезультатЗапроса = Запрос.Выполнить();

ВДЗ = РезультатЗапроса.Выбрать();

Пока ВДЗ.Следующий() Цикл
ТС.НормаПоКалендарю = ВДЗ.РабочихЧасовДлительностьНедели;
КонецЦикла;
Оставьте свое сообщение