пятница, 30 января 2015 г.

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

Скачать решение

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


Ежемесячно, сотрудникам компании может выплачиваться фиксированная
сумма денег. Размер суммы задается в документе «Начисление зарплаты» и в
последствии может быть изменен.
Сотрудникам предоставляется оплачиваемый отпуск, размер которого
определяется как количество дней отпуска умноженное на среднюю дневную
ставку. Дни отпуска рассчитываются по шестидневному графику. Средняя
дневная ставка определяется как сумма всех начислений за три предыдущих
месяца, поделенная на количество отработанных дней в трех предыдущих
месяцах. Следует учесть, что данные об отпуске не могут вводиться в систему
задним числом.
Механизм перерасчетов в рамках данной задачи использовать не надо.
Ввод всех начислений происходит документом «Начисление зарплаты».
Считать, что все данные вводятся только в пределах одного месяца, например,
можно указать начисление по тарифу с 10.01 по 31.01, а запись: тариф с 10.01 по
03.02 вводить нельзя.
Необходимо предоставить пользователю возможность исправлять
результат расчета в форме документа, а также самостоятельно создавать новые
виды расчетов и привязывать их к существующим алгоритмам расчета.
Для анализа сделанных сотрудникам предприятия начислений в
конфигурации необходимо предусмотреть отчет следующего вида:
Решение задачи :
1) Первым делом заполним регистр сведений "Графики работы". Для этого потребуется создать новый справочник "Графики работы". Можно в нем сразу же добавить предопределенные элементы 5дневка  и 6дневка. Заполнять график будем с помощью обработки "Заполнение графика". Необходимо выполнить минимум доработок.
  1. Добавить реквизит обработки "График". 
  2. В модуле обработки установить отбор на набор записей:  Набор.Отбор.График.Установить(График); после первой строки кода.
  3. Далее при создании новой записи упомянуть график "везде где только нужно" ).
  4. Заполнить график в режиме предприятия. Для пятидневки в поле выходные дни пишем 67, для шестидневки только 7. 
2) Создадим и заполним регистр сведений "Тарифные ставки".
Измерения:
Подразделение
ОтработаноС
ОтработаноПо
Ресурс (тип число(10,1))
После заполнения регистр будет иметь вид:



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


ПВР "Дополнительные начисления" сбросим флаг "Использует период действия", зависимость от базы = "Не зависит". Заведем  предопределенный ВР: "ПремияФиксСуммой".

4) Понадобятся 2 регистра расчета "Основные начисления" и "Дополнительные начисления".

реквизит график необходимо связать с измерением регистра сведений.

5). Переходим к документу "Начисление ЗП".
Добавим реквизиты шапки и таб. частей.

В условии сказано "Считать, что все данные вводятся только в пределах одного месяца, например,можно указать начисление по тарифу с 10.01 по 31.01, а запись: тариф с 10.01 по
03.02 вводить нельзя."
Понимаю что реализовать это можно процедурой проверки поля"Период действия конец".
&НаКлиенте
Процедура ОсновныеНачисленияДатаОкончанияПриИзменении(Элемент)
ТекСтрока = Элементы.ОсновныеНачисления.ТекущиеДанные;
Если НачалоМесяца(ТекСтрока.ПериодДействияНачало) <> НачалоМесяца(ТекСтрока.ПериодДействияКонец) Тогда
ТекСтрока. ПериодДействияКонец = Дата(1,1,1);
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст = "Даты должны принадлежать одному периоду";
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры

В условии требуется "предоставить пользователю возможность исправлять
результат расчета в форме документа".
Реализую это требование следующим образом: В форме документа создам процедуру "Рассчитать", которая и выполнит расчет и загрузит данные расчета в ТЧ, а по команде провести выполнится запись в регистр значений "как есть" исправленных пользователем.
В решении я вижу пару нереализованных моментов:
1) Для отпуска базой являются 3 предыдущих месяца. По идее если пользователь заводит подобный  ВР с типом "по среднему", то еще необходимо с помощью реквизита запросит количество месяцев базы для нового ВР. В решении для всех это кол-во =3.
2) В подобных задачах иногда используются приоритеты для указания последовательности выполнения расчетов, но как мне кажется в этой задаче и так достаточно заморочек и без этого, и особой нужды в этом нет.



6) Несложный отчет "Начисления", в котором необходимо объединить 2 таблицы и добавить в группировку по колонкам поле "период регистрации"
Итак. ниже листинги процедур и сама база.



&НаСервере
Процедура РассчитатьНаСервере()
Документ = РеквизитФормыВЗначение("Объект");
Документ.Рассчитать();
ЗначениеВРеквизитФормы( Документ, "Объект");
КонецПроцедуры

&НаКлиенте
Процедура Рассчитать(Команда)
РассчитатьНаСервере();
КонецПроцедуры


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

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


Листинг процедуры Рассчет общего модуля:

Процедура ВыполнитьРассчет(НаборЗаписей, СпособРасчета, МассивСотрудников) Экспорт

Регистратор=НаборЗаписей.Отбор.Регистратор.Значение;

Если СпособРасчета = Перечисления.СпособыРасчета.ПропорциональноОтработанномуВремени Тогда

