Модуль формы документа "Расчет лимитов":
&НаКлиенте
Процедура Заполнить(Команда)
ЗаполнитьНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьНаСервере()
Дата = ?(Объект.Дата = '00010101000000', ТекущаяДата(), Объект.Дата);
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Организация", Объект.Организация);
Запрос.УстановитьПараметр("Отпуск", Константы.Начисление_ОтпускЗаСвойСчет.Получить());
Запрос.УстановитьПараметр("Оклад", Константы.Показатель_Оклад.Получить());
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(Дата));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(Дата));
Запрос.Текст = "ВЫБРАТЬ
| СостоянияСотрудников.Сотрудник,
| &НачалоПериода КАК НачалоПериода,
| &КонецПериода КАК КонецПериода,
| ВЫБОР
| КОГДА КадроваяИсторияСотрудников.ДействуетДо = ДАТАВРЕМЯ(1, 1, 1)
| ИЛИ КадроваяИсторияСотрудников.ДействуетДо > &КонецПериода
| ТОГДА КадроваяИсторияСотрудников.Должность.ТарифнаяСетка
| ИНАЧЕ КадроваяИсторияСотрудников.ДолжностьПоОкончании.ТарифнаяСетка
| КОНЕЦ КАК КатегорияДолжности,
| МАКСИМУМ(ВЫБОР
| КОГДА ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.ДействуетДо = ДАТАВРЕМЯ(1, 1, 1)
| ИЛИ ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.ДействуетДо > &КонецПериода
| ТОГДА ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.Значение
| ИНАЧЕ ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.ЗначениеПоОкончании
| КОНЕЦ) КАК РазмерОклада,
| ЛимитыКомпенсации.Значение КАК КоличествоОкладов
|ПОМЕСТИТЬ Данные
|ИЗ
| РегистрСведений.СостоянияСотрудников.СрезПоследних(&КонецПериода, ) КАК СостоянияСотрудников
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(&КонецПериода, ГоловнаяОрганизация = &Организация) КАК КадроваяИсторияСотрудников
| ПО СостоянияСотрудников.Сотрудник = КадроваяИсторияСотрудников.Сотрудник
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЛимитыКомпенсации КАК ЛимитыКомпенсации
| ПО (ВЫБОР
| КОГДА КадроваяИсторияСотрудников.ДействуетДо = ДАТАВРЕМЯ(1, 1, 1)
| ИЛИ КадроваяИсторияСотрудников.ДействуетДо > &КонецПериода
| ТОГДА КадроваяИсторияСотрудников.Должность.ТарифнаяСетка
| ИНАЧЕ КадроваяИсторияСотрудников.ДолжностьПоОкончании.ТарифнаяСетка
| КОНЕЦ = ЛимитыКомпенсации.Категория)
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних(&КонецПериода, Организация = &Организация) КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников
| ПО СостоянияСотрудников.Сотрудник = ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.Сотрудник
| И (ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.Показатель = &Оклад)
|ГДЕ
| НЕ СостоянияСотрудников.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияСотрудника.Увольнение)
|
|СГРУППИРОВАТЬ ПО
| СостоянияСотрудников.Сотрудник,
| ВЫБОР
| КОГДА КадроваяИсторияСотрудников.ДействуетДо = ДАТАВРЕМЯ(1, 1, 1)
| ИЛИ КадроваяИсторияСотрудников.ДействуетДо > &КонецПериода
| ТОГДА КадроваяИсторияСотрудников.Должность.ТарифнаяСетка
| ИНАЧЕ КадроваяИсторияСотрудников.ДолжностьПоОкончании.ТарифнаяСетка
| КОНЕЦ,
| ЛимитыКомпенсации.Значение
|
|ИМЕЮЩИЕ
| МАКСИМУМ(ВЫБОР
| КОГДА ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.ДействуетДо = ДАТАВРЕМЯ(1, 1, 1)
| ИЛИ ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.ДействуетДо > &КонецПериода
| ТОГДА ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.Значение
| ИНАЧЕ ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.ЗначениеПоОкончании
| КОНЕЦ) > 0
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Данные.Сотрудник,
| Данные.НачалоПериода,
| Данные.КонецПериода,
| Данные.КатегорияДолжности,
| Данные.РазмерОклада,
| Данные.РазмерОклада * Данные.КоличествоОкладов / 12 КАК ПлановыйЛимит,
| СУММА(ВЫБОР
| КОГДА Начисления.ПериодДействияНачало ЕСТЬ NULL
| ТОГДА 0
| ИНАЧЕ РАЗНОСТЬДАТ(Начисления.ПериодДействияНачало, Начисления.ПериодДействияКонец, ДЕНЬ) + 1
| КОНЕЦ) КАК КоличествоДнейОтпуска
|ПОМЕСТИТЬ ДанныеСОтпуском
|ИЗ
| Данные КАК Данные
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрРасчета.Начисления КАК Начисления
| ПО Данные.Сотрудник = Начисления.Сотрудник
| И (Начисления.ВидРасчета = &Отпуск)
| И (НЕ Начисления.Сторно)
| И (Начисления.Активность)
| И (Начисления.ПериодДействияНачало МЕЖДУ &НачалоПериода И &КонецПериода)
|
|СГРУППИРОВАТЬ ПО
| Данные.Сотрудник,
| Данные.НачалоПериода,
| Данные.КонецПериода,
| Данные.КатегорияДолжности,
| Данные.РазмерОклада,
| Данные.РазмерОклада * Данные.КоличествоОкладов / 12
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ДанныеСОтпуском.Сотрудник,
| ДанныеСОтпуском.НачалоПериода,
| ДанныеСОтпуском.КонецПериода,
| ДанныеСОтпуском.КатегорияДолжности,
| ДанныеСОтпуском.РазмерОклада,
| ДанныеСОтпуском.ПлановыйЛимит,
| ВЫБОР
| КОГДА ДанныеСОтпуском.КоличествоДнейОтпуска = 0
| ТОГДА 1
| ИНАЧЕ ВЫБОР
| КОГДА ДанныеСОтпуском.КоличествоДнейОтпуска >= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1
| ТОГДА 0
| ИНАЧЕ ВЫРАЗИТЬ((РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1 - ДанныеСОтпуском.КоличествоДнейОтпуска) / (РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1) КАК ЧИСЛО(3, 2))
| КОНЕЦ
| КОНЕЦ КАК КоэффициентВремени,
| ВЫБОР
| КОГДА ДанныеСОтпуском.КоличествоДнейОтпуска = 0
| ТОГДА 1
| ИНАЧЕ ВЫБОР
| КОГДА ДанныеСОтпуском.КоличествоДнейОтпуска >= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1
| ТОГДА 0
| ИНАЧЕ ВЫРАЗИТЬ((РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1 - ДанныеСОтпуском.КоличествоДнейОтпуска) / (РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1) КАК ЧИСЛО(3, 2))
| КОНЕЦ
| КОНЕЦ * ДанныеСОтпуском.ПлановыйЛимит КАК ЗаработанныйЛимит
|ИЗ
| ДанныеСОтпуском КАК ДанныеСОтпуском";
Выборка = Запрос.Выполнить().Выбрать();
Объект.Данные.Очистить();
Пока Выборка.Следующий() Цикл
СтрокаТаблицыДанные = Объект.Данные.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаТаблицыДанные, Выборка);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ДанныеПлановыйЛимитПриИзменении(Элемент)
Пересчитать();
КонецПроцедуры
&НаКлиенте
Процедура Пересчитать()
ТекущаяСтрока = Элементы.Данные.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущаяСтрока.ЗаработанныйЛимит = ТекущаяСтрока.ПлановыйЛимит * ТекущаяСтрока.КоэффициентВремени;
КонецПроцедуры
&НаКлиенте
Процедура ДанныеКоэффициентВремениПриИзменении(Элемент)
Пересчитать();
КонецПроцедуры
Модуль объекта документа "Расчет лимитов":
Процедура ОбработкаПроведения(Отказ, Режим)
Если Константы.Показатель_Компенсация.Получить().Пустая() Тогда
СообщениеПользователю = Новый СообщениеПользователю;
СообщениеПользователю.Текст = "Не установлена константа ""Показатель_Компенсация""";
СообщениеПользователю.Сообщить();
Отказ = Истина;
Возврат;
КонецЕсли;
Движения.КомпенсацияКварПлаты.Записать();
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
Запрос.УстановитьПараметр("Дата", Дата);
Запрос.УстановитьПараметр("КонецПредыдущегоГода", Новый Граница(КонецГода(ДобавитьМесяц(Дата, -12)), ВидГраницы.Включая));
Запрос.УстановитьПараметр("ПредыдущийГод", НачалоГода(ДобавитьМесяц(Дата, -12)));
Запрос.Текст = "ВЫБРАТЬ
| Остатки.Сотрудник,
| Остатки.Год,
| Остатки.СуммаОстаток КАК Сумма
|ИЗ
| РегистрНакопления.КомпенсацияКварПлаты.Остатки(&МоментВремени, Год <= &ПредыдущийГод) КАК Остатки
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Док.Сотрудник,
| СУММА(Док.ЗаработанныйЛимит) КАК Сумма,
| МАКСИМУМ(ЕСТЬNULL(Остатки.СуммаОстаток, 0) * -1) КАК СуммаОстаток
|ИЗ
| Документ.РасчетЛимитов.Данные КАК Док
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.КомпенсацияКварПлаты.Остатки(&МоментВремени, Год = НАЧАЛОПЕРИОДА(&Дата, ГОД)) КАК Остатки
| ПО Док.Сотрудник = Остатки.Сотрудник
| И (Остатки.СуммаОстаток < 0)
|ГДЕ
| Док.Ссылка = &Ссылка
|
|СГРУППИРОВАТЬ ПО
| Док.Сотрудник
|
|ИМЕЮЩИЕ
| СУММА(Док.ЗаработанныйЛимит) > 0";
Результат = Запрос.ВыполнитьПакет();
Выборка = Результат[1].Выбрать();
ВыборкаКорректировкаПрошлыхПериодов = Результат[0].Выбрать();
Пока ВыборкаКорректировкаПрошлыхПериодов.Следующий() Цикл
Движение = Движения.КомпенсацияКварПлаты.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Сотрудник = ВыборкаКорректировкаПрошлыхПериодов.Сотрудник;
Движение.Сумма = ВыборкаКорректировкаПрошлыхПериодов.Сумма;
Движение.Год = ВыборкаКорректировкаПрошлыхПериодов.Год;
КонецЦикла;
Пока Выборка.Следующий() Цикл
Движение = Движения.КомпенсацияКварПлаты.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Сотрудник = Выборка.Сотрудник;
Движение.Сумма = Выборка.Сумма;
Движение.Год = НачалоГода(Дата);
Если Выборка.СуммаОстаток > 0 Тогда
Зачтем = Мин(Выборка.Сумма, Выборка.СуммаОстаток);
Движение = Движения.ЗначенияОперативныхПоказателейРасчетаЗарплатыСотрудников.Добавить();
Движение.Период = Дата;
Движение.Сотрудник = Выборка.Сотрудник;
Движение.Показатель = Константы.Показатель_Компенсация.Получить();
Движение.Организация = Организация;
Движение.ФизическоеЛицо = Выборка.Сотрудник.ФизическоеЛицо;
Движение.Значение = Зачтем;
КонецЕсли;
КонецЦикла;
Движения.ЗначенияОперативныхПоказателейРасчетаЗарплатыСотрудников.Записывать = Истина;
Движения.КомпенсацияКварПлаты.Записывать = Истина;
КонецПроцедуры