Продвинутый курс. Занятие №18

Заключительное занятие 4-го блока продвинутого курса по программированию.

Необходимо изучить следующие главы текущего блока.
Глава 5. Перерасчеты
Глава 6. Диаграмма Ганта

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

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

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

комментариев 12 на “Продвинутый курс. Занятие №18”

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

    Расчет отпуска реализован стандартно. Проблем не возникло.
    В остальном подглядел решение, каюсь.

  2. С первой частью задания проблем особых не возникло. Отработанные дни учитываются в дополнительном ресурсе регистра расчета. Доработки при проведении незначительны.
    Во второй части даиграмма по начислениям построилась, но возникла сложность с редактированием интервалов пользователем. После просмотра решения ситуация прояснилась

  3. Задание выполнила.
    1)Для отпуска – добавила новый способ “ПоСреднему”, прописала алгоритм, проставила параметр “База” в Истина. При проведениие документа для отпуска указываю базу предыдущие 3 месяца.
    2)Как то сложновато получилось, но реализовала. В табличных частях документа по 2 новых поля(Результат, РучноеИсправление), в регистрах расчета реквизит НомерСтрокиДокумента. Добавила команду Расчитать, по ней делаю весь расчет как раньше в обработке проведения в 2 этапа, потом запросом из регистров расчета по регистратору выбираю результат и помещаю его в документ если не установлен флаг РучноеИсправление(все это в экспортной процедуре общего модуля), движения на этом этапе очищаю. При проведении проверяю рассчитан ли документ, если да – провожу просто занося уже расчитанный результат в регистры.
    3)Построение самого отчета взяла из уроков. В расшифровку интервала добавила структуру периодов действия из регистра. Для корректировки записи в регистре расчета при редактировании интервалов использую событие ДиаграммаПриОкончанииРедактированияИнтервала. В нем заполняю структуру
    ПараметрыКорректировки = Новый Структура;
    ПараметрыКорректировки.Вставить(“ДокСсылка”, Интервал.Значение.Расшифровка);
    ПараметрыКорректировки.Вставить(“ВидРасчета”, Интервал.Значение.Серия.Значение);
    ПараметрыКорректировки.Вставить(“Сотрудник”, Интервал.Значение.Точка.Значение);
    ПараметрыКорректировки.Вставить(“ПериодДействияНовый”, Новый Структура(“ПериодДействияНачало,ПериодДействияКонец”,Интервал.Начало,Интервал.Конец));
    ПараметрыКорректировки.Вставить(“ПериодДействияСтарый”, Новый Структура(“ПериодДействияНачало,ПериодДействияКонец”,Интервал.Расшифровка.ПериодДействияНачало,Интервал.Расшифровка.ПериодДействияКонец));
    Потом в процедуре на сервере нахожу нужный документ, меняю там в нужной строку период действия, расчитываю, записываю его и провожу, отчет переформировываю.

  4. Задание выполнила. Создала новый вид расчета “Отпуск”, новый способ расчета “по среднему заработку”, начисление провожу документом “Начисление заработной платы”. При проведении записываю в регистр базовый период. Данные об отработанном времени беру из  данных графика за базовый период. По второй части: в табличной части документа начисления заработной платы создаю 2 новых реквизита “Ручная корректировка” и “Сумма”, при редактировании суммы устанавливается признак ручной корректировки и автоматический расчет для этой строки не происходит. Третья часть задания: Для пересчета записей ссылку на регистратор записываю в расшифровку значения, а номер строки – в расшифровку интервала.

  5. respublica 22.07.2011 в 16:42

    Задание выполнено.
    1. Для расчета отпуска ввел новый документ НачислениеОтпускаСотруднику, в котором создал 2 таб. части: “РасчетСреднего” и “Начисления”, а также реквизит СредневнойЗаработок, который рассчитывается при заполнении таб. части “Расчет..” и является основой для заполнения реквизита Размер регистра расчета. Для отпуска не стал вводить новый способ расчета, так как для него подходит способ “по отработанному времени”. Для проверки расчета ввел реквизит регистра расчета ОтработаноДней.
    2. Для просмотра и правки результата расчета ввел в таб. части документа по начислению 2 реквизита РассчитанАвтоматически и Результат. Для заполнения этих реквизитов ввел еще один реквизит регистра расчета НомерСтрокиИзДокумента. С программированием проблем не возникло.
    3. Сам вывод диаграммы Ганта хорошо показан в уроках. При настройке редактирования интервала я сначала пытался править записи регистра расчета, но этот путь оказался тупиковым, так как при перепроведении документа изменения затираются. Поэтому я просто меняю даты периода действия в строке таб. части документа и перепровожу его. Кстати, в этот момент пожалел, что ввел отдельный документ для расчета отпуска…

  6. Задание №18 выполнено.
    С начислением отпускных каких-то проблем не возникло. Для учета кол-ва отработанных дней завел еще один ресурс в регистре расчета ОсновныеНачисления. Базовый период определяется автоматически как 3 месяца, предшествующие периоду действия.
    Для просмотра результата расчета в документе начисления в табл. частях Начисления и Удержания завел реквизит Результат (а также реквизит Дней для начислений). Расчет происходит так же как и раньше при проведении, то есть записываются записи в регистр, рассчитываются, результат заносится в табл. часть и движения регистра уничтожаются. При проведении теперь записи создаются сразу с полной информацией и какого-то дополнительного расчета не происходит.
    С отчетом по начислениям возникли сложности. Сама диаграмма построилась без каких-то проблем, данные получаются запросом, в качестве точек выступают подразделения, у них есть подчиненные точки – сотрудники. В качестве серий – виды расчета. Дополнительно в расшифровке для интервала периода хранятся данные о документе-регистраторе и строке документа, соответствующей данному интервалу. Все это хранится в структуре и проблема состояла в том, что при получении расшифровки в обработчике события редактирования интервала ссылка на регистратор почему-то исчезала из структуры, точнее ключ оставался, а значение становилось Неопределено, причем номер строки оставался как и положено. Поведение мне непонятно, при формировании диаграммы значение в структуру запиывается корректно (проверял в отладчике). Как-то победить это мне не удалось, поэтому данные о документе пришлось хранить в виде трех значений – идентификатора вида документа, его номера и даты. Код процедуры формирования диаграммы:
    <code>
    &НаСервере
    Процедура СформироватьНаСервере()
    Запрос = Новый Запрос(”
    |ВЫБРАТЬ
    |    ОсновныеНачисления.Сотрудник КАК Сотрудник,
    |    ОсновныеНачисления.Подразделение КАК Подразделение,
    |    ОсновныеНачисления.ВидРасчета,
    |    ОсновныеНачисления.ПериодДействияНачало,
    |    ОсновныеНачисления.ПериодДействияКонец,
    |    ОсновныеНачисления.Регистратор,
    |    ОсновныеНачисления.НомерСтроки
    |ИЗ
    |    РегистрРасчета.ОсновныеНачисления КАК ОсновныеНачисления
    |ГДЕ
    |    ОсновныеНачисления.ПериодДействияНачало >= &НачалоПериода
    |    И ОсновныеНачисления.ПериодДействияКонец <= &КонецПериода
    |
    |ИТОГИ ПО
    |    Подразделение,
    |    Сотрудник”);
    Запрос.УстановитьПараметр(“НачалоПериода”, Период.ДатаНачала);
    Запрос.УстановитьПараметр(“КонецПериода”, Период.ДатаОкончания);

    Диаграмма.Очистить();
    ВыборкаПодразделения = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Пока ВыборкаПодразделения.Следующий() Цикл
    ТочкаПодр = Диаграмма.УстановитьТочку(ВыборкаПодразделения.Подразделение);

    ВыборкаСотр = ВыборкаПодразделения.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Пока ВыборкаСотр.Следующий() Цикл
    Точка = ТочкаПодр.Точки.Добавить();
    Точка.Значение = ВыборкаСотр.Сотрудник;
    Точка.Текст = ВыборкаСотр.Сотрудник.Наименование;

    ВыборкаВР = ВыборкаСотр.Выбрать();
    Пока ВыборкаВР.Следующий() Цикл
    Расшифровка = Новый Структура;
    Расшифровка.Вставить(“РегистраторИмя”, ВыборкаВР.Регистратор.Метаданные().Имя);
    Расшифровка.Вставить(“РегистраторНомер”, ВыборкаВР.Регистратор.Номер);
    Расшифровка.Вставить(“РегистраторДата”, ВыборкаВР.Регистратор.Дата);
    Расшифровка.Вставить(“НомерСтроки”, ВыборкаВР.НомерСтроки);

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

  7. Готово!
    С расчетом отпускных проблем особых не возникло.
    Немного пришло помучиться с отображением результата в форме документа, т.к. пришлось поменять схему проведения + учесть занесение в регистр исправленных результатов.
    С отчетом вышла оказия. Видимо, я неправильно понял задание по отчету и сделал его по аналогии с уроками. В решении же все иначе.
    Проверку на корректность периодов я сделал только для оклада, используя Месяц() для начала и конца интервала. Опять же, ступил и как было в задании написано (но там-то в качестве примера), так и сделал. Видимо, сказывается усталость и какие-то моменты из задания просто упускаешь из виду.  :(

  8. Для получения фактически отработанного времени при расчете отпуска в регистр расчета добавлен ресурс, который хранит число отработанных часов. Механизм ручной корректировки результатов документа “Начисление зарплаты” позаимствовал из типовых конфигураций (в простейшем виде). В документ добавлен булевский реквизит “РучнаяКорректировка”, который выведен на форму документа. Кроме того, в качестве табличных частей на форму выведены движения документа. При снятой галочке “Ручная корректировка” записи можно только просматривать, при установленной – появляется возможность редактирования. При проведении документа проверяется наличие галочки: если она снята, то движения документа очищаются и формируются заново. Если установлена – то в результате проведения остаются движения, указанные пользователем в табличных частях. Создан отчет в виде диаграммы Ганта, с возможностью редактирования интервалов. В расшифровке сохраняются регистратор, номер строки, которые затем анализируются в событии “ПриОкончанииРедактированияИнтервала” для перерасчета набора записей регистра расчета. Долго мучался с проблемой потери расшифровки при повторном программном формировании отчета, к сожалению, не хватило терпения самостоятельно решить эту проблему.

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

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

    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

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

    Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
    Запрос.УстановитьПараметр(“Оклад”, ПланыВидовРасчета.ОсновныеНачисления.Оклад);
    Запрос.УстановитьПараметр(“Отпуск”, ПланыВидовРасчета.ОсновныеНачисления.Отпуск);

    Запрос.Выполнить();
    Возврат МенеджерВТ;
    КонецФункции

    В табличную часть документа начисления добавим реквизит Результат и для удобства приведем названия реквизитов в соответствие с регистром расчетов. Вынесем запись движений из обработки проведения в экспортную функцию ЗаписьДвижений(), добавим запись реквизита Результат. В конце обработки проведения перезаполняем ТЧ:

    Процедура ОбработкаПроведения(Отказ, Режим)
    ЗаписатьДвижения();
    РасчетЗП.РассчитатьРегистрРасчета(Движения.ОсновныеНачисления, Отказ);
    РасчетЗП.РассчитатьРегистрРасчета(Движения.ДополнительныеНачисления, Отказ);
    Если не Отказ тогда
    ПерезаполнитьТЧ();
    КонецЕсли;
    КонецПроцедуры

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

    Запрос.Текст=”ВЫБРАТЬ * ИЗ Начисления КАК Начисления”;
    Начисления.Загрузить(Запрос.Выполнить().Выгрузить());

    Запрос.Текст=”ВЫБРАТЬ * ИЗ Удержания КАК Удержания”;
    Удержания.Загрузить(Запрос.Выполнить().Выгрузить());
    КонецПроцедуры

    Чтобы обеспечить возможность ручной правки результата, добавим команду формы Записать и серверную процедуру ЗаписатьНаСервере():
    &НаСервере
    Процедура ЗаписатьНаСервере();
    Документ=РеквизитФормыВЗначение(“Объект”);
    Документ.ЗаписатьДвижения();
    КонецПроцедуры

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

    &НаКлиенте
    Процедура ДиаграммаПриОкончанииРедактированияИнтервала(Элемент, Интервал, ОтменаРедактирования)
    Если НачалоМесяца(Интервал.Начало)<>НачалоМесяца(Интервал.Конец) тогда
    Сообщить (“Ошибочный интервал”);
    ОтменаРедактирования=истина;
    Иначе
    ЗначениеИнтервала=Интервал.Значение;
    ТочкаИнтервала=ЗначениеИнтервала.Точка;
    СерияИнтервала=ЗначениеИнтервала.Серия;

    Данные=Новый Структура();
    Данные.Вставить(“Начало”, Интервал.Начало);
    Данные.Вставить(“Конец”, Интервал.Конец);
    Данные.Вставить(“Регистратор”, ЗначениеИнтервала.Расшифровка);
    Данные.Вставить(“Сотрудник”, ТочкаИнтервала.Значение);
    Данные.Вставить(“Подразделение”, ТочкаИнтервала.Родитель.Значение);
    Данные.Вставить(“ВидРасчета”, СерияИнтервала.Родитель.Значение);

    ЗначениеСтарогоИнтервала=Диаграмма.ПолучитьЗначение(ТочкаИнтервала,СерияИнтервала);

    Для каждого ЭлементИнтервала из ЗначениеСтарогоИнтервала цикл
    Если ЭлементИнтервала.Расшифровка=Интервал.Расшифровка тогда
    Данные.Вставить(“НачалоСтароеЗначение”, ЭлементИнтервала.Начало);
    Данные.Вставить(“КонецСтароеЗначение”, ЭлементИнтервала.Конец);
    КонецЕсли;
    КонецЦикла;

    КорректировкаЗаписиНаСервере(Данные);
    КонецЕсли;
    СформироватьНаСервере();
    КонецПроцедуры

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