gifts2017

Автоматический расчет стажа для ЗУП 3.0 на основании таблицы Места работы

Опубликовал mangy в раздел Программирование - Практика программирования

Часто кадровики просят сделать доработку - рассчитывать данные о стаже на основании данных таблицы "Места работы" раздела Трудовая деятельность. Создание такой доработки описано в данной статье.
В результате в форме ввода стажа появится кнопка "Заполнить по данным Места работы", которая рассчитает стаж из таблицы мест работы автоматически на дату приема или на дату, которую введет пользователь.

Для реализации этой доработки нужно всего-навсего добавить несколько процедур в модуль общей формы, итак:

Общая форма "Ввод стажа сотрудников", модуль формы.

1 Изменяем процедуру:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
..................
ДополнитьФорму();
//АВТО РАСЧЕТ СТАЖА + 
РазместитьДополнительныеЭлементыНаФорму();
//АВТО РАСЧЕТ СТАЖА -
ЗаполнитьДанныеОСтаже(Параметры.ДанныеСтажей);
..............................
КонецПроцедуры 

2 Добавляем процедуры

//АВТО РАСЧЕТ СТАЖА +
&НаСервере     
Процедура РазместитьДополнительныеЭлементыНаФорму()
	
	Кнопка = Элементы.Добавить("АвтоРасчетСтажа", Тип("КнопкаФормы"), Элементы.ФормаКоманднаяПанель);
	Кнопка.Вид = ВидКнопкиФормы.КнопкаКоманднойПанели;	
	Команда = Команды.Добавить("РассчитатьСтажПоДаннымПредМестРаботы");
	Команда.Действие = "РассчитатьСтажПоДаннымПредМестРаботы";
	Команда.Отображение = ОтображениеКнопки.Текст;
	Команда.Заголовок = "Заполнить по данным Места работы"; 
	Кнопка.ИмяКоманды = "РассчитатьСтажПоДаннымПредМестРаботы";	
	
	МассивДобавляемыхРеквизитов = Новый Массив;
	МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ТаблицаСведенийОСтаже", новый ОписаниеТипов("таблицаЗначений")));
	МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ДатаНачала", новый ОписаниеТипов("Дата"),"ТаблицаСведенийОСтаже"));
	МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("ДатаОкончания", новый ОписаниеТипов("Дата"),"ТаблицаСведенийОСтаже"));  	
	ИзменитьРеквизиты(МассивДобавляемыхРеквизитов); 
	
	УстановитьДействие("ПриОткрытии","ПриОткрытии");
	
КонецПроцедуры
&НаКлиенте
Процедура РассчитатьСтажПоДаннымПредМестРаботы(Команда)
	
	Если ЭтаФорма.ТаблицаСведенийОСтаже.Количество() = 0 Тогда
		Сообщить("Данные о трудовой деятельности не заполнены");
		Возврат;
	КонецЕсли;
	
	ЭтаФорма.СпособИсчисленияСтажа1  = 0;
	
	Если ЭтаФорма.ДатаОтсчета1 = Дата(1,1,1) Тогда
		Если ЭтаФорма.ДатаПриема1 = Дата(1,1,1) Тогда
			ЭтаФорма.ДатаОтсчета1 = ТекущаяДата();
		Иначе
			ЭтаФорма.ДатаОтсчета1 = ЭтаФорма.ДатаПриема1;
		КонецЕсли;
	КонецЕсли; 
	
	ИтогСтажДатаОтсчёта = ЭтаФорма.ДатаОтсчета1;
		
	РассчитатьСтажПоДаннымПредМестРаботыНаСервере(ИтогСтажДатаОтсчёта);    
	
	Модифицированность = Истина;
	
КонецПроцедуры

&НаСервере 
Процедура РассчитатьСтажПоДаннымПредМестРаботыНаСервере(ИтогСтажДатаОтсчёта) 
	
	//ТаблицаЗаписейОСтажеПоСотруднику = ТаблицаЗаписейРегистра("ТрудоваяДеятельностьФизическихЛиц", ЭтаФорма.ФизическоеЛицо);
	ТаблицаЗаписейОСтажеПоСотруднику = ЭтаФорма.ТаблицаСведенийОСтаже.Выгрузить();
	
	ИтогСтажЛет				=	0;
	ИтогСтажМесяцев			=	0;
	ИтогСтажДней			=	0;
	
	ПолучитьТаблицуИтоговСтажаПоСотруднику(ТаблицаЗаписейОСтажеПоСотруднику, ИтогСтажДатаОтсчёта, ИтогСтажЛет, ИтогСтажМесяцев, ИтогСтажДней);
		
КонецПроцедуры

