Продвинутый курс. Домашнее задание №16

Эта запись посвящена второму потоку продвинутого курса по программированию.

Первое задание по расчету.

Для выполнения рекомендуется изучить следующие главы 4-го блока.
Глава 1. Настройки объектов расчета
Глава 2. Графики работы
Глава 3. Универсальные алгоритмы
Глава 4. Задача сторнирования

К сожалению, у Вас недостаточно прав для просмотра этой записи. Если Вы еще не залогинены на сайте
залогиньтесь.

Если не активировали токен — посмотрите видео-инструкцию (видео N5)

Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —
напишите нам на e-mail поддержки.

комментариев 19 на “Продвинутый курс. Домашнее задание №16”

  1. Задание выполнил.
    Добавил перечисление СпособыРасчета со значениями ПоОтработанномуВремени, Процентом, Больничный, Сдельно. В планах видов расчета ОсновныеНачисления и ДополнительныеНачисления добавил реквизит СпособРасчета типа ПеречислениеСсылка.СпособыРасчета. В плане видов расчета ДополнительныеНачисления установил свойство «Зависимость от базы» в значение «Зависит по периоду регистрации».
    В пользовательском режиме создал требуемые виды расчета:
    в плане видов расчета ОсновныеНачисления –

    «Оклад по часам» (Категория расчета = 0, Способ расчета = По отработанному времени, Вытесняющие виды расчета – «Больничный»);
    «Больничный» (Категория расчета = 0, Способ расчета = Больничный)

    в плане видов расчета ДополнительныеНачисления –

    «Надбавка за вредность» (Категория расчета = 1, Способ расчета = Процентом, Базовые виды расчетов – «Оклад по часам», Ведущие виды расчетов – «Оклад по часам»)
    «Сдельная оплата» (Категория расчета = 0, Способ расчета = Сдельно).

    При проведении документа «Начисление заработной платы» вводятся записи регистров расчета и осуществляется их расчет: 

    Процедура ОбработкаПроведения(Отказ, Режим)  Движения.ОсновныеНачисления.Записывать = Истина;  Движения.ДополнительныеНачисления.Записывать = Истина;
     Для Каждого ТекСтрокаНачисления Из Начисления Цикл
     Если ТипЗнч(ТекСтрокаНачисления.ВидРасчета) = Тип("ПланВидовРасчетаСсылка.ОсновныеНачисления") Тогда
    Движение = Движения.ОсновныеНачисления.Добавить(); Движение.ПериодДействияНачало = ТекСтрокаНачисления.ДатаНачала; Движение.ПериодДействияКонец = КонецДня(ТекСтрокаНачисления.ДатаОкончания);
    Движение.ТипГрафика = ТекСтрокаНачисления.ТипГрафика;
    ИначеЕсли ТипЗнч(ТекСтрокаНачисления.ВидРасчета) = Тип("ПланВидовРасчетаСсылка.ДополнительныеНачисления") Тогда
    Движение = Движения.ДополнительныеНачисления.Добавить();
    КонецЕсли;
    Движение.ПериодРегистрации = ПериодРегистрации;
    Движение.Сторно = ТекСтрокаНачисления.Сторно;
    Движение.ВидРасчета = ТекСтрокаНачисления.ВидРасчета; Движение.Сотрудник = ТекСтрокаНачисления.Сотрудник; Движение.Подразделение = ТекСтрокаНачисления.Подразделение; Движение.БазовыйПериодНачало = НачалоМесяца(ПериодРегистрации); Движение.БазовыйПериодКонец = КонецМесяца(ПериодРегистрации); Движение.Размер = ТекСтрокаНачисления.Размер;
    КонецЦикла;
    ТаблицаДополнений = Движения.ОсновныеНачисления.ПолучитьДополнение(); Для каждого СтрокаДополнения Из ТаблицаДополнений Цикл
    Движение = Движения.ОсновныеНачисления.Добавить(); ЗаполнитьЗначенияСвойств(Движение, СтрокаДополнения);
    Движение.Сторно = Истина;
    Движение.ПериодДействияНачало = СтрокаДополнения.ПериодДействияНачалоСторно; Движение.ПериодДействияКонец = СтрокаДополнения.ПериодДействияКонецСторно; Движение.ПериодРегистрации = СтрокаДополнения.ПериодРегистрацииСторно;
    КонецЦикла;
    Движения.Записать();
    РасчетЗП.РассчитатьРегистрРасчета(Движения.ОсновныеНачисления, Отказ);
    РасчетЗП.РассчитатьРегистрРасчета(Движения.ДополнительныеНачисления, Отказ);
    КонецПроцедуры 

    Добавил общий модуль РасчетЗП, в котором реализовал универсальные алгоритмы расчета: 

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

    Для начисления сдельной оплаты доработал документ «Выпуск продукции». Добавил в документ реквизит ВидРасчета (тип ПланВидовРасчетаСсылка.ДополнительныеНачисления), в котором нужно указывать вид расчета «Сдельная оплата». Добавил табличную часть Исполнители с реквизитами Сотрудник (тип СправочникСсылка.ФизическиеЛица) и КТУ (тип Число). В табличную часть Продукция добавил реквизит Расценка (тип Число). Ввод записей в регистр расчета и их расчет происходят одновременно при проведении документа. В обработку проведения был добавлен код:

    Движения.ДополнительныеНачисления.Записывать = Истина; 
    СуммаВсего = Продукция.Итог("Расценка");
    ОсталосьРаспределитьСумма = СуммаВсего;
    КТУВсего = Исполнители.Итог("КТУ");
    Для Каждого ТекСтрокаНачисления Из Исполнители Цикл
    Движение = Движения.ДополнительныеНачисления.Добавить(); Движение.ПериодРегистрации = НачалоМесяца(Дата);
    Движение.ВидРасчета = ВидРасчета;
    Движение.Сотрудник = ТекСтрокаНачисления.Сотрудник; Движение.Подразделение = Подразделение;
    Если КТУВсего = 0 Тогда
    Движение.Размер = 0;
    Иначе Размер = Окр(ТекСтрокаНачисления.КТУ * СуммаВсего / КТУВсего, 2);
    Движение.Размер = ?(Размер > ОсталосьРаспределитьСумма, ОсталосьРаспределитьСумма, Размер);
    Движение.Результат = Движение.Размер;
    ОсталосьРаспределитьСумма = ОсталосьРаспределитьСумма - Движение.Размер;
    КонецЕсли;
    КонецЦикла; 
    • Код стал выглядеть как-то не очень читаемо. Посоветуйте как лучше оформлять фрагменты кода.

  2. Выполнил.

    Создал предопределенные виды расчета, указанные в задании. Оклад и БольничныйЛист в ПВР ОсновныеНачисления, НадбавкаЗаВредность и СдельнаяОплата соответсвенно в ПВР ДополнительныеНачисления. Создал перечисления ПорядокРасчета со значениями Первичное, ЗависимоеПервогоУровня и СпособыРасчетаОплатыТруда со значениями ПоОтработанномуВремени, Процентом, ПоБольничномуЛисту. Добавил в реквизиты обоих ПВР.

    Изменил обработку по заполнению графика, для заполнения количества часов.

    Доработал документ ВыпускПродукции. В ТЧ продукция добавил реквизит Расценка. Создал ТЧ Исполнители с реквизитами Сотрудник и КТУ. Реализовал расчет сдельной оплаты в соответствии с заданием. При проведении рассчитанные данные записываются в набор записей РР Дополнительные начисления.

    При реализации универсального механизма расчета обращался к материалам базового курса.

  3. Задание выполнил. За основу взял универсальные алгоритмы базового курса. Для решения определил два ПВР:  ОсновныеНачисления с поддержкой периода действия без базы, в него вошли Оклад, Больничный (вытесняет Оклад),  ДополнительныеНачисления без поддержки периода действия, но с базой  ОсновныеНачисления, в него вошли НадбавкаЗаВредность (база Оклад) и СдельнаяОплата.  Записи по СделнаяОплата вводятся непосредственно документом ВыпускПродукции.

  4. Сдельную оплату нужно было встроить в выпуск продукции? Вроде написано, что все цифры для расчёта вводит расчётчик ЗП?

  5. Задание выполнил.
    Создал перечисление ВидыРасчета добавил туда записи по видам расчета. Добавил новый реквизит в Планы видов расчета СпособоРасчета. Добавил предопределенные элементы в планы расчета.
    Доработал документ выпуск продукции – добавил поле Расценка, и табл часть для указания исполнителей и КТУ. Проведение по рег.расчета сделал в модуле документа ВыпускПродукции.
    Универсальные алгоритмы взял из конфигурации с примерами 4 го блока. Доработал в соотв со способами расчета.
     

  6. Задание выполнено.

    1. Очистил РС ГрафикиРаботы, внес изменения в обработку ЗаполнениеГрафика для реализации почасового учета и заполнил графики.
    2. Создал перечисление КатегорияРасчета со значениями: Первичное, ЗависимоеПервогоУровня и добавил в ПВР ОсновныеНачисления и Дополнительные Начисления. Также создал перечисление СпособыРасчета со значениями: ФиксированнойСуммой, Процентом, ПоСтавке и добавил реквизит со ссылкой на это перечисление в ПВР.
    3. Добавил предопределенные элементы в ПВР Основные начисления:
    – Оклад по часам, способ расчета – ПоСтавке, категория – Первичное, вытесняется ВР – Оплата по Больничному листу.
    – Оплата по больничному листу, способ расчета – Процентом, категория – Зависимое первого уровня (базовый и ведущий ВР: Оклад по часам),
    4. Добавил предопределенные элементы в ПВР Дополнительные начисления:
    – Надбавка за вредность, способ расчета – Процентом, категория – Зависимое первого уровня (базовый ВР: Оклад по часам), зависимость от базы в ПВР – “Зависит по периоду регистрации”.
    – Сдельная оплата, способ расчета – Фиксированной суммой (рассчитанное значение передается в РР в виде готовой суммы), категория – Первичное.
    5. Для универсального расчета ЗП в общем серверном модуле РасчетЗП создал функцию РасчитатьЗаписьРегистраРасчета(), в которой в зависимости от вида расчета (ОсновныеНачисления или ДополнительныеНачисления) и категории расчета, формируется запрос (во многом скопировал его с запроса в базовом курсе, внеся небольшие изменения). На основании полученного результата запроса и в зависимости от способа расчета вычисляю результат.
    6. Добавил справочник СдельныеРасценкиРабот.
    7. Для расчета сдельной заработной платы использовал документ ВыпускПродукции из прошлого ДЗ. Добавил в него ТЧ Сотрудники с реквизитами Сотрудник и КТУ. В ТЧ Продукция добавил реквизит СдельнаяРасценка. При проведении получаю общую стоимость выпущенной продукции и распределяю по КТУ. Полученный результат записывается в НаборЗаписейДополнительныеНачисления.

  7. 1.Создал перечисление “СпособрРасчёта”, заполнил перечисление 4 именами методов расчёта новых арсчётов. Создал одноимённый реквизит в 2 планах видов расчёта. Создал общий модуль – серверный “РасчётЗП”. Cоздал новый план видов расчёта “”ДополнительныеНачисленияПериодРегисьтрации” настроеный на расчёт по периоду регистрации.  Создал одноимённый регистр расчёта аналогичный “ДополнительныеНачисления” , но с ещё 1 реквизитом (Участие – Число 6.4).
    2.В документе “НачислениеЗаработнойПлаты” добавил 2 абличных части “ДополнительныеНачисления” и “”ДополнительныеНачисленияПериодРегистрации” заполненых реквизитами соответствующим образом и доработал процедуру “ОбработкаПроведения” на сохранение данных из 2 добавленых таблиц. Запустил программу. Создал новые виды расчёта и настроил их (способ, категория, база, вытесняющие и т.п….). 3.Реализовал универсальный алгоритм расчёта записей регистра расчёта (как и в
    учебном примере (через 2 процедуры и 2 функции)).  Процедуру “РасчитатьРегистрРасчёта”
    вызываю 3 раза (по кол-ву регистров начисления) из процедуры “ОбработкаПроведения” документа “РасчетЗП” после сохранения движений по регистрам. В базовом курсе мы очень похожий универсальный механизм реализовывали, но немного по другому (не использовали метаданные и т.п.).

    • есть вопрос: образцовые решения теперь смотрим из публикаций для потока №1?

      • Можно взять и оттуда :)
        А вообще и для вашего потока такие же решения будут появляться :)

        • Ещё 2 вопроса:  сколько ДЗ осталось?
          Глава №7 (“Кейсы”) последняя?

        • Видимо 2 поток не успею дождаться – уже предупредили, что для окончания доступа к МГ осталось 7 дней.
          Для выполнения финала доспут буден продлён?

  8. Выполнил.
    1.В ПВР ОсновныеНачисления создал предопределенные виды расчета: БольничныйЛист и ОкладПоЧасам (вытесняющие,ведущие – БольничныйЛист), и в ПВР ДополнительныеНачисления – НадбавкаЗаВредность (базовые – ОкладПоЧасам, ведущие – оба ВР из ПВР ОсновныеНачисления) и СдельнаяОплата. В оба ПВР добавил реквизит СпособРасчета – ссылка на перечисление(ПоОтработанномуВремени, ПоБольничномуЛисту, Процентом).
    2.Подправил обработку ЗаполнениеГрафика – в Значение заносится количество рабочих часов.
    3.Для расчета ЗП по ВР СдельнаяОплата скорректировал документ ВыпускПродукции – в ТЧ Продукция добавил реквизит Расценка и добавил ТЧ Оплата(сотрудник,КТУ). При проведении заполняю и записываю набор записей РР.
    4.В документ НачислениеЗП добавил ТЧ ДопНачисления (без типа графика и дат). При проведении для ВР БольничныйЛист заменяю тип графика на пятидневку, для вычисления базы для надбавки – заполняю базовый период как начало и конец месяца от ПериодРегистрации.
    5.Универсальный алгоритм расчета ЗП был взят из базового курса. Внес в него мелкие изменения по больничному листу.

  9. Создал перечисление «Способы расчета» и добавил его как реквизит во все планы видов расчета.
    Скопировал из базового курса общий модуль расчет  ЗП. В плане видов расчета «Основные начисления» убрал зависимость от базы и добавил предопределенные виды расчета «Оклад по часам», «Больничный лист» и «Сдельная». И хотя вид расчета «Сдельная оплата» не использует период действия, но, посчитав, что отдельный план видов расчета для него создавать избыточно, к тому же по логике его можно отнести к основным начислениям, добавил его именно в этот план.  Для ВР оклад настроил его вытеснение больничным листом.
    В план видов расчета «Дополнительные начисления» добавил вид расчета «Надбавка за вредность». Поскольку в задании сказано: «Рассчитывается как процент  от начисленного оклада в текущем периоде», зависимость от базы для ПВР установил в «Зависит по периоду регистрации». В качестве базы для надбавки указал оклад.
    Подкорректировал процедуру «РассчитатьРегистрРасчета» из общего модуля «Расчет ЗП» отразил специфику расчета оклада и больничного, обеспечил вызов этой процедуры в обработке проведения документа «Начисление ЗП».
    Для ввода надбавки использовал документ «Регистрация разовых начислений», который довольно успешно скопировал из конфигурации базового курса (да здравствует Копипаст J).
    Осталось реализовать последний вид расчета «Сдельная оплата» для его записи идеально подходит документ «Выпуск продукции», созданный при выполнении прошлых ДЗ. Причем рассчитывать данный вид расчета, также имеет смысл в обработке проведения данного документа, а не в общей процедуре поскольку этот вид расчета не использует ни данные базы, ни данные графика, то реализовывать его расчет в универсальных алгоритмах можно, но вряд ли нужно, поскольку кроме усложнения алгоритмов больше никаких преимуществ это не даст. В документ «Выпуск продукции» в ТЧ «Продукция» добавил реквизиты «Расценка выпуска цена» и Расценка выпуска сумма», и новую ТЧ «Работники» с реквизитами «Сотрудник» и «КТУ».
    Поскольку вид расчета «Сдельная оплата» не использует период действия и  для него имеет смысл запись и расчет проводить в один этап, хотел использовать  команду Записать в виде Записать(,Истина). Но при выполнении данной команды появилось сообщение «Необходим перерасчет фактического периода действия», т.е. все таки надо сначала просто  Записать без параметров, что и сделал рассчитав и заполнив сразу результат, дабы не записывать второй раз. При следующем проведении получил сообщение об ошибке «Неверно задан период действия», пришлось при записи движений указывать ПериодДействияНачало и ПериодДействияКонец хотя он не имеет смысла для данного вида расчета, но как говорится издержки производства, раз добавил его в ПВР использующий период действия значит надо заполнять. После соответствующих изменений все заработало.