В нашей организации случился переход с Камин-5 на ЗУП. Как положено, перенесли начальные остатки. Старая кадровая история (кто и где работал), тоже нужна. Решили перенести в усечённом виде – перенесли Реестр кадровых приказов. Естественно Интервальные Кадровые сведения не восстанавливались. Теперь просмотреть «старые» кадровые движения по ссылке {Кадровые документы} было невозможно, отображались только документы, сделанные в ЗУП. Для просмотра кадровых перемещений за всю историю, приходилось формировать «Личную карточку (Т2)». При большом количестве ссылок на старые кадровые документы, это было крайне неудобно (происходило разбиение на листы).
Вторая проблемка заключалась в том, что существовали для одной должности несколько видов оплаты, и для поддержания в Камин-5 такой возможности приходилось создавать Дубликаты с таким же наименованием. Частично, по наименованию не различали должности с нормальными и вредными условиями труда… как следствие, интервалы в запросе строились для должностей по Наименованию (не по ссылке)
Имеющуюся потребность: сформировать отчет для вычисления стажа, пришлось реализовать отдельным отчетом. Поскольку, задача формирования истории стажа (вычисление стажа работы в разных должностях и подразделениях) показалась универсальной, то решил выделить получение таблицы стажа в отдельную функцию. Кроме того, штатный механизм ЗУП получение Стажа показался мне малость Тормознутым – нарисовал собственную функцию форматирования Стажа (общими функциями 1С8 вычисляется разность дат в годах, месяцах, днях). Штатным осталось только получение Представления форматированного размера интервала. На всякий случай сделал вариант обратного интервала, когда ДатаНачала > ДатаКонца.
Запрос стажа (Фрагмент получения Таблицы интервалов стажа):
Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ РКП.Организация КАК Организация,
| РКП.ФизическоеЛицо КАК ФизическоеЛицо,
| РКП.Сотрудник КАК Сотрудник,
| МАКСИМУМ(РКП.Подразделение) КАК Подразделение,
| МАКСИМУМ(РКП.Должность.Наименование) КАК Должность,
| РКП.Дата КАК ДатаС,
| МАКСИМУМ(РКП.Сотрудник.Код) КАК СотрудникКод,
| РКП.ВидСобытия КАК ВидСобытия
|ПОМЕСТИТЬ СпКП
|ИЗ РегистрСведений.РеестрКадровыхПриказов КАК РКП
|ГДЕ РКП.ВидСобытия <> ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) И РКП.ФизическоеЛицо = &ФизическоеЛицо
|
|СГРУППИРОВАТЬ ПО РКП.Организация, РКП.ФизическоеЛицо, РКП.Сотрудник, РКП.Дата, РКП.ВидСобытия
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ РеестрУв.Организация,
| РеестрУв.ФизическоеЛицо,
| РеестрУв.Сотрудник,
| ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка),
| """",
| ДОБАВИТЬКДАТЕ(РеестрУв.Дата, ДЕНЬ, 1),
| РеестрУв.Сотрудник.Код,
| РеестрУв.ВидСобытия
|ИЗ РегистрСведений.РеестрКадровыхПриказов КАК РеестрУв
|ГДЕ РеестрУв.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) И РеестрУв.ФизическоеЛицо = &ФизическоеЛицо
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ КИ.ГоловнаяОрганизация,
| КИ.ФизическоеЛицо,
| КИ.Сотрудник,
| ВЫБОР КОГДА КИ.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) ТОГДА ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) Иначе КИ.Подразделение Конец,
| ВЫБОР КОГДА КИ.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) ТОГДА """" Иначе КИ.Должность.Наименование Конец,
| ВЫБОР КОГДА КИ.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) ТОГДА ДОБАВИТЬКДАТЕ(КИ.Период, ДЕНЬ, 1) ИНАЧЕ КИ.Период
| КОНЕЦ,
| КИ.Сотрудник.Код,
| КИ.ВидСобытия
|ИЗ РегистрСведений.КадроваяИсторияСотрудников КАК КИ
|ГДЕ КИ.ФизическоеЛицо = &ФизическоеЛицо И КИ.ВидСобытия <> ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.НеподтвержденныеДанные)
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ ТекКС.ГоловнаяОрганизация,
| ТекКС.ФизическоеЛицо,
| ТекКС.Сотрудник,
| ВЫБОР КОГДА ТекКС.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) ТОГДА ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
| Иначе ТекКС.Подразделение Конец,
| ВЫБОР КОГДА ТекКС.ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение) ТОГДА """"
| Иначе ТекКС.Должность.Наименование Конец, КОНЕЦПЕРИОДА(&Текущая, ДЕНЬ),
| ТекКС.Сотрудник.Код,
| ТекКС.ВидСобытия
|ИЗ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(, ФизическоеЛицо = &ФизическоеЛицо) КАК ТекКС
|
|ИНДЕКСИРОВАТЬ ПО Организация, ФизическоеЛицо, Сотрудник, ДатаС
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ КП.Организация КАК Организация,
| КП.ФизическоеЛицо КАК ФизическоеЛицо,
| КП.Сотрудник КАК Сотрудник,
| КП.Подразделение КАК Подразделение,
| КП.Должность КАК Должность,
| КП.ДатаС КАК ДатаС,
| МИНИМУМ(КП.ДатаПо) КАК ДатаПо
|ПОМЕСТИТЬ Инт
|ИЗ
| (ВЫБРАТЬ СпКП.Организация КАК Организация,
| СпКП.ФизическоеЛицо КАК ФизическоеЛицо,
| СпКП.Сотрудник КАК Сотрудник,
| СпКП.Подразделение КАК Подразделение,
| СпКП.Должность КАК Должность,
| СпКП.ДатаС КАК ДатаС,
| ДОБАВИТЬКДАТЕ(Стало.ДатаС, ДЕНЬ, -1) КАК ДатаПо
| ИЗ
| СпКП КАК СпКП
| ЛЕВОЕ СОЕДИНЕНИЕ СпКП КАК Стало
| ПО СпКП.ФизическоеЛицо = Стало.ФизическоеЛицо И СпКП.ДатаС < Стало.ДатаС
| И (НЕ(СпКП.Подразделение = Стало.Подразделение И СпКП.Должность = Стало.Должность))) КАК КП
|
|СГРУППИРОВАТЬ ПО КП.Организация, КП.ФизическоеЛицо, КП.Сотрудник, КП.Подразделение, КП.Должность, КП.ДатаС
|
|ИНДЕКСИРОВАТЬ ПО ФизическоеЛицо, Сотрудник, ДатаС
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ Интрв.Организация КАК Организация,
| Интрв.ФизическоеЛицо КАК ФизическоеЛицо,
| Интрв.Сотрудник.Код КАК ТабН,
| Интрв.Сотрудник КАК Сотрудник,
| Интрв.Подразделение.Код КАК КодП,
| Интрв.Подразделение КАК Подразделение,
| Интрв.Должность КАК Должность,
| МИНИМУМ(Интрв.ДатаС) КАК НачДата,
| Интрв.ДатаПо КАК ДатаПо
|ИЗ Инт КАК Интрв
|ГДЕ Интрв.Подразделение <> ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
|
|СГРУППИРОВАТЬ ПО
| Интрв.ФизическоеЛицо,
| Интрв.Подразделение,
| Интрв.Должность,
| Интрв.ДатаПо,
| Интрв.Сотрудник,
| Интрв.Организация,
| Интрв.Сотрудник.Код,
| Интрв.Подразделение.Код
|
|УПОРЯДОЧИТЬ ПО ФизическоеЛицо, Сотрудник, НачДата
|";
Запрос.Параметры.Вставить("ФизическоеЛицо", ФизЛицо);
Запрос.Параметры.Вставить("Текущая", ТекущаяДата());
Функция форматирования интервала (ПолучитьРазмерИнтервалаВФормате(ДатаНач,ДатаКон)):
Функция ПолучитьРазмерИнтервалаВФормате(ДатаНач,ДатаКон) Экспорт
Результат = Новый Структура;
Если ЗначениеЗаполнено(ДатаКон) Тогда КонПериода = ДатаКон; Иначе КонПериода = ТекущаяДата(); КонецЕсли;
Если Час(КонПериода)<12 Тогда КонПериода = НачалоДня(КонПериода);
Иначе КонПериода = НачалоДня(КонецДня(КонПериода)+9);
КонецЕсли;
Результат.Вставить("ДатаНач",ДатаНач); Результат.Вставить("КонПериода",КонПериода);
Если Не ЗначениеЗаполнено(ДатаНач) Тогда
Результат.Вставить("Представление","Нет ДатаНач!");
Результат.Вставить("Лет",0); Результат.Вставить("Месяцев",0); Результат.Вставить("Дней",0);
ИначеЕсли КонПериода>ДатаНач Тогда
Результат.Вставить("Лет", Год(КонПериода)-Год(ДатаНач));
Результат.Вставить("Месяцев",Месяц(КонПериода)-Месяц(ДатаНач));
Если Час(КонПериода)<12 Тогда Результат.Вставить("Дней", День(КонПериода)-День(ДатаНач));
Иначе Результат.Вставить("Дней", День(КонПериода)-День(ДатаНач)+1);
КонецЕсли;
Если Результат.Дней<0 Тогда
Результат.Месяцев = Результат.Месяцев - 1;
Результат.Дней = Результат.Дней + День(КонецМесяца(НачалоМесяца(КонПериода)-9));
КонецЕсли;
Если Результат.Месяцев<0 Тогда
Результат.Лет = Результат.Лет - 1;
Результат.Месяцев = Результат.Месяцев + Месяц(КонецГода(НачалоГода(КонПериода)-9));
КонецЕсли;
Представление = ЗарплатаКадрыРасширенныйКлиентСервер.ПредставлениеСтажа(Результат.Лет, Результат.Месяцев, Результат.Дней);
Результат.Вставить("Представление",СокрЛП(Представление));
Иначе //Обратный Интервал
Результат.Вставить("Лет", Год(ДатаНач)-Год(КонПериода));
Результат.Вставить("Месяцев",Месяц(ДатаНач)-Месяц(КонПериода));
Результат.Вставить("Дней", День(ДатаНач)-День(КонПериода));
Если Результат.Дней<0 Тогда
Результат.Месяцев = Результат.Месяцев - 1;
Результат.Дней = Результат.Дней + День(КонецМесяца(НачалоМесяца(ДатаНач)-9));
КонецЕсли;
Если Результат.Месяцев<0 Тогда
Результат.Лет = Результат.Лет - 1;
Результат.Месяцев = Результат.Месяцев + Месяц(КонецГода(НачалоГода(ДатаНач)-9));
КонецЕсли;
Результат.Дней = -Результат.Дней; Результат.Месяцев = -Результат.Месяцев; Результат.Лет = -Результат.Лет;//Инверсия
Представление = ЗарплатаКадрыРасширенныйКлиентСервер.ПредставлениеСтажа(Результат.Лет, Результат.Месяцев, Результат.Дней);
Результат.Вставить("Представление","Минус "+СокрЛП(Представление));
КонецЕсли;
Возврат Результат;
КонецФункции//ПолучитьРазмерИнтервалаВФормате()
Универсальная функция получения таблицы кадровых перемещений и функция форматирования Интервала в формате Лет-Месяцев-Дней в моём случае лежит в расширении. В моём расширении Функция Получение Стажа – универсальна, стажи формируются с отбором по Сотруднику или по Физическому лицу. Запрос легко модифицируется (СтрЗаменить(Запрос.Текст, "ФизическоеЛицо = &ФизическоеЛицо", "Сотрудник = &ФизическоеЛицо")).
Во вложении лежит отчет, собранный для автономного использования (не требует Расширения). Подключается как обычная внешняя печатная форма, привязанная к Сотруднику. Если у Вас множество организаций, и требуется Справка по отдельной организации, то потребуется получить данные для отбора и поправить Функцию/Запрос отбором по Организации (желающие могут допилить).
Тестировалось в ЗУП Корп 3.1.38, но должно работать в других конфигурациях, включающих ЗУП: ЗУП 3.1; ЕРП 2.5; и др., использующие Регистры сведений "РеестрКадровыхПриказов" и "КадроваяИсторияСотрудников", по которым собирается Кадровая история.
Проверено на следующих конфигурациях и релизах:
- Зарплата и управление персоналом КОРП, редакция 3.1, релизы 3.1.38.18
Вступайте в нашу телеграмм-группу Инфостарт