Процедура ПолучитьТаблицуИтоговСтажаПоСотруднику(ЗаписиОСтаже, РасчётСтажДатаОтсчёта, РасчётЛет=0, РасчётМесяцев=0, РасчётДней =0);
    ДлинаСуток = 86400;
	
	ТаблицаЗаписейОСтаже = ЗаписиОСтаже.Скопировать();
    //РАСЧЕТ ОБЩЕГО ТРУДОВОГО СТАЖА С УЧЕТОМ ПЕРЕСЕЧЕНИЯ ПЕРИОДОВ

	//Выполним календарное поглащение:
	ВсегоЗаписей = ТаблицаЗаписейОСтаже.Количество(); 
	Для Н = 0 по ВсегоЗаписей - 1 Цикл
		Запись = ТаблицаЗаписейОСтаже[Н];

		Для К = 0 по ВсегоЗаписей - 1 Цикл
			Запись2 = ТаблицаЗаписейОСтаже[К];

			Если Запись = Запись2 Тогда//Запись не может поглатить саму себя
				Продолжить;
			КонецЕсли;	 
			
			Если (Запись2.ДатаНачала > Запись.ДатаОкончания) или
				(Запись2.ДатаОкончания < Запись.ДатаНачала)Тогда
				//Периоды не пересекаются
				Продолжить;
			Иначе	
				Если (Запись2.ДатаНачала >= Запись.ДатаНачала) Тогда
					Если (Запись2.ДатаОкончания <= Запись.ДатаОкончания) Тогда
						//Полное поглощение периода - удаляем запись2 с помощью задания отрицательного интервала
						Запись2.ДатаНачала = Дата('00010102');
						Запись2.ДатаОкончания = Дата('00010101');
					Иначе//Запись 2 начинается позднее и оканчивается позднее записи 1 - обрежем голову
						Запись2.ДатаНачала = Запись.ДатаОкончания + ДлинаСуток;
					КонецЕсли;	
				Иначе
					Если (Запись2.ДатаОкончания <= Запись.ДатаОкончания) Тогда
						//Запись2 начинается раньше и оканчивается раньше Записи1 - обрежем хвост
						Запись2.ДатаОкончания = Запись.ДатаНачала - ДлинаСуток;
					Иначе//Запись 2 начинается раньше и оканчивается позднее записи 1 - разбиение интервала на 2 части
						//породим вторую часть копирование исходной записи
						НоваяСтрока = ТаблицаЗаписейОСтаже.Добавить();
						ЗаполнитьЗначенияСвойств(НоваяСтрока, Запись2);
						//обрежем хвост у первой части
						Запись2.ДатаОкончания = Запись.ДатаНачала - ДлинаСуток;
						//обрежем голову у второй части
						НоваяСтрока.ДатаНачала = Запись.ДатаОкончания + ДлинаСуток;
					КонецЕсли;	
				КонецЕсли;	 
			КонецЕсли;	 
		КонецЦикла;	  
	КонецЦикла;	
	
	//если дата отсчета меньше даты окончания данных о стаже - скорректируем таблицу
	УдалитьПоследующиеЗаписи = Ложь;
	МассивКУдалению = Новый Массив;
	Для Каждого Запись из ТаблицаЗаписейОСтаже Цикл
		Если УдалитьПоследующиеЗаписи Тогда
			МассивКУдалению.Добавить(Запись);
		Иначе		
			Если Запись.ДатаНачала >= РасчётСтажДатаОтсчёта Тогда
				МассивКУдалению.Добавить(Запись);
				УдалитьПоследующиеЗаписи = Истина;
			ИначеЕсли Запись.ДатаОкончания >= РасчётСтажДатаОтсчёта Тогда
				Запись.ДатаОкончания = РасчётСтажДатаОтсчёта - 24*60*60;
				УдалитьПоследующиеЗаписи = Истина;
			КонецЕсли;    				
		КонецЕсли;
	КонецЦикла;	  	
	Для Каждого Элемент Из МассивКУдалению Цикл
		ТаблицаЗаписейОСтаже.Удалить(Элемент);
	КонецЦикла;   		
	
	//Расчет общего стажа по оставшимся записям
	ОбщийСтажДатаОтсчёта		=	Дата('00010101');
	ОбщийСтажЛет				=	0;
	ОбщийСтажМесяцев			=	0;
	ОбщийСтажДней				=	0;

	Для Каждого Запись из ТаблицаЗаписейОСтаже Цикл

		//Пропустим поглощенные и дополнительные записи
		Если  Запись.ДатаОкончания = Дата('00010101') Тогда
			Продолжить;
		КонецЕсли;	
		
		ЛетПоПериоду = 0;
		МесяцевПоПериоду = 0;
		ДнейПоПериоду = 0;
		ПерсонифицированныйУчет.ПолучитьСтажЗаПериод(Запись.ДатаОкончания,	Запись.ДатаНачала, ЛетПоПериоду,	МесяцевПоПериоду, ДнейПоПериоду);

		ОбщийСтажДатаОтсчёта	= Запись.ДатаОкончания; 
		ОбщийСтажЛет			=	ОбщийСтажЛет		+	ЛетПоПериоду;
		ОбщийСтажМесяцев		=	ОбщийСтажМесяцев	+	МесяцевПоПериоду;
		ОбщийСтажДней			=	ОбщийСтажДней		+	ДнейПоПериоду;
	КонецЦикла;	
	
	//Заносим в таблицу итогового стажа данные об общем стаже

	ПерсонифицированныйУчет.ПолучитьПриведенныйСтаж(ОбщийСтажЛет,ОбщийСтажМесяцев,ОбщийСтажДней);
	Если ОбщийСтажЛет + ОбщийСтажМесяцев + ОбщийСтажДней <> 0 Тогда
		
		//Получаем дату приёма
		ПараметрыПолученияСотрудников = КадровыйУчет.ПараметрыПолученияСотрудниковОрганизацийПоСпискуФизическихЛиц();
		ПараметрыПолученияСотрудников.СписокФизическихЛиц = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ЭтаФорма.ФизическоеЛицо);
		ПараметрыПолученияСотрудников.НачалоПериода = ТекущаяДатаСеанса();	
		ПараметрыПолученияСотрудников.ОкончаниеПериода = ТекущаяДатаСеанса();
		ПараметрыПолученияСотрудников.КадровыеДанные = "ДатаПриема";
		
		СотрудникиОрганизации = КадровыйУчет.СотрудникиОрганизации(Истина, ПараметрыПолученияСотрудников);
		
		ДатаПриема = Неопределено;
		Для Каждого ДанныеСотрудника Из СотрудникиОрганизации Цикл
			Если ЗначениеЗаполнено(ДанныеСотрудника.ДатаПриема) Тогда 
				Если ДатаПриема = Неопределено Тогда 
					ДатаПриема = ДанныеСотрудника.ДатаПриема;
				Иначе 
					ДатаПриема = Мин(ДатаПриема, ДанныеСотрудника.ДатаПриема);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		
		Если Не ЗначениеЗаполнено(ДатаПриема) Тогда 
			ДатаПриема = ТекущаяДатаСеанса();
		КонецЕсли; 		
		
		ЭтаФорма.Лет1				= ОбщийСтажЛет;
		ЭтаФорма.Месяцев1			= ОбщийСтажМесяцев;
		ЭтаФорма.Дней1				= ОбщийСтажДней;
	КонецЕсли;	 
