Top.Mail.Ru

Регистры расчета в 1С для чайников(Часть 3)

В данной статье на примерах покажем принцип действия «механизма зависимости по базовому периоду«, а также покажем принцип действия перерасчётов в 1С. В качестве примера для расчёта возьмём расчёт премии сотрудника процентом от оклада, пусть премия сотруднику начисляется ежемесячно и её размер зависит от начисленного оклада за 2 предыдущих месяца.

Премия — это вид расчёта не обладающий протяжённостью во времени. Объекта для хранения видов расчётов не обладающих протяжённостью во времени у нас в конфигурации не предусмотрено. Создадим такой объект.

Добавим в конфигурацию план видов расчёта «ДополнительныеНачисления». Перейдём на вкладку «Расчет».

Флаг «Использует период действия» не устанавливаем так как план видов расчёта «ДополнительныеНачисления» не будет хранить виды расчётов обладающие протяжённостью во времени. Установим флаг «Зависимость от базы» в значение «Зависит по периоду действия«(в нашем случае база для расчета премии будет зависеть от периода действия оклада), если «Зависимость от базы» установить в значение «Зависит по периоду регистрации» тогда база для расчета премии будет зависеть от периода регистрации записи по окладу(поле ПериодРегистрации регистра расчёта).

В качестве базовых планов видов расчёта укажем ПВР «Основные начисления»(так как вид расчёта Оклад у нас хранится в ПВР «Основные начисления») и ПВР «Дополнительные начисления»(пусть в базу для расчёта премии у нас попадает не только оклад, но и премия начисленная в предыдущие периоды).

Создадим предопределённый вид расчёта «Премия».

На вкладке «Базовые» мы видим планы видов расчёта «Основные начисления» и «Дополнительные начисления»(это те ПВР, которые мы указали на вкладке «Расчёт» в качестве базовых планов видов расчёта). Укажем виды расчёта «Оклад» и «Премия». Примечание: в качестве базовых можно указать как протяжённые, так и не протяжённые во времени виды расчётов(в данном примере вид расчёта «Оклад» у нас обладает протяжённостью во времени, а премия нет).

На вкладке «Ведущие» укажем такие же виды расчёта «Оклад» и «Премия». На вкладке ведущие указываются виды расчётов при изменении которых требуется пересчитать текущий вид расчёта «Премия»(т.е. в данном случае при изменении оклада за прошлые периоды мы должны пересчитать премию за текущий период, а также при изменении премии за прошлые периоды мы должны пересчитать премию за текущий период). С вкладкой «Ведущие» связан объект «Перерасчёты«. Перерасчёт показывает какие данные необходимо пересчитать при изменении ведущих видов расчёта.

Создадим регистр расчёта «Дополнительные начисления».

На вкладке «Основное» укажем созданный ранее план видов расчета «Дополнительные начисления». Поставим флаг «Базовый период» — у нас стали доступны поля «Базовый период начало» и «Базовый период конец«. Укажем периодичность — месяц. В качестве регистратора укажем документ «Начисление зарплаты». Структура регистра показана выше — измерение «Сотрудник», ресурс «Сумма», реквизит «Параметр» для хранения процента премии.

В полях «Базовый период начало» и «Базовый период конец» мы указываем за какой период брать базу для расчёта премии.

Доработаем документ «Начисление зарплаты»:

Добавим табличную часть «Дополнительные начисления».

Реквизит «ВидРасчета» имеет тип «ПланВидовРасчетаСсылка.ДополнительныеНачисления», типы остальных реквизитов очевидны.

Дополним обработку проведения документа движениями по регистру расчета «ДополнительныеНачисления»:

// регистр ДополнительныеНачисления
Движения.ДополнительныеНачисления.Записывать = Истина; //устанавливаем флаг автоматической записи движений
Движения.ДополнительныеНачисления.Очистить(); //чистим коллекцию движений чтобы на обычных формах не дублировались движения

Для Каждого ТекСтрокаДополнительныеНачисления Из ДополнительныеНачисления Цикл
	Движение = Движения.ДополнительныеНачисления.Добавить();
	Движение.Сторно = Ложь; //указываем, что это не сторнирующая запись
	Движение.ВидРасчета = ТекСтрокаДополнительныеНачисления.ВидРасчета;
	Движение.БазовыйПериодНачало = ТекСтрокаДополнительныеНачисления.БазовыйПериодНачало;
	Движение.БазовыйПериодКонец = КонецДня(ТекСтрокаДополнительныеНачисления.БазовыйПериодКонец); //берём дату на конец дня
	Движение.ПериодРегистрации = ПериодРегистрации;
	Движение.Сотрудник = ТекСтрокаДополнительныеНачисления.Сотрудник;
	Движение.Параметр = ТекСтрокаДополнительныеНачисления.РазмерПремии; //в Параметр пишем процент премии сотрудника
КонецЦикла;
	
Движения.Записать();
Расчет.РассчитатьНачисления(Ссылка, Движения.ОсновныеНачисления);	
Расчет.РассчитатьНачисления(Ссылка, Движения.ДополнительныеНачисления);	//расчет премии

Заполним в документе табличную часть «ДополнительныеНачисления» и проведём документ:

В движениях документа видим, что все поля заполнились кроме суммы т.к. расчёт премии ещё не сделали:

Базовый период для расчета премии у нас 01.01.2017-28.02.2017, процент премии-10, сотрудник Иванов.

Выполним расчёт премии:

Для этого дополним общий модуль «Расчет» кодом расчета премии, полный текст общего модуля расположен ниже:

Для расчёта премии используем виртуальную таблицу «БазаОсновныеНачисления«(эта таблица у нас доступна в конструкторе запросов так как мы для ПВР «ДополнительныеНачисления» в качестве базовых планов видов расчёта указали ПВР»ОсновныеНачисления»). База будет получена за интервал между «Базовый период начало» и «Базовый период конец» по виду расчёта «Оклад» так как он у нас входит в базу для премии. Так же в виртуальную таблицу необходимо передать массив измерений регистра в разрезе которых будем получать базу, у нас это измерение одно «Сотрудник», его и передаём. Если измерения будет 2, тогда передать 2.

Процедура РассчитатьНачисления(Регистратор, НаборЗаписей) Экспорт
	
	Если ТипЗнч(НаборЗаписей) = Тип("РегистрРасчетаНаборЗаписей.ОсновныеНачисления") Тогда
		//Оклад
		Запрос=Новый Запрос;
		Запрос.Текст="ВЫБРАТЬ
		             |	ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.КоличествоЧасовФактическийПериодДействия, 0) КАК ЧасовФакт,
		             |	ОсновныеНачисленияДанныеГрафика.Параметр,
		             |	ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.КоличествоЧасовПериодДействия, 0) КАК ЧасовПлан,
		             |	ОсновныеНачисленияДанныеГрафика.НомерСтроки
		             |ИЗ
		             |	РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(
		             |			Регистратор = &Регистратор
		             |				И ВидРасчета = &ВидРасчетаОклад) КАК ОсновныеНачисленияДанныеГрафика";
		
		Запрос.УстановитьПараметр("Регистратор", Регистратор);
		Запрос.УстановитьПараметр("ВидРасчетаОклад", ПланыВидовРасчета.ОсновныеНачисления.Оклад);
		
		Выборка=Запрос.Выполнить().Выбрать();
		СтруктураПоиска=Новый Структура;
		СтруктураПоиска.Вставить("НомерСтроки",0);
		Для Каждого Запись Из НаборЗаписей Цикл
			СтруктураПоиска.НомерСтроки=Запись.НомерСтроки;
			Если Выборка.НайтиСледующий(СтруктураПоиска) Тогда
				Запись.Сумма =?(Выборка.ЧасовПлан=0,0, Выборка.ЧасовФакт/Выборка.ЧасовПлан * Выборка.Параметр);
				Запись.ЧасовПлан = Выборка.ЧасовПлан;
				Запись.ОтработаноЧасов = Выборка.ЧасовФакт;
			КонецЕсли;		
			Выборка.Сбросить();
		КонецЦикла;
		
	ИначеЕсли ТипЗнч(НаборЗаписей) = Тип("РегистрРасчетаНаборЗаписей.ДополнительныеНачисления") Тогда	
		//Премия
                //берём базу для премии на основе записей регистра Основные начисления, для этого используем виртуальную таблицу БазаОсновныеНачисления
		Запрос=Новый Запрос;
		Запрос.Текст="ВЫБРАТЬ
		             |	ДополнительныеНачисленияБазаОсновныеНачисления.НомерСтроки,
		             |	ЕСТЬNULL(ДополнительныеНачисленияБазаОсновныеНачисления.Параметр, 0) КАК Параметр,
		             |	ЕСТЬNULL(ДополнительныеНачисленияБазаОсновныеНачисления.СуммаБаза, 0) КАК СуммаБаза
		             |ИЗ
		             |	РегистрРасчета.ДополнительныеНачисления.БазаОсновныеНачисления(
		             |			&Измерения,
		             |			&Измерения,
		             |			,
		             |			Регистратор = &Регистратор
		             |				И ВидРасчета = &ВидРасчетаПремия) КАК ДополнительныеНачисленияБазаОсновныеНачисления";
		
		Запрос.УстановитьПараметр("Регистратор", Регистратор);
		Запрос.УстановитьПараметр("ВидРасчетаПремия", ПланыВидовРасчета.ДополнительныеНачисления.Премия); //устанавливаем вид расчёта Премия
		
		Измерения = Новый Массив(1); //создаём массив измерений в разрезе которых будем брать базу, у нас в обеих регистрах 1 измерение Сотрудник поэтому указываем его
		Измерения[0] = "Сотрудник";
		
		Запрос.УстановитьПараметр("Измерения", Измерения); //устанавливаем измерения в параметр
		
		Выборка=Запрос.Выполнить().Выбрать();
		СтруктураПоиска=Новый Структура;
		СтруктураПоиска.Вставить("НомерСтроки",0);
		Для Каждого Запись Из НаборЗаписей Цикл /цикл по набору записей регистра доп.начисления
			СтруктураПоиска.НомерСтроки=Запись.НомерСтроки;
			Если Выборка.НайтиСледующий(СтруктураПоиска) Тогда //ищем запись в базе по номеру строки
				Запись.Сумма =?(Выборка.СуммаБаза=0,0, Выборка.СуммаБаза/100 * Выборка.Параметр); //вычисляем премию, делим базу полученную за базовый период на 100 и умножаем на процент премии из документа
			КонецЕсли;		
			Выборка.Сбросить();
		КонецЦикла;

	КонецЕсли;
	
	НаборЗаписей.Записать(,Истина); //записываем набор записей, обязательно установить 2 параметр ТолькоЗапись = Истина, иначе у нас при записи пересчитается фактичекий период действия