Запрос = Новый("Запрос");
Запрос.Текст ="ВЫБРАТЬ
| ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия, 0) КАК Факт,
| ЕСТЬNULL(ТарифныеСтавки.РазмерСтавки, 0) КАК Тариф,
| ОсновныеНачисленияДанныеГрафика.НомерСтроки,
| ОсновныеНачисленияДанныеГрафика.ОтработаноДней

|ИЗ
| РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(
| Сотрудник В (&МассивСотрудников)
| И ВидРасчета.СпособРасчета = &СпособРасчета
| И Регистратор = &Регистратор) КАК ОсновныеНачисленияДанныеГрафика
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТарифныеСтавки КАК ТарифныеСтавки
| ПО ОсновныеНачисленияДанныеГрафика.Подразделение = ТарифныеСтавки.Подразделение
| И ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия >= ТарифныеСтавки.ОтработаноС
| И ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия <= ТарифныеСтавки.ОтработаноПо";

Запрос.УстановитьПараметр("СпособРасчета", СпособРасчета);
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Запрос.УстановитьПараметр("МассивСотрудников", МассивСотрудников);

Выборка = Запрос.Выполнить().Выбрать();

Для Каждого Запись Из НаборЗаписей Цикл

Отбор  = Новый("Структура");
Отбор.Вставить("НомерСтроки",Запись.НомерСтроки);
Выборка.Сбросить();
Если выборка.НайтиСледующий(Отбор) тогда
Запись.Параметр = Выборка.Факт;
Запись.Результат = (Выборка.Факт) * Выборка.Тариф;
Запись.ОтработаноДней = Выборка.Факт/8;

КонецЕсли;
КонецЦикла;


ИначеЕсли    СпособРасчета = Перечисления.СпособыРасчета.ПоСреднему Тогда

Измер = Новый("Массив");
Измер.Добавить("Сотрудник");

Запрос = Новый("Запрос");
Запрос.Текст ="ВЫБРАТЬ
| ОсновныеНачисленияБазаОсновныеНачисления.НомерСтроки,
| ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия, 0) / 8 КАК ДнейОтпуска,
| ЕСТЬNULL(ОсновныеНачисленияБазаДополнительныеНачисления.РезультатБаза, 0) КАК БазаДН,
| ЕСТЬNULL(ОсновныеНачисленияБазаОсновныеНачисления.РезультатБаза, 0) КАК БазаОН,
| ОсновныеНачисленияДанныеГрафика.ЗначениеПериодДействия,
| ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия,
| ОсновныеНачисленияДанныеГрафика.ЗначениеБазовыйПериод,
| ОсновныеНачисленияДанныеГрафика.ЗначениеПериодРегистрации,
| ОсновныеНачисленияБазаОсновныеНачисления.ОтработаноДнейБаза КАК ОтработаноДней
|ИЗ
| РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(
| Сотрудник В (&МассивСотрудников)
| И ВидРасчета.СпособРасчета = &СпособРасчета
| И Регистратор = &Регистратор) КАК ОсновныеНачисленияДанныеГрафика
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрРасчета.ОсновныеНачисления.БазаОсновныеНачисления(
| &ИзмеренияОсновного,
| &ИзмеренияБазового,
| ,
| Сотрудник В (&МассивСотрудников)
| И ВидРасчета.СпособРасчета = &СпособРасчета
| И Регистратор = &Регистратор) КАК ОсновныеНачисленияБазаОсновныеНачисления
| ПО ОсновныеНачисленияДанныеГрафика.Сотрудник = ОсновныеНачисленияБазаОсновныеНачисления.Сотрудник
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрРасчета.ОсновныеНачисления.БазаДополнительныеНачисления(&ИзмеренияОсновного, &ИзмеренияБазового, , Сотрудник В (&МассивСотрудников)) КАК ОсновныеНачисленияБазаДополнительныеНачисления
| ПО ОсновныеНачисленияДанныеГрафика.Сотрудник = ОсновныеНачисленияБазаДополнительныеНачисления.Сотрудник";

Запрос.УстановитьПараметр("СпособРасчета", СпособРасчета);
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Запрос.УстановитьПараметр("МассивСотрудников", МассивСотрудников);
Запрос.УстановитьПараметр("ИзмеренияОсновного", Измер);
Запрос.УстановитьПараметр("ИзмеренияБазового", Измер);
Выборка = Запрос.Выполнить().Выбрать();

Для Каждого Запись Из НаборЗаписей Цикл

Отбор  = Новый("Структура");
Отбор.Вставить("НомерСтроки",Запись.НомерСтроки);
Выборка.Сбросить();
Если выборка.НайтиСледующий(Отбор) тогда
Запись.Параметр = Выборка.ДнейОтпуска;
Если Выборка.ОтработаноДней <> 0 Тогда
СреднийЗаработок =    (Выборка.БазаДН + Выборка.БазаОН)/Выборка.ОтработаноДней;
Запись.Результат = Выборка.ДнейОтпуска * СреднийЗаработок;
Иначе
Запись.Результат = 0;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;


КонецПроцедуры
Скачать решение

Возможно Вам будет интересен курс "Профессиональный учет в 1С:ЗУП 3.0»

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

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