КонецПроцедуры 


&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	Если СтрНайти(ВладелецФормы.ИмяФормы,"ТрудоваяДеятельность") <> 0 Тогда
		Для Каждого СтрокаДанных Из ВладелецФормы.ТрудоваяДеятельностьФизическихЛиц Цикл
			Строка = ЭтаФорма.ТаблицаСведенийОСтаже.Добавить();
			Строка.ДатаНачала = СтрокаДанных.ДатаНачала;	
			Строка.ДатаОкончания = СтрокаДанных.ДатаОкончания;
		КонецЦикла;
	Иначе
		ЗаполнитьСведенияОТрудовойДеятельностиНаСервере();
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьСведенияОТрудовойДеятельностиНаСервере() 
	
	НаборЗаписей = РегистрыСведений["ТрудоваяДеятельностьФизическихЛиц"].СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.ФизическоеЛицо.Значение = ЭтаФорма.ФизическоеЛицо;
	НаборЗаписей.Отбор.ФизическоеЛицо.Использование = Истина;
	
	НаборЗаписей.Прочитать();
	
	Для Каждого Запись Из НаборЗаписей Цикл
		Строка = ЭтаФорма.ТаблицаСведенийОСтаже.Добавить();
		Строка.ДатаНачала = Запись.ДатаНачала;	
		Строка.ДатаОкончания = Запись.ДатаОкончания; 		
	КонецЦикла;     
	
КонецПроцедуры
 //АВТО РАСЧЕТ СТАЖА -
 

3. PROFIT! Проверяем рекультат.

См. также

Подписаться Добавить вознаграждение

Комментарии

2. Михаил (Michael0507) 07.07.16 14:49
3. Ильдар Тагиров (pentanom) 07.07.16 15:19
4. Shefer 04.10.16 15:15
mangy, спасибо, пригодилось. Единственное, кадровики попросили: для того, что бы у них сошлось с программкой, по которой они считают стаж, вычитать из получившегося стажа количество дней, равное количеству строк в таблице Места работы. И вручную проверяли - именно на это количество и разница.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа