Профессия — 1С

Рукопашный бой Карташ

Категории

История изменения реквизита за период

рубрики: Периодические запросы | Дата: 7 Апрель, 2014

Это вторая статья на тему периодических запросов в ЗУП. Рассмотрим пример, когда нам надо получить историю изменения должности сотрудников за какой-то период. Это может быть и история изменения подразделения и комбинация изменения должности с подразделением.




Принцип один и тот же. Но рассмотрим на примере должности. То есть в итоговой таблице после выполнения запроса у нас будут следующие поля: Сотрудник, ДатаНачала, ДатаОкончания, Должность. Соответственно будут заданы и два параметра: &НачалоПериода и &КонецПериода в рамках которых мы и будем анализировать изменение должностей. Заврос будем строить по регистру сведений РаботникиОрганизаций. Напомню, что в этом регистре есть ресурс ПериодЗавершения. То есть в кадровых документах есть возможность указывать и дату завершения действия данного приказа. Так в приеме на работу можно указать дату окончания, после которой сотрудник будет считаться уволенным. И эта дата окончания записывается именно в реквизит ПериодЗавершения. То же самое и с кадровыми перемещениями — если указана дата окончания, то после нее сотрудник считается вернувшимся на предыдущую должность в предыдущее подразделение. В то же самое время все эти кадровые движение есть возможность делать без указания даты окончания, т.е. просто использовать два разных кадровых документа вместо одного. Сразу оговорюсь, что в рамках данной статьи буду рассматривать ситуацию когда в кадровых документах дата окончания не указыватеся. Это значительно упростит запрос, хотя общий принцип останется тот же.

План будет такой. Сначала находим даты начала работ на новой должности каждого сотрудника, затем даты окончания, а затем присоединим даты окончания к датам начала. На первый взгляд все просто. Вообще на самом деле это общий план для всех периодических запросов где речь идет о получении в разрезе сотрудника истории изменения каких-либо реквизитов. Сначала получаем даты начала, затем даты окончания и наконец соединяем их в единую таблицу. Просто в зависимости от задачи трудоемкость получения этих дат может изменяться.

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




  1. Первое, что приходит в голову — это получить срез последних на &НачалоПериода с условием что причина изменения состояния не равно увольнение, т.е. посмотреть какую же должность занимал сотрудник на &НачалоПериода. Вот текст запроса:

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

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

    
    ВЫБРАТЬ
    	КадровоеПеремещениеПредыдущийПериод.Период,
    	КадровоеПеремещениеПредыдущийПериод.Сотрудник,
    	КадровоеПеремещениеПредыдущийПериод.Должность
    ИЗ
    	(ВЫБРАТЬ
    		РаботникиОрганизаций.Период КАК Период,
    		РаботникиОрганизаций.Сотрудник КАК Сотрудник,
    		РаботникиОрганизаций.Должность КАК Должность,
    		МАКСИМУМ(РаботникиОрганизацийПредыдущая.Период) КАК ПериодМаксимум
    	ИЗ
    		РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
    			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизацийПредыдущая
    			ПО РаботникиОрганизаций.Сотрудник = РаботникиОрганизацийПредыдущая.Сотрудник
    				И РаботникиОрганизаций.Период > РаботникиОрганизацийПредыдущая.Период
    	ГДЕ
    		РаботникиОрганизаций.ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Перемещение)
    		И РаботникиОрганизаций.Период МЕЖДУ &НачалоПериода И &КонецПериода
    	
    	СГРУППИРОВАТЬ ПО
    		РаботникиОрганизаций.Период,
    		РаботникиОрганизаций.Сотрудник,
    		РаботникиОрганизаций.Должность) КАК КадровоеПеремещениеПредыдущийПериод
    		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
    		ПО КадровоеПеремещениеПредыдущийПериод.ПериодМаксимум = РаботникиОрганизаций.Период
    			И КадровоеПеремещениеПредыдущийПериод.Сотрудник = РаботникиОрганизаций.Сотрудник
    ГДЕ
    	КадровоеПеремещениеПредыдущийПериод.Должность <> РаботникиОрганизаций.Должность
    