КонецПроцедуры

Проверим, считается ли премия:

Создадим 2 документа с видом расчёта «Оклад» по сотруднику Иванов за Январь 2017 и Февраль 2017. На основе этих документов и будет собираться база для расчёта премии.

Перепроведём документ(за март 2017) в котором начисляем премию. В движениях документа видим, что премия рассчиталась и начислена в размере 12000 рублей.

Проверим расчёт премии: По сотруднику Иванов за период Январь 2017 — Февраль 2017 было начислено 120000 рублей оклада. (120000/100)*10 = 12000 рублей.

Перерасчёты

Теперь поговорим про перерасчеты.

Создадим в регистре расчёта «ДополнительныеНачисления» перерасчёт «Перерасчет1» с измерением «Сотрудник».

Свяжем измерение перерасчёта «Сотрудник» с измерением «Сотрудник» регистра «ДополнительныеНачисления» и измерениями регистров, указанных на вкладке «Ведущие».

Благодаря этой связи премия, начисленная на основании «Оклада» при изменении этого «Оклада» попадёт в перерасчёт. Это значит, что при изменении базы для премии по сотруднику Иванов, премия по сотруднику Иванов попадёт в перерасчёт.

Проверим так ли это…

Создадим отчёт на СКД на основе данных «Перерасчет1».

ВЫБРАТЬ
	Перерасчет1.ОбъектПерерасчета,
	Перерасчет1.ВидРасчета,
	Перерасчет1.Сотрудник
ИЗ
	РегистрРасчета.ДополнительныеНачисления.Перерасчет1 КАК Перерасчет1

Сформируем отчёт.

Изначально отчёт пустой…

Теперь изменим значение оклада по сотруднику Иванов за Февраль 2017 — было 60000 рублей, изменим на 80000 рублей.

Сформируем заново отчёт по перерасчёту…

Видим, что вид Премия(за март 2017) попала в перерасчёт.

На этом про регистры расчёта в 1С всё…

Comments

So empty here ... leave a comment!

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

Sidebar