В работе кадрового отдела часто возникают ситуации, когда пересекаются периоды отпусков, командировок или болезней.
Например, больничный сотрудника 11.05 - 20.05. Но вводится кадровый отпуск отпуск с 18.05.
При этом рассчетчики, формируя документы через АнализНеявок, получают неверные данные: больничный создается с 11.05 по 17.05.
Чтобы избежать подобных проблем, предлагаю контроль пересечений кадровых отклонений, найденные пересечения сообщаются пользователю. Реализовано это подпиской на события "Обработка проведения" документов "ОтпускаОрганизаций", "НеявкиИБолезниОрганизаций", и "КомандировкиОрганизаций".
Ниже код, который желательно поместить в отдельный модуль и в подписке на события выбрать процедуру "ОбработкаПроведенияКонтрольПересеченияНеявкиИБолезни()".
Процедура ОбработкаПроведенияКонтрольПересеченияНеявкиИБолезни(Источник,Отказ, Режим) Экспорт
Если ТипЗнч(Источник) = тип("ДокументОбъект.НеявкиИБолезниОрганизаций") Тогда
//если несколько строк в ТЧ, то нужно фиктивно нарисовать им дату окончания
ТЧ=источник.РаботникиОрганизации.Выгрузить();
ТЧ.Сортировать("Сотрудник,ДатаНачала");
НайденоОкончание=Ложь;
ПоследнийП=ТЧ.Количество()-1;
Для п=0 по ПоследнийП Цикл
Сотрудник=ТЧ[п].Сотрудник;
Если п<>ПоследнийП и ТЧ[п].Сотрудник=ТЧ[п+1].Сотрудник Тогда
НайденоОкончание=Истина;
Если ТЧ.Колонки.Найти("ДатаОкончания")=неопределено Тогда
ТЧ.Колонки.Добавить("ДатаОкончания",новый ОписаниеТипов("Дата"));
КонецЕсли;
ТЧ[п].ДатаОкончания=ТЧ[п+1].ДатаНачала-86400;
КонецЕсли;
п=п+1;
КонецЦикла;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТЧ",ТЧ);
Запрос.УстановитьПараметр("ПричинаОтсутствияРаботает",Перечисления.СостоянияРаботникаОрганизации.Работает);
//если есть фиктивная дата окончания
Если НайденоОкончание Тогда
//КОНТРОЛЬ ОШИБОК С ДАТОЙ ЗАВЕРШЕНИЯ
Запрос.Текст = ПолучитьТекстЗапросаДляСостоянияСДатойОкончания();
СообщитьПользователюКонфликтыСДатойОкончания(Запрос);
//удаляем строки с датой завершения
п=0;
пока п < ТЧ.Количество() Цикл
Если ЗначениеЗаполнено(ТЧ[п].ДатаОкончания) Тогда
ТЧ.Удалить(п);
Иначе
п=п+1;
КонецЕсли;
КонецЦикла;
//КОНТРОЛЬ ОШИБОК БЕЗ ДАТЫ ЗАВЕРШЕНИЯ
Запрос.Текст = вернутьТекстЗапросаДляСостоянияБезДатыОкончания();
СообщитьПользователюКонфликтыБезДатыОкончания(Запрос);
Иначе //нет фиктивной даты окончания
//КОНТРОЛЬ ОШИБОК БЕЗ ДАТЫ ЗАВЕРШЕНИЯ
Запрос.Текст = вернутьТекстЗапросаДляСостоянияБезДатыОкончания();
СообщитьПользователюКонфликтыБезДатыОкончания(Запрос);
КонецЕсли;
ИначеЕсли ТипЗнч(Источник) = тип("ДокументОбъект.ОтпускаОрганизаций") Тогда
//КОНТРОЛЬ ОШИБОК С ДАТОЙ ЗАВЕРШЕНИЯ
Запрос = Новый Запрос;
Запрос.Текст = ПолучитьТекстЗапросаДляСостоянияСДатойОкончания();
Запрос.УстановитьПараметр("ТЧ",источник.РаботникиОрганизации);
Запрос.УстановитьПараметр("ПричинаОтсутствияРаботает",Перечисления.СостоянияРаботникаОрганизации.Работает);
Запрос.УстановитьПараметр("СостояниеКомандировка",Перечисления.СостоянияРаботникаОрганизации.ОтпускЕжегодный);
СообщитьПользователюКонфликтыСДатойОкончания(Запрос);
ИначеЕсли ТипЗнч(Источник) = тип("ДокументОбъект.КомандировкиОрганизаций") Тогда
//запрос с указанной датой окончания
Запрос = Новый Запрос;
//причина отсутствия у этого документа - командировка
ТЗ=источник.РаботникиОрганизации.Выгрузить();
ТЗ.Колонки.Добавить("ПричинаОтсутствия",новый ОписаниеТипов("ПеречислениеСсылка.СостоянияРаботникаОрганизации"));
ТЗ.ЗаполнитьЗначения(Перечисления.СостоянияРаботникаОрганизации, "ПричинаОтсутствия");
Запрос.УстановитьПараметр("ТЧ",ТЗ);
Запрос.УстановитьПараметр("ПричинаОтсутствияРаботает",Перечисления.СостоянияРаботникаОрганизации.Работает);
//КОНТРОЛЬ ОШИБОК С ДАТОЙ ЗАВЕРШЕНИЯ
Запрос.Текст = ПолучитьТекстЗапросаДляСостоянияСДатойОкончания();
СообщитьПользователюКонфликтыСДатойОкончания(Запрос);
//КОНТРОЛЬ ОШИБОК БЕЗ ДАТЫ ЗАВЕРШЕНИЯ
//удаляем строки с датой завершения
п=0;
пока п < ТЗ.Количество() Цикл
Если ЗначениеЗаполнено(ТЗ[п].ДатаОкончания) Тогда
ТЗ.Удалить(п);
Иначе
п=п+1;
КонецЕсли;
КонецЦикла;
Запрос.Текст = вернутьТекстЗапросаДляСостоянияБезДатыОкончания();
СообщитьПользователюКонфликтыБезДатыОкончания(Запрос);
КонецЕсли;
КонецПроцедуры
Функция вернутьТекстЗапросаДляСостоянияБезДатыОкончания()
Возврат
"ВЫБРАТЬ
| ТЧ.Сотрудник КАК Сотрудник,
| ТЧ.ПричинаОтсутствия КАК ПричинаОтсутствия,
| ТЧ.ДатаНачала КАК ДатаНачала
|ПОМЕСТИТЬ Таблица
|ИЗ
| &ТЧ КАК ТЧ
|;
|
| X
|ВЫБРАТЬ
| МАКСИМУМ(СостояниеРаботниковОрганизаций.Период) КАК Период,
| Таблица.Сотрудник
|ПОМЕСТИТЬ ПериодыСвязи
|ИЗ
| Таблица КАК Таблица
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботниковОрганизаций КАК СостояниеРаботниковОрганизаций
| ПО Таблица.Сотрудник = СостояниеРаботниковОрганизаций.Сотрудник
| И Таблица.ДатаНачала >= СостояниеРаботниковОрганизаций.Период
|ГДЕ
| Таблица.ПричинаОтсутствия <> &ПричинаОтсутствияРаботает
|
|СГРУППИРОВАТЬ ПО
| Таблица.Сотрудник
|;
|
| X
|ВЫБРАТЬ
| МИНИМУМ(СостояниеРаботниковОрганизаций.Период) КАК Период,
| Таблица.Сотрудник
|ПОМЕСТИТЬ ПериодыСвязиПосле
|ИЗ
| Таблица КАК Таблица
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботниковОрганизаций КАК СостояниеРаботниковОрганизаций
| ПО Таблица.Сотрудник = СостояниеРаботниковОрганизаций.Сотрудник
| И Таблица.ДатаНачала &ПричинаОтсутствияРаботает
|
|СГРУППИРОВАТЬ ПО
| Таблица.Сотрудник
|;
|
| X
|ВЫБРАТЬ
| Таблица.Сотрудник,
| Таблица.ПричинаОтсутствия КАК НовоеСостояние,
| ЕСТЬNULL(ВЫБОР
| КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения &ПричинаОтсутствияРаботает
|;
|
| X
|ВЫБРАТЬ
| Таблица.Сотрудник,
| Таблица.ПричинаОтсутствия КАК НовоеСостояние,
| СостояниеРаботниковОрганизаций.Состояние КАК ТекущееСостояние,
| СостояниеРаботниковОрганизаций.Регистратор,
| СостояниеРаботниковОрганизаций.Период,
| Таблица.ДатаНачала
|ИЗ
| Таблица КАК Таблица
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПериодыСвязиПосле КАК ПериодыСвязиПосле
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботниковОрганизаций КАК СостояниеРаботниковОрганизаций
| ПО ПериодыСвязиПосле.Сотрудник = СостояниеРаботниковОрганизаций.Сотрудник
| И ПериодыСвязиПосле.Период = СостояниеРаботниковОрганизаций.Период
| ПО Таблица.Сотрудник = ПериодыСвязиПосле.Сотрудник
|ГДЕ
| СостояниеРаботниковОрганизаций.Состояние <> &ПричинаОтсутствияРаботает"
КонецФункции
Функция ПолучитьТекстЗапросаДляСостоянияСДатойОкончания()
Возврат "ВЫБРАТЬ
| ТЧ.Сотрудник КАК Сотрудник,
| ТЧ.ДатаНачала КАК ДатаНачала,
| ТЧ.ДатаОкончания,
| ТЧ.ПричинаОтсутствия КАК НовоеСостояние
|ПОМЕСТИТЬ ТаблицаТЧ
|ИЗ
| &ТЧ КАК ТЧ
|ГДЕ
| ТЧ.ДатаОкончания <> ДАТАВРЕМЯ(1, 1, 1)
|;
|
| X
|ВЫБРАТЬ
| МАКСИМУМ(СостояниеРаботниковОрганизаций.Период) КАК Период,
| ТаблицаТЧ.Сотрудник
|ПОМЕСТИТЬ ПериодыСвязи
|ИЗ
| ТаблицаТЧ КАК ТаблицаТЧ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботниковОрганизаций КАК СостояниеРаботниковОрганизаций
| ПО ТаблицаТЧ.Сотрудник = СостояниеРаботниковОрганизаций.Сотрудник
| И ТаблицаТЧ.ДатаНачала >= СостояниеРаботниковОрганизаций.Период
|ГДЕ
| ТаблицаТЧ.НовоеСостояние <> &ПричинаОтсутствияРаботает
|
|СГРУППИРОВАТЬ ПО
| ТаблицаТЧ.Сотрудник
|;
|
| X
|ВЫБРАТЬ
| ТаблицаТЧ.Сотрудник,
| ЕСТЬNULL(ВЫБОР
| КОГДА СостояниеРаботниковОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения ДАТАВРЕМЯ(1, 1, 1)
| И СостояниеРаботниковОрганизаций.ПериодЗавершения &ПричинаОтсутствияРаботает
|;
|
| X
|ВЫБРАТЬ
| НаНачало.Сотрудник,
| НаНачало.ТекущееСостояние,
| НаНачало.ДатаНачала,
| НаНачало.НовоеСостояние,
| НаНачало.ДатаТекущегоСостояния,
| НаНачало.ДатаСледующегоИзменениСостояния,
| НаНачало.ДатаОкончания,
| НаНачало.Регистратор
|ИЗ
| НаНачало КАК НаНачало
|;
|
| X
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТаблицаТЧ.Сотрудник КАК Сотрудник,
| СостояниеРаботниковОрганизаций.Состояние КАК ТекущееСостояние,
| ТаблицаТЧ.ДатаНачала КАК ДатаНачала,
| ТаблицаТЧ.НовоеСостояние КАК НовоеСостояние,
| СостояниеРаботниковОрганизаций.Период КАК ДатаИзменения,
| ТаблицаТЧ.ДатаОкончания КАК ДатаОкончания,
| СостояниеРаботниковОрганизаций.Регистратор
|ИЗ
| ТаблицаТЧ КАК ТаблицаТЧ
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботниковОрганизаций КАК СостояниеРаботниковОрганизаций
| ПО ТаблицаТЧ.Сотрудник = СостояниеРаботниковОрганизаций.Сотрудник
| И (СостояниеРаботниковОрганизаций.Период >= ТаблицаТЧ.ДатаНачала)
| И (СостояниеРаботниковОрганизаций.Период = НаНачало.ДатаНачала
| И НаНачало.ДатаСледующегоИзменениСостояния &ПричинаОтсутствияРаботает";
КонецФункции
Процедура СообщитьПользователюКонфликтыБезДатыОкончания(Запрос)
Результат = Запрос.ВыполнитьПакет();
ВыборкаНаНачало = Результат[3].Выбрать();
Пока ВыборкаНаНачало.Следующий() Цикл
Сообщить("Внимание! "+ВыборкаНаНачало.Сотрудник+" из состояния """+ВыборкаНаНачало.ТекущееСостояние+" ("+Формат(ВыборкаНаНачало.Период,"ДФ=dd.MM.yyyy")+")"" переходт в состояние """+ВыборкаНаНачало.НовоеСостояние+"("+Формат(ВыборкаНаНачало.ДатаНачала,"ДФ=dd.MM.yyyy")+")"" (документ "+ВыборкаНаНачало.Регистратор+")");
КонецЦикла;
ВыборкаПосле = Результат[4].Выбрать();
Пока ВыборкаПосле.Следующий() Цикл
Сообщить("Внимание! "+ВыборкаПосле.Сотрудник+" : состояние """+ВыборкаПосле.НовоеСостояние+" ("+Формат(ВыборкаПосле.ДатаНачала,"ДФ=dd.MM.yyyy")+")"" будет изменено на """+ВыборкаПосле.ТекущееСостояние+" ("+Формат(ВыборкаПосле.Период,"ДФ=dd.MM.yyyy")+")"" (документ "+ВыборкаПосле.Регистратор+")");
КонецЦикла;
КонецПроцедуры
Процедура СообщитьПользователюКонфликтыСДатойОкончания(Запрос)
Результат = Запрос.ВыполнитьПакет();
ВыборкаНаНачало = Результат[3].Выбрать();
Пока ВыборкаНаНачало.Следующий() Цикл
Сообщить("Внимание! "+ВыборкаНаНачало.Сотрудник+" из состояния """+ВыборкаНаНачало.ТекущееСостояние+"("+Формат(ВыборкаНаНачало.ДатаТекущегоСостояния,"ДФ=dd.MM.yyyy")+")"" переходт в состояние """+ВыборкаНаНачало.НовоеСостояние+" ("+Формат(ВыборкаНаНачало.ДатаНачала,"ДФ=dd.MM.yyyy")+")"" (документ "+ВыборкаНаНачало.Регистратор+")");
КонецЦикла;
ВыборкаВМомент = Результат[4].Выбрать();
Пока ВыборкаВМомент.Следующий() Цикл
Сообщить("Внимание! "+ВыборкаВМомент.Сотрудник+" "+Формат(ВыборкаВМомент.ДатаИзменения,"ДФ=dd.MM.yyyy")+" переходт в состояние """+ВыборкаВМомент.ТекущееСостояние+""" (документ "+ВыборкаВМомент.Регистратор+")");
КонецЦикла;
КонецПроцедуры