Ну а теперь объединим все три запроса в один и поместим во временную таблицу.


ВЫБРАТЬ
	&НачалоПериода,
	РаботникиОрганизацийСрезПоследних.Сотрудник,
	РаботникиОрганизацийСрезПоследних.Должность
ПОМЕСТИТЬ ВТ_ДатыНачала
ИЗ
	РегистрСведений.РаботникиОрганизаций.СрезПоследних(&НачалоПериода, ) КАК РаботникиОрганизацийСрезПоследних
ГДЕ
	РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния <> ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Увольнение)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	РаботникиОрганизаций.Период,
	РаботникиОрганизаций.Сотрудник,
	РаботникиОрганизаций.Должность
ИЗ
	РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
ГДЕ
	РаботникиОрганизаций.Период МЕЖДУ &НачалоПериода И &КонецПериода
	И РаботникиОрганизаций.ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.ПриемНаРаботу)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	КадровоеПеремещениеПредыдущийПериод.Период,
	КадровоеПеремещениеПредыдущийПериод.Сотрудник,
	КадровоеПеремещениеПредыдущийПериод.Должность
ИЗ
	(ВЫБРАТЬ
		РаботникиОрганизаций.Период КАК Период,
		РаботникиОрганизаций.Сотрудник КАК Сотрудник,
		РаботникиОрганизаций.Должность КАК Должность,
		МАКСИМУМ(РаботникиОрганизацийПредыдущая.Период) КАК ПериодМаксимум
	ИЗ
		РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизацийПредыдущая
			ПО РаботникиОрганизаций.Сотрудник = РаботникиОрганизацийПредыдущая.Сотрудник
				И РаботникиОрганизаций.Период > РаботникиОрганизацийПредыдущая.Период
	ГДЕ
		РаботникиОрганизаций.ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Перемещение)
		И РаботникиОрганизаций.Период МЕЖДУ &НачалоПериода И &КонецПериода
	
	СГРУППИРОВАТЬ ПО
		РаботникиОрганизаций.Период,
		РаботникиОрганизаций.Сотрудник,
		РаботникиОрганизаций.Должность) КАК КадровоеПеремещениеПредыдущийПериод
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
		ПО КадровоеПеремещениеПредыдущийПериод.ПериодМаксимум = РаботникиОрганизаций.Период
			И КадровоеПеремещениеПредыдущийПериод.Сотрудник = РаботникиОрганизаций.Сотрудник
ГДЕ
	КадровоеПеремещениеПредыдущийПериод.Должность <> РаботникиОрганизаций.Должность

Теперь займемся датами окончания. Также рассмотрим все варианты.

  1. Естественно работа на должности заканчивается в момент увольнения. Соответственно дату окончания можно получить из записи регистра с причиной изменения состояния увольнение. Здесь есть один маленький ньюанс. При увольнении в поле Период регистра сведений РаботникиОрганизаций записывается дата следующая за последним днем работы, т.е. дата с которой сотрудник уже не работает в организации. Следовательно нам необходимо будет вычесть один день из периода.

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

    
    ВЫБРАТЬ
    	ДОБАВИТЬКДАТЕ(КадровоеПеремещениеПредыдущийПериод.Период, ДЕНЬ, -1) КАК ДатаОкончания,
    	КадровоеПеремещениеПредыдущийПериод.Сотрудник
    ИЗ
    	(ВЫБРАТЬ
    		РаботникиОрганизаций.Период КАК Период,
    		РаботникиОрганизаций.Сотрудник КАК Сотрудник,
    		РаботникиОрганизаций.Должность КАК Должность,
    		МАКСИМУМ(РаботникиОрганизацийПредыдущая.Период) КАК ПериодМаксимум
    	ИЗ
    		РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
    			ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизацийПредыдущая
    			ПО РаботникиОрганизаций.Сотрудник = РаботникиОрганизацийПредыдущая.Сотрудник
    				И РаботникиОрганизаций.Период > РаботникиОрганизацийПредыдущая.Период
    	ГДЕ
    		РаботникиОрганизаций.ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Перемещение)
    		И ДОБАВИТЬКДАТЕ(РаботникиОрганизаций.Период, ДЕНЬ, -1) МЕЖДУ &НачалоПериода И &КонецПериода
    	
    	СГРУППИРОВАТЬ ПО
    		РаботникиОрганизаций.Период,
    		РаботникиОрганизаций.Сотрудник,
    		РаботникиОрганизаций.Должность) КАК КадровоеПеремещениеПредыдущийПериод
    		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
    		ПО КадровоеПеремещениеПредыдущийПериод.ПериодМаксимум = РаботникиОрганизаций.Период
    			И КадровоеПеремещениеПредыдущийПериод.Сотрудник = РаботникиОрганизаций.Сотрудник
    ГДЕ
    	КадровоеПеремещениеПредыдущийПериод.Должность <> РаботникиОрганизаций.Должность
    

