среда, 18 февраля 2015 г.

1с специалист задача 3.16

Условие задачи из сборника:

Начисление зарплаты сотрудникам предприятия осуществляется ежемесячно с использованием метода отклонений. Все сотрудники работают по пятидневному графику работы, однако в решении необходимо предусмотреть возможность работы по нескольким различным графикам. Сотрудники предприятия получают оплату по окладу пропорционально
отработанному времени в часах. Часовая ставка рассчитывается как начальное значение оклада, деленное на количество рабочих часов в том же периоде, что и фактически отработанные часы. Первоначальное значение оклада может изменяться не чаще, чем один раз в день, но берется на начало расчетного периода. В целях управленческого учета, дополнительно, необходимо хранить информацию о начисленном окладе, исходя из отработанного времени в днях. Ставка за один день рассчитывается аналогично ставке за один час. Таким образом, если сотрудник отработал полдня, то в часах сумма оклада будет меньше, чем в днях. Сотруднику предприятия выплачивается надбавка, рассчитываемая как общая сумма продаж товаров за предыдущий месяц по подразделению, в котором работает сотрудник, умноженная на определенный процент. Значение процента для надбавки может быть изменено только один раз в течение расчетного периода. В этом случае, расчет начисления должен производиться исходя из действующего на рассчитываемый период процента. Например, если процент изменился 10 августа, то до 10.10 при расчете берется старый процент, а после 10.10 (включительно) уже новый. За каждый день невыхода сотрудника на работу без уважительной причины сотруднику начисляется штраф в размере 200 рублей. Механизм перерасчетов в рамках данной задачи использовать не надо. Ввод всех начислений происходит документом «Начисление зарплаты». Считать, что все данные вводятся только в пределах одного месяца, например, можно указать начисление оклада с 10.01 по 31.01, а запись: оклад с 10.01 по 03.02 вводить нельзя.

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

Решение:


Довольно "завернутое" условие.
После продолжительного мысленного усилия пришел к следующей структуре.
 В ПВР "Основные начисления" идут
  • Оклад (вытесняется "невыходом" и "Неполным рабочим днем)"
  • Неполный рабочий день.(вытесняется невыходом).
  • Невыход.
В ПВР "Дополнительные начисления" - Премия.

В регистре сведений "Сведения о сотрудниках" добавим ресурс "ПроцентПремии", понятно для чего.
Добавим регистр сведений "Продажи" с измерением "подразделение" и "сумма".
В Регистр сведений "Графики" уберем ресурс значение и добавим новые "дней" и "часов", заполним регистр с помощью обработки немножко дописав ее.
Оклад считаем стандартным способом.
Неполный рабочий день считаем практически так же как и оклад только для расчета берем не часы, а дни.
Невыход считаем получая фактические дни невыхода и умножаем на (-200).
"Затык" с расчетом премии. В запросе определяем дату последнего изменения премии и если премия менялась в текущем периоде, разбиваем на 2 записи.Но вопрос как рассчитать эти записи.  Возможно решая билет целиком нужно брать продажи из регистра накопления из задачи по оперативному учету, а так в рамках отдельной задачи вижу единственный годный вариант разбить премию пропорционально дням месяца. Рассчитать премию (надбавку) можно прямо в модуле документа.

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
ПериодРегистрации = НачалоМесяца(ПериодРегистрации);
КонецПроцедуры


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


Из-за этого весьма компактной получилась процедура расчета записей общего модуля.


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

Ну и конечно отчеты.




Комментариев нет:

Отправить комментарий