Объединим два запроса по датам окончания и поместим результат во временную таблицу ВТ_ДатыОкончания. Далее присоединим даты окончания к датам начала. Причем внутри нашего периода может быть несколько периодов окончания, поэтому берем дату окончания ближайшую к дате начала. Делаем это с использованием группировки. Если дата окончания не найдена, то считаем датой окончания &КонецПериода. В общем вот итоговый текст запроса.


ВЫБРАТЬ
	&НачалоПериода КАК ДатаНачала,
	РаботникиОрганизацийСрезПоследних.Сотрудник,
	РаботникиОрганизацийСрезПоследних.Должность
ПОМЕСТИТЬ ВТ_ДатыНачала
ИЗ
	РегистрСведений.РаботникиОрганизаций.СрезПоследних(&НачалоПериода, ) КАК РаботникиОрганизацийСрезПоследних
ГДЕ
	РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния <> ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Увольнение)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	РаботникиОрганизаций.Период,
	РаботникиОрганизаций.Сотрудник,
	РаботникиОрганизаций.Должность
ИЗ
	РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
ГДЕ
	РаботникиОрганизаций.Период МЕЖДУ &НачалоПериода И &КонецПериода
	И РаботникиОрганизаций.ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.ПриемНаРаботу)

ОБЪЕДИНИТЬ ВСЕ

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

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

ОБЪЕДИНИТЬ ВСЕ

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ_ДатыНачала.Сотрудник,
	ВТ_ДатыНачала.Должность,
	ВТ_ДатыНачала.ДатаНачала КАК ДатаНачала,
	МИНИМУМ(ЕСТЬNULL(ВТ_ДатыОкончания.ДатаОкончания, &КонецПериода)) КАК ДатаОкончания
ИЗ
	ВТ_ДатыНачала КАК ВТ_ДатыНачала
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДатыОкончания КАК ВТ_ДатыОкончания
		ПО ВТ_ДатыНачала.Сотрудник = ВТ_ДатыОкончания.Сотрудник
			И ВТ_ДатыНачала.ДатаНачала <= ВТ_ДатыОкончания.ДатаОкончания

СГРУППИРОВАТЬ ПО
	ВТ_ДатыНачала.Сотрудник,
	ВТ_ДатыНачала.Должность,
	ВТ_ДатыНачала.ДатаНачала

УПОРЯДОЧИТЬ ПО
	ВТ_ДатыНачала.Сотрудник.Наименование,
	ДатаНачала

Здесь показан основной принцип. можно построить таким же образом историю изменения подразделения сотрудника за период или одновременно должности и подразделения. И конечно применять такой принцип можно не только к регистру сведений РаботникиОрганизаций, но и к другим периодическим регистрам сведений. Например, СостояниеРаботниковОрганизаций. Как правило необходимость в подобных запросах встречается в конфигурации ЗУП.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

   

2018г. Профессия — 1С. Обмен опытом по программированию в 1С