В регистре расчетов должно получиться примерно следующее.

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

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

Определим у каждого измерения перерасчета следующие свойства.

Заполним предопределенную табличную часть Ведущие виды расчета вида расчета «ПремияПроцентом» в плане видов расчета «ВсеВидыРасчета» следующим образом:

70
Решение задачи
Теперь при изменении записи регистра расчетов, содержащей «Оклад» (естественно, запись должна попадать в базовый период «ПремииПроцентом»), таблица «Перерасчета» будет заполняться строками, каждая из которых будет представлять собой набор сведений о виде расчета и документе-регистраторе записи регистра расчета, которую нужно пересчитать. Также в таблице будут присутствовать измерения перерасчета.
При регистрации перерасчетов не будет происходить изменения ни текущего набора записей, ни наборов записей других регистраторов.
Помимо автоматической регистрации перерасчетов существует возможность их программной регистрации (т.е. в таблицу Перерасчета можно вводить записи и самим из программного кода).
Чтобы обработать таблицу перерасчета, нужно программно выполнить ряд действий, связанных, например, с чтением из таблицы перерасчета информации о перерасчетах, перепроведением (точнее «частичным» перепроведением) документа-регистратора пересчитываемой записи, вводом документов-перерасчетов, очисткой (корректировкой) перерасчета, отказом от перерасчета и т.д.
Замечание. Нужно понять, что принцип работы перерасчетов в системе «1С:Предприятие 8.0» является «уведомительным». Т.е. мы сами в процессе конфигурирования будем решать, заниматься ли нам вводом корректирующих записей или перерасчетом ресурсов затронутых перерасчетами учетных записей, а можем просто «не обращать внимания» на сведения, которые предоставляет нам система в таблице перерасчета, то есть отказаться от пересмотра результатов расчета. Напомним, что в версии 7.7 разработчик конфигурации не мог управлять процессом перерасчета записей журнала расчетов (он мог лишь создавать или не создавать правила перерасчета).
Для работы с перерасчетами из встроенного языка используются следующие объекты:
71
Сонфигурирование в системе "1С: Предприятие 8.0". Решение расчетных задач

Представим объекты Перерасчетов в виде таблицы.
72


Решение задачи
Для того, чтобы использовать «Перерасчет» в нашей конфигурации, =у придется создать ряд новых объектов и внести изменения в существующие алгоритмы:
создадим обработку, в которой будет проверяться «актуальность» расчетов (при изменении «Оклада» в обработке должны будут отображаться те записи регистра расчета, которые необходимо будет пересчитать - т.е. «ПремииПроцентом»),
создадим константу «Дата запрета редактирования». Эта константа будет определять «закрытие» периода. Записи регистра расчета с периодом регистрации меньше (или равно) «Даты запрета редактирования» редактировать будет нельзя. Записи регистра расчета с периодом регистрации меньше (или равно) «Даты запрета редактирования» будут считаться архивными, их нельзя будет редактировать. Для пересчета таких записей будем создавать новый документ-перерасчет, внесем изменения в модуль документа «Начис л ениеЗарпл атыВ сей».
Константа «Дата запрета редактирования»
Создадим константу с именем «ДатаЗапретаРедактирования» типа Дата.
Вставим новую константу в форму констант.
Обработка «Перерасчет зарплаты»
Создадим обработку «Перерасчет зарплаты». Основные свойства.
Имя: «ПерерасчетЗарплаты»
о Табличные части: ДокументыПерерасчета. Реквизиты табличной части:
Формы: Форма.
Вставим в диалог Формы табличное поле и свяжем его с табличной частью отчета ДокументыПерерасчета.
Используем еще одну возможность системы «1С:Предприятие 8.0», для реализации которой в 7.7 потребовалось бы немало потрудиться.
Попробуем отобразить в колонке Документ (типа ДокументСсылка) табличного поля флажок, в котором можно поставить пометку. Причем этот флажок свяжем с данными - с реквизитом табличной части Пометка.
75
В результате дальнейших действий должно получиться так:

Удалим все колонки из табличного поля. Через меню «Форма»-«Размещение данных» вставим в табличное поле колонку Документ как поле ввода.

В окне свойств поля ввода Документ изменим свойство Элемент управления на Флажок (см. картинку ниже). А в свойстве Данные флажка выберем значение Пометка (см. вторую картинку ниже).

На закладке Характеристики окна свойств поля ввода Документ установим свойство Режим редактирования: Непосредственно.
Перейдем к следующим объектам.
Создадим элемент управления Командная панель с кнопками:
76
Решение задачи

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

В результате должна получиться примерно такая форма:
В модуле формы запишем процедуры
77
Процедура ПередОгкрытием(Отказ, СтандартнаяОбработка) ЗаполнитьДанныеО;
КонецПроцедуры
Комментарии. Нужно не забыть назначить обработчик события Перед Открытием Формы (в разделе свойств События формы необходимо выбрать событие ПередОткрытием).
Процедура ЗаполнитьДанныеО Экспорт Запрос = Новый Запрос(
"ВЫБРАТЬ РАЗЛИЧНЫЕ
I ИСТИНА КАК Пометка,
1 ОбъектПерерасчета КАК Документ
ИЗ
I РегистрРасчета.РасчетыВсе.Перерасчет
I");
ДокументыПерерасчета.Загрузить(Запрос.Выполнить().Выгрузить()); КонецПрощедуры
Комментарии.
В процедуре Заполнить Данные мы использовали запрос к таблице «Перерасчета». Вообще таблица объекта «Перерасчет» имеет следующий состав полей.

Интересно первое поле в представленном запросе - ИСТИНА КАК Пометка. Это означает, что в результат запроса будет добавлена колонка с названием Пометка, содержащая значения Истина.
Результат запроса выгружается в табличное поле ДокументыПерерас чета.
Для оперативного обновления содержания табличного поля в процедуре «ОбновитьПерерасчеты», связанной с кнопкой «Обновить список» поместим следующее.
Процедура ОбнсвитъПерерасчеты(Кнопка)
ЗаполнитьДанные(); КонецПро цедуры
Назначим обработчик события ПриАктивизацииСтроки у табличного
поля ДокументыПерерасчета. В процедуре
78
Решение задачи
ДокументыПерерасчетаПриАктивизацииСтроки следующее.
запишем
Процедура ДокументыПерерасчетаПриАктивизацииСтроки(Элемент) Если Элемент.ТекущиеДанные = Неопределено Тогда СтрокиПерераечета.ОчиститьО; Возврат; КонецЕсли;
ОбновитьСписокПерерасчетов(Элемент.ТекущиеДанные.Документ); КонецПроцедуры
Процедура ОбновитьСписокПерерасчетов(Документ)
НаборПерерасчета РегистрыРасчета.РасчетыВсе.Перерасчеты.Перерасчет,СоздатьНаборЗаписей();
НаборПерерасчета. Отбор.ОбъектПерерасчета.Значение = Документ;
НаборПерерасчета.Прочитать();
СтрокиПерерасчета.ОчиститьО;
Для Каждого Строка Из НаборПерерасчета Цикл
СтрокаТЗ=СтрокиПерерасчета.Добавить();
СтрокаТЗ.ВидРасчета=Строка.ВидРасчета;
СтрокаТЗ.Подразделение=Строка.Подразделение;
СтрокаТЗ.Должность=Строка.Должность;
СтрокаТЗ.Сотрудник=Строка.Сотрудник; КонецЦикла; КонецПроцедуры
Теперь при установке курсора на какую-либо строку табличного поля ДокументыПерерасчета, табличное поле СтрокиПерерасчета автоматически будет заполняться перерасчетами из набора перерасчетов объекта «Перерасчет», соответствующих документу из табличного поля ДокументыПерерасчета.
В процедуре ОткрытъДокумент, связанной с кнопкой «Открыть документ», запишем алгоритм, позволяющий открыть форму документа, на котором стоит курсор в табличном поле ДокументыПерерасчета.
Процедура ОткрытьДокумент(Кнопка)
Если ЭлементыФормы, ДокументыПерерасчета. ТекущиеДанные
НЕОПРЕДЕЛЕНО Тогда
о
ЭлементыФормы.ДокументыПерерасчета.ТекущиеДанные.Документ.ПолучитьФор му(). Открыть();
КонецЕсли; КонецПроцедуры
В процедуре ПометитьВсе связанной с кнопкой «Пометить все», запишем алгоритм, позволяющий установить флажки во всех строках
79
Конфигурирование в системе "1С:Предприятие 8.0". Решение расчетных задач
табличного поля ДокументыПерерасчета. В процедуре СнятьПометпки связанной с кнопкой «Снять пометки», запишем алгоритм, позволяющий снять все флажки.
Процедура ПометигьВсе(Кнопка)
Для Каждого СтрокаТаблицы Из ДокументыПерерасчета Цикл СтрокаТаблицы.Пометка = Истина;
КонецЦикла; КонецПроцедуры
Процедура СнягьПометки (Кнопка)
Для Каждого СтрокаТаблицы Из ДокументыПерерасчета Цикл СтрокаТаблицы.Пометка = Ложь;
КонецЦикла; КонецПроцеду'ры
Проверим работу формы в режиме исполнения. Выполним следующие действия:
При этой система автоматически введет новый перерасчет (фактичеси будет введен сигнал о том, что необходимо пересчитать «ПремикюПроцентом» по данной комбинации измерений перерасчета). Чтобы убедиться в этом, сформируем запрос к таблице «Перерасчета» с помощью» отчета «Знакомство с запросом».
Текст запроса.
ВЫБРАтЬ *=
ИЗ
РегистрРасчетаРасчетыВсе.Перерасчет
3. Откройте обработку ПерерасчетЗарплаты.
Должна получиться примерно такая картинка.
80
Таблица результатов запроса:


Решение задачи
При нажатии на кнопку «Выполнить перерасчет» вызывается процедура ВыполнитъПерерасчет.
Процедура ВыполнитьПерерасчет(Кнопка) Экспорт
Для Каждого СтрокаТаблицы Из ДокументыПерерасчета Цикл Если СтрокаТаблицы.Пометка Тогда
Попытка // если не запрещено редактиование документа - выполним перерасчет
Если СтрокаТаблицы.Документ.ПериодРегистрации Константы.ДатаЗапретаРедактирования.ПолучитьО Тогда
СтрокаТаблицы.Документ.ПолучитьОбъект().Перерассчитать();
Сообщить("Перерасчитан документ " +
СтрокаТаблицы.Документ);
// иначе - введем документ перерасчета
Иначе СтрокаТаблицы.Документ.ПолучитьОбъект().ВвестиПерерассчет();
Сообщить("Введен перерасчет документа " +
СтрокаТаблицы.Документ);
КонецЕсли; Исключение
Сообщить(ОписаниеОшибки());
Сообщить("Документ " + СтрокаТаблицы.Документ+ " не может быть перерасчитан автоматически");
КонецПопытки;
КонецЕсли; КонецЦикла;
КонецПроцедуры
Комментарии.
81
В данной процедуре для каждой отмеченной флажком строки табличного поля ДокументыПерерасчета выполняется попытка:
Рассмотрим оба этих действия детально. Перерасчет документа
Для выполнения перерасчета документа необходимо поместить в модуль документа «НачислениеЗарплатыВсей» процедуру Пересчитать (с ключевым словом Экспорт).
Текст процедуры следующий.
Процедура Пересчитать() Экспорт НачатьТранзакцию();
НаборПерерасчетов =
РегистрыРасчета.РасчетыВсе.Перерасчеты.Перерасчет.СоздатьНаборЗаписей();
НаборПерерасчетов.Отбор.ОбъектПерерасчета.Значение = Ссылка;
НаборПерерасчетов.Прочитать(); РВсеМенеджер=РегистрыРасчета.РасчетыВсе;
Отбор= Новый СтруктураО;
Отбор .Вставить("Регистратор",Ссылка);
Ресурсы = Новый Массив(1);
Ресурсы[0] = "РасчетыВсе.Результат";
Измерения= Новый Структура();
Измерения.Вставить("Подразделение","РасчетыВсе.Подразделение");
Измерения.Вставить("Должность","РасчетыВсе.Должность");
Измерения.Вставить("Сотрудник","РасчетыВсе.Сотрудник");
ДанныеБазы = РВсеМенеджер.ПолучитьБазу(Отбор,Ресурсы,Измерения);
Отработано =
РВсеМенеджер.ПолучитьДанныеГрафика(Отбор,ВидПериодаРегистраРасчета.Фактический ПериодДействия);
Норма =
РВсеМенедхер.ПолучитьДанныеГрафика(Отбор,ВидПериодаРегистраРасчета.ПериодРегис
трации);
82
Решение задачи
ОтработаноПоБазе =РВсеМенеджер.ПолучитьДанныеГрафика(Отбор,ВидПериодаРегистраРасчета.БазовыйПер
иод);
Движения.РасчетыВсе.Прочитать();
Таблица = Движения.РасчетыВсе.Выгрузить();
СтруктураПоиска = Новый Структура("Подразделение,Должность,Сотрудник");
Для Каждого СтрокаПерерасчета Из НаборПерерасчетов Цикл
СтруктураПоискаЛодразделение = СтрокаПерерасчетаЛодразделение;
СтруктураПоиска. Должность = СтрокаПерерасчета. Должность;
СтруктураПоиска. Сотрудник = СтрокаПерерасчета.Сотрудник;
//СтрокиПерерасчета = Таблица.НайтиСтроки(СтруктураПоиска);
Для Каждого СтрокаРегистра Из ТаблицаЛайтиСтроки(СтруктураПоиска) Цикл
СтрокаРегистра.Результат
РассчитатьНачисленияУдержания(СтрокаРегистра, ТаблицаЛндекс(СтрокаРегистра),
ДанныеБазы, Отработано,Норма, ОтработаноПоБазе);
КонецЦикла; КонецЦикла;
Движения.РасчетыВсе.Загрузить(Таблица); Движения.РасчетыВсе.Записать(); ЗафиксироватьТранзакциюО; КонецПроцедуры
Комментарии.
В процедуре выполняется выборка записей из «Перерасчета», устанавливается отбор по текущему документу, а затем для каждой из оставшихся после отбора записей «Перерасчета» производится поиск соответствующей записи в регистре расчета «РасчетыВсе». По найденной строке производится перерасчет записи (вызывается уже знакомая нам процедура РассчитатъНачисленияУдержания).
Замечание. Процедура выполняется в транзакции (используются методы НачатъТранзакцию(), ЗафиксироватьТранзакциюО). Это необходимо, т.к. мы хотим быть уверены в неизменности данных, прочитанных нами при перерасчете.
Проверим работу алгоритма на практике.
В режиме исполнения выполним следующие действия:
В результате в строке сообщений появится примерно следующая информация:
83
«Перерасчитан документ Начисление зарплаты всей 6 от 01.01.2003 00:00:00».
В регнсгре расчета «РасчетыВсе» результат премии изменится.
Ввод документа-перерасчета
Для выполнения перерасчета с вводом документов-перерасчетов
необходимо поместить в модуль документа
«НачислениеЗарплатыВсей» процедуру ВвестиПерерасчет (с
ключевым словом Экспорт).
В процедуре ВвестиПерерасчет выполняется создание нового документа (перерасчета) на основании текущего, поэтому в модуль документа «НачислениеЗарплатыВсеи» также необходимо поместить процедуру ОбработкаЗаполнения.
Текст процедуры ОбработкаЗаполнения следующий.
Процедура. ОбработкаЗаполнения(Основание)
ПериодРегистрации = НачалоМесяца(ТекущаяДата()); Дата= ТекущаяДата();
КонецПроцедуры
Текст процедуры ВвестиПерерасчет следующий.
Процедура ВвеетиПерерасчет() Экспорт НачатьТранзакцию();
НаборПерерасчетов =
РегистрыРасчета.РасчетыВсе.Перерасчеты.Перерасчет.СоздатьНаборЗаписей();
НаборПерерасчетов.Отбор.ОбъектПерерасчета.Значение = Ссылка; НаборПерерасчетов.Прочитать();
ДокументПерерасчета = Документы.НачислениеЗарплатыВсей.СоздатьДокумент(); ДокумешПерерасчета.Заполнить(Ссылка); Запрос = Новый Запрос(
"ВЫБРАТЬ
I*
IИ3
|РегистрРасчета.РасчетыВсе
|где РегистрРасчета.РасчетыВсе.Регистратор=парДокументОбъект
||);
Запрос.УстановитьПараметр(" парДокументОбъект", Ссылка); Таблица =Запрос.Выполнить().Выгрузить();
84
Решение задачи
СтруктураПоиска = Новый Структура("Подразделение,Должность,Сотрудник"); Для Каждого СтрокаПерерасчета Из НаборПерерасчетов Цикл
СтруктураПоиска.Подразделение = СтрокаПерерасчетаЛодразделение;
СтруктураПоиска.Должность = СтрокаПерерасчета.Должность;
СтруктураПоиска.Сотрудник = СтрокаПерерасчета.Сотрудник;
Для Каждого СтрокаРегистра Из Таблица.НайтиСтроки(СтруктураПоиска) Цикл
НоваяСтрока = ДокументПерерасчета.Список.Добавить(); НоваяСтрока. Сотрудник = СтрокаРегистра.Сотрудник; НоваяСтрока.ВидРасчета = СтрокаРегистра.ВидРасчета; НоваяСтрока.Подразделение = СтрокаРегистраЛодразделение; НоваяСтрока.Должность = СтрокаРегистра.Должность; НоваяСтрока.График = СтрокаРегистра.График; НоваяСтрока.ВидРасчета = СтрокаРегистра.ВидРасчета;
НоваяСтрока.ДатаНачала =
СтрокаРегистра ЛериодДействияНачало;
НоваяСтрока.ДатаОкончания =
СтрокаРегистра ЛериодДействияОкончание;
НоваяСтрока.Размер = СтрокаРегистра.Результат; НоваяСтрока. Сторно = Истина;
НоваяСтрока = ДокументПерерасчета.Список.Добавить(); НоваяСтрока. Сотрудник = СтрокаРегистра. Сотрудник; НоваяСтрока.ВидРасчета = СтрокаРегистра.ВидРасчета; НоваяСтрока.Подразделение = СтрокаРегистраЛодразделение; НоваяСтрока.Должность = СтрокаРегистра.Должность; НоваяСтрока.График = СтрокаРегистра.График; НоваяСтрока.ВидРасчета = СтрокаРегистра.ВидРасчета;
НоваяСтрока.ДатаНачала =
СтрокаРегистраЛериодДействияНачало;
НоваяСтрока.ДатаОкончания =
СтрокаРегистра.ПериодДействияОкончание;
НоваяСтрока.Размер = СтрокаРегистра.ПараметрРасчета; КонецЦикла; КонецЦикла;
ДокументПерерасчета.Записать(); ЗафиксироватьТранзакцию();
КонецПроцедуры
Комментарии.
В процедуре выполняется выборка записей из «Перерасчета», устанавливается отбор по текущему документу, устанавливается отбор по текущему документу, а затем для каждой из оставшихся после отбора записей «Перерасчета» производится поиск соответствующей
85
Конфигурирование в системе "1 С'Предприятие 8.0". Решение расчетных задач
У\ РшениеЈасчетнш задач
записи в регистре расчета «РасчетыВсе». По найденной строке выполняется программное создание нового документа-перерасчета. В создаваемом документе заполняются две строки табличной части: первая строка является сторнирующей, в неё помещается текущий результат из регистра расчета со знаком «-» и устанавливается признак Сторно. Во второй строке заполняется только параметр расчета, который в последствии используется для расчета результата новой записи.
Замечание. Процедура выполняется в транзакции.
Проверим работу алгоритма на практике.
В режиме ислолнения выполним следующие действия:
В результате в строке сообщений появится примерно следующая информация:
«Введен перерасчет документа Начисление зарплаты всей 6 от 01.01.2003 00:00:00».
Откроем форму списка документа
«НачислениеЗарплатыВсей». Откроем последний
(непроведенный) документ.

Проведем данный документ.
В регистре расчета «РасчетыВсе» появятся две новые записи сторнирующая и запись-перерасчет.
86
Решение задачи

Отчет «Расчеты сотрудников»
Создадим отчет, который бы выдавал нам информацию о состоянии расчетов сотрудников (обо всех начислениях, удержаниях, выплатах) на заданную дату.
В результате работы отчета должно получиться примерно следующее.

Создадим новый отчет, определим его основные свойства.
о «Сотрудник» тип
«СправочникСсылка. Физические Лица»,
Формы: РасчетыСотрудников,
Форма отчета должна выглядеть так.
87


Конфигурирование в системе "1 С:Предприятие 8.0". Решение расчетных задач
Макет: РасчетыСотрудников
В свойствах формы назначим (создадим) у формы обработчик события При открытии. В модуле формы документа в процедуре ПриОткрытии запишем:
Процедура ПриОткрытии()
ДатаОтчета= НачалоМесяца(РабочаяДата); КонецПроцедуры
Дата отчета при открытии всегда будет устанавливаться на начало месяца.
У элемента формы ДатаОтчета назначим обработчик события При изменении. В модуле формы документа в процедуре ДатаОтчетаПриИзменении запишем:
Процедура ДатаОтчетаПриИзменении(Элемент)
ДатаОтчета =НачалоМесяца( ДатаОтчета); КонецПроцедуры
При изменении даты отчета значение реквизита отчета ДатаОтчета всегда будет принимать дискретные значения, соответствующие началу месяца (для данной задачи месяц соответствует периодичности регистра расчета «РасчетыВсе», а начало месяца будет соответствовать периоду регистрации, за который мы и будем формировать отчет).
Решение задачи
В процедуре ОтчетРасчетыСотрудниковВсеНажатие, связанной с кнопкой «Сформировать», напишем.
Процедура КнопкаСформироватьНажатие(Элемент)
ТабДок = Новый ТабличныйДокумент;
ОтчетОбъект.ОтчетРасчетыСотрудниковВсе(ТабДок);
ТабДок. ТолькоПросмотр = Истина;
ТабДок.ОтображатьСетку = Ложь;
ТабДок.ОтображатьЗаголовки = Ложь;
ТабДок.Показать(); КонецПроцедуры
В модуле отчета пометим процедуру ОтчетРасчетыСотрудниковВсе.
Процедура ОтчетРасчетыСотрудниковВсе(ТабДок) Экспорт
Макет = ПолучитьМакет("РасчетыСотрудников");
Запрос = Новый Запрос; ТекстЗапроса = "ВЫБРАТЬ |РасчетыВсе.Подразделение КАК Подразделение, |РасчетыВсе.Должность КАК Должность, |РасчетыВсе.Сотрудник КАК Сотрудник, |РасчетыВсе.ВидРасчета КАК ВидРасчета, |ВЫБОР
|КОГДА ВидРасчета.Тип=Начисления ТОГДА СУММА(РасчетыВсе.Результат)
|КОНЕЦ КАК Начислено, |ВЫБОР
|КОГДА ВидРасчета.Тип=Удержания ТОГДА СУММА(РасчетыВсе.Результат)
|КОНЕЦ КАК Удержано, |ВЫБОР
|КОГДА ВидРасчета.Тип=Выплаты ТОГДА СУММА(РасчетыВсе.Результат)
|КОНЕЦ КАК Выплачено |ИЗ
|РегистрРасчета.РасчетыВсе КАК РасчетыВсе |ГДЕ
|РасчетыВсе.ПериодРегистрации = ДатаОтчета"; Условие=""; Если Сотрудники.Количество() о 0 Тогда
Условие = Условие + " И Сотрудник В Иерархии (СписокСотрудников)";
Запрос.УстановитьПараметр("СписокСотрудников",
Сотрудники.ВыгрузитьКолонкуС'Сотрудник"));
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + Условие;
ТекстЗапроса = ТекстЗапроса +"
89
зирование в системе "1С:Предприятие 8.0"..
|СГРУППИРОВАТЬ ПО
|РасчетыВсе.Подразделение,
|РасчетыВсе.Должность, |РасчетыВсе.Сотрудник, |РасчетыВсе.ВидРасчета
|упорядочить по
|Подразделение,
|Должность,
|Сотрудник
|ИТОГИ СУММА(Начислено),СУММА(Удержано),СУММА(Выплачено) ПО
|Подразделение,
|Должность,
|Сотрудник
|";
Запрос .Текст = ТекстЗапроса; Запрос УстановитьПараметр("ДатаОтчета", ДатаОтчета);
Запрос .УстановитьПараметр("Начисления", Перечисления.ТипыВидовРасчета.Начисление);
Запрос.У становитьПараметрС'Удержания", Перечисления.ТипыВидовРасчета.Удержание);
Запрос .У становитьПараметрС'Выплаты", Перечисления.ТипыВидовРасчета.Выплата); Результат = Запрос.Выподнить();
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок"); ОбластьЗаголовок.Параметры.ДатаОтчета=ДатаОтчета; ОбластьПодразделение = Макет.ПолучитьОбласть("Подразделение"); ОбластьДолжность = Макет.ПолучитьОбласть(" Должность"); ОбластьСотрудник = Макет.ПолучитьОбласть("Сотрудник"); ТабДок.Вывести(ОбластьЗаголовок);
Выбор каПодразделение Результат.ВыбратьСОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПодразделение.Следующий() Цикл
ОбластьПодразделение.Параметры.Заполнить(ВыборкаПодразделение); ТабДок.Вывести(ОбластьПодразделение);
ВыборкаДолжность ВыборкаПодразделение.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаДолжность.Следующий() Цикл
ОбластьДолжность.Параметры.Заполнить (ВыборкаДолжность);
ТабДок.Вывести(ОбластьДолжность); ВыборкаСотрудник = ВыборкаДолжность.Выбрать(); Пока ВыборкаСотрудник.Следующий() Цикл
ОбластьСотрудник.Параметры.Заполнить(ВыборкаСотрудник); ТабДок.Вывести(ОбластьСотрудник);
Решение задачи
КонецЦикла; КонецЦикла; КонецЦикла; КонецПроцедуры
Комментарии.
В процедуре выполняется запрос к регистру расчета «РасчетыВсе». Запрос похож на то, что мы рассматривали ранее. Особый интерес представляют строки запроса:
|ВЫБОР
|КОГДА ВидРасчета.Тип=Начисления ТОГДА СУММА(РасчетыВсе.Результат)
|КОНЕЦ КАК Начислено, |ВЫБОР
|КОГДА ВидРасчета.Тип=Удержания ТОГДА СУММА(РасчетыВсе.Результат)
|КОНЕЦ КАК Удержано, |ВЫБОР
|КОГДА ВидРасчета.Тип=Выплаты ТОГДА СУММА(РасчетыВсе.Результат)
|КОНЕЦ КАК Выплачено
Означает это следующее: операторы ВЫБОР и КОНЕЦ определяют границы условия, в рамках которого используется конструкция КОГДА...ТОГДА...ИНАЧЕ. Читается это примерно так: добавляем в запрос колонку Начислено и помещаем туда результат расчета только тех видов расчета, которые являются начислениями (при этом используем функцию Сумма, соответственно, т.к. дальше в запросе мы используем группировки, по каждой группировочной строке будет автоматически осуществляться суммирование результатов) и т.д.
Затем результат запроса обрабатывается и используется для заполнения табличного документа.
91
Конфигурирование в системе "1С:Предприятие8,0". Решение расчетных задач
Практикум №1
Командировка
Реализуйте возможность начисления сотрудникам организации оплаты за командировку. Оплату командировочных необходимо производить в зависимости от среднего заработка сотрудника за три предыдущих расчетных периода. С этой целью необходимо выполнить следующее:
Вид расчета Командировка
Создайте в плане видов расчета ВсеВидыРасчета предопределенный вид расчета Командировка. Выполните настройку базы вида расчета Командировка, а также настройку вытеснения таким образом, чтобы вид расчета Командировка вытеснял вид расчета Оклад. Для этого определите базовые и вытесняющие виды расчета следующим образом:
[ |
Базовые |
Вытесняющие |
Командировка |
Оклад, ПремияПроцентом |
|
Оклад |
Командировка |
Документ «Командировка»
Создайте документ Командировка.
Создайте реквизиты документа: ПериодРегистрации, ВидРасчета, График, ДатаНачала, ДатаОкончания, ДнейКомандировки, Сотрудник, Подразделение, Должность. Реквизит ДнейКомандировки должен рассчитываться автоматически при заполнении реквизитов ДатаНачала и ДатаОкончания и отражать количество дней по графику работы Шестидневка за период между датой начала и датой окончания командировки
Необходимо создать в справочнике ГрафикиРаботы график Шестидневка с типом графика Шестидневка и не забыть его заполнить.
Запрос по графику работы
Для получения количества отработанных дней по графику работы Шестидневка можно воспользоваться следующей функцией:
Функция ПолучитьКоличествоРабочихДней(ДН,ДК) КоличРабочихДней=0; Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ
92
Решение задачи
| СУММА(ГрафикиРаботы.Значение) КАК Значение
|ИЗ
| РегистрСведений.ГрафикиРаботы КАК ГрафикиРаботы
|
|ГДЕ
| (ГрафикиРаботы.Дата МЕЖДУ ДатаНачала И ДатаОкончания) И
| ГрафикиРаботы.ГрафикРаботы=График
|";
Запрос.УстановитьПараметрС'ДатаНачала", ДН); Запрос.УстановитьПараметр("ДатаОкончания", ДК); Запрос.УстановитьПараметр("График", График); Результат = Запрос.Выполнить(); Если Результат.Пустой() Тогда
Возврат 0; КонецЕсли;
Выборка= Результат.Выбрать(); Пока Выборка.Следующий() Цикл
КоличРабочихДней=Выборка.Значение; КонецЦикла;
Возврат КоличРабочихДней; КонецФункции
Создайте табличную часть Состав документа и в табличной части документа создайте реквизиты: Месяц типа Дата; ОтработаноДней типа Число; Зарплата типа Число. Создайте на командной панели кнопку «Заполнить строки». При нажатии на кнопку необходимо производить заполнение табличной части следующими данными:
Запросы по базе
При заполнении реквизита ОтработаноДней можно воспользоваться следующей функцией:
93
Функция ОгработаноПоБазе(Период)
//анализ фактического периода действия для Оклада
ЗапросФПД = Новый Запрос("ВЫБРАТЬ
| ФПД.ПериодДействияНачало КАК ФПДН,
| ФПД.ПериодДействияОкончание КАК ФПДО
|ИЗ
| РегистрРасчета.РасчетыВсе.ФактическийПериодДействия КАК ФПД
| ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
| РегистрРасчета.РасчетыВсе КАК РасчетыВсе
| ПО РасчетыВсе.Регистратор = ФПД.Регистратор и
| РасчетыВсе.НомерСтроки = ФПД.НомерСтроки
|ГДЕ
| РасчетыВсе. ПериодДействия = Период И
| РасчетыВсе.Должность = Должность И
| РасчетыВсе.Подразделение = Подразделение И
| РасчетыВсе.Сотрудник = Сотрудник И
| РасчетыВсе.ВидРасчета = ВидРасчетаОклад");
ЗапросФПД.УстановитьПараметр("Период", Период);
ЗапросФПД.УстановитьПараметр(" Должность", Должность);
ЗапросФПД.УстановитьПараметр("Подразделение", Подразделение);
ЗапросФПД,УстановитьПараметр("Сотрудник", Сотрудник);
ЗапросФПД.УстановитьПараметр("ВидРасчетаОклад", ПланыВидовРасчега.ВсеВидыРасчета. Оклад);
Результат = ЗапросФПД.Выполнить(); Выборка= Результат.Выбрать();
Отработано=0;
Если Выборка.Количество()=0 Тогда
//анализ периода действия для Оклада
ЗапросПД = Новый Запрос();
В параметрах конструктора запроса (см. строку выше) необходимо написать текст запроса для получения периода действия записи регистра расчета «РасчетыВсе», содержащей внд расчета «Оклад», в рассматриваемом расчетном периоде для выбранного
сотрудника.
Результат = ЗапросПД.Выполнить(); Выбор ка= Результат.Выбрать(); Пока Выборка.Следующий() Цикл
Отработано=Отработано+
ПолучитьКоличествоРабочихДней(Выборка.ПДН,Выборка.ПДО);
КонецЦикла; Иначе
Пока Выборка.Следующий() Цикл
94
Решение задачи
Отработано=Отработано+ ПолучитьКоличествоРабочихДней(Выборка.ФПДН,Выборка.ФПДО);
КонецЦикла; КонецЕсли; Возврат Отработано; КонецФункции // ОтработаноПоБазе()
Комментарии.
В данной функции производится вычисление количества отработанных сотрудником дней за указанный период. Вычисление производится с учетом фактически отработанного сотрудником времени. При этом анализируется запись регистра расчетов, содержащая вид расчета Оклад. Сначала рассматривается фактический период действия записи. Если фактический период действия определен, производится вычисление фактически отработанного сотрудником времени по графику Шестидневка по каждой строке таблицы фактического периода действия, а затем накопление полученных результатов. В том случае, если фактический период действия не определялся, производится анализ записи. Также определяется количество отработанных сотрудником дней по графику Шестидневка.
Замечание. Ранее рассматривался метод ПолучитьДанныеГрафика, с помощью которого можно было очень просто получить количество отработанных сотрудником дней. В данной ситуации воспользоваться этим методом затруднительно, т.к. запись в регистр расчета еще не производилась.
При заполнении реквизита Зарплата можно воспользоваться следующей функцией:
Функция ПолучитьДанныеРасчетнойБазы(Период)
ЗапросБ = Новый Запрос("ВЫБРАТЬ
| СУММА(РасчетыВсе.Результат) КАК Результат
|ИЗ
| ПланВидовРасчета.ВсеВидыРаечета.БазовыеВидыРасчета КАК
ВсеВидыРасчетаБазовыеВидыРасчета
| ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
| РегистрРасчета.РасчетыВсе КАК РасчетыВсе
| ПО РасчетыВсе.ВидРасчета =
ВсеВидыРасчетаБазовыеВидыРасчета.ВидРасчета
|ГДЕ
| РасчетыВсе.ПериодДействия = Период И
| РасчетыВсе.Должность = Должность И
| РасчетыВсе.Подразделение = Подразделение И
| РасчетыВсе.Сотрудник = Сотрудник И
| ВсеВидыРасчетаБазовыеВидыРасчета.Ссылка = Командировка");
ЗапросБ.УстановитьПараметр("Период", Период); ЗапросБ.УстановитьПараметр(" Должность", Должность); ЗапросБ.УстановитьПараметр("Подразделение", Подразделение); ЗапросБ.УстановшъПараметрС'Сотрудник", Сотрудник);
ЗапросБ.УстановитьПараметрС'Командировка", ПланыВидовРасчета.ВсеВидыРасчета.Командировка);
Результат = ЗапросБ.Выполнить(); Если Результат.Пустой() Тогда
Возврат 0; КонецЕсли;
Выборка= Результат,Выбрать(); Пока Выборка,Следующий() Цикл
Зарплата=Выборка.Результат; КонецЦикла; Возврат Зарплата; КонецФункцни // ПолучитьДанныеРасчетнойБазы()
Комментарии.
В данной функции производится суммирование значений ресурса
Результат записей регистра расчета РасчетыВсе, входящих в базу
вида расчета Командировка, за выбранный период для выбранного
сотрудника.
Замечание. Ранее рассматривался метод ПолучитъБазу, с помощью
которого можно было очень просто получить базу для записей
регистра, удовлетворяющих заданному отбору. В данной ситуации
воспользоваться этим методом затруднительно, т.к. запись в
регистр расчета еще не производилась.
Создайте реквизит формы СреднедневнойЗаработок типа Число, а
также элемент управления формы надпись (свойство «Данные»
надписи свяжите с реквизитом формы СреднедневнойЗаработок), в
котором отображайте среднедневной заработок сотрудника за
несколько периодов. Формула для определения среднедневного
заработка должна быть следующая:
СреднедневнойЗаработок = Список.Итог( "Зарплата ")/
Список.Итог(''ОтработаноДней ").
При проведении документа Командировка необходимо вводить вид
расчета Командировка в регистр расчета РасчетыВсе.
В модуле документа Командировка реализуйте алгоритм расчета
результата начисления с учетом среднедневного заработка
сотрудника и количества дней в командировке.
В режиме исполнения назначьте командировку сотрудника Калошину
(Слесарь, Цех 1) с 10 по 20.02.2003г. При этом средний заработок
вычисляйте с учетом данных Января (при необходимости назначьте
Калошину в Январе Оклад, ПремиюПроцентом и Отпуск).
96
Peшeниe задачи
Замечание. В рассмотренной задаче производится попытка "эмулировать" работу функций ПолучитьДанныеГрафика и ПолучитьДанныеРасчетнойБазы. Сложность «ручной» реализации этих методов заставляет задуматься о методической правильности такого подхода. Кроме того, в данном примере для упрощения используется большое количество запросов, что сильно «утяжеляет» решение. Оптимальнее получать все необходимые данные "за один раз", а не "мельчить", создавая сетевой трафик и получая много мелких результатов запроса на клиента (хотя, конечно, всегда найдутся ситуации, когда надо поступать ровно наоборот).
Вывод - старайтесь пользоваться встроенными функциями и не делайте попыток их реализации другими средствами встроенного языка. Помните, что один «большой» запрос гораздо эффективнее нескольких «мелких».
97
Конфигурирование в системе "1 С:Предприятие 8.0". Решение расчетных задач
Решение 2. Несколько планов видов расчета и несколько регистров расчета
Планы видов расчета
Создадим несколько планов видов расчета.
Каждый план видов расчета будет содержать виды расчетов, которые можно объединить вместе по какому-либо присущему всем этим видам расчетам признаку.
Зачем мы это делаем? Чтобы не определять в планах видов расчета лишних свойств, как это было в Решении 1.
Создадим вместо одного четыре плана видов расчета:
План видов расчета «ОсновныеНачисления»
Основные свойства:

Создадим следующие предопределенные виды расчета:
98
Решение задачи

План видов расчета «Премии»
Основные свойства:

Реквизиты: Тип
«ПеречислениеСсылка.ТипыВидовРасчета»).
(тип

Важно! В свойствах планов видов расчета «ОсновныеНачисления» и «Премии» определим следующие Базовые планы видов расчета.
99
Конфигурироеание в системе " 1С:Предприятие 8.0". Решение расчетных задач

План видов расчета «Удержания»
Основные свойства:

Реквизиты: Тип
«ПеречислениеСсылка.ТипыВидовРасчета»).
Формы: ФормаСписка, ФормаВидаРасчета.
(тип

100
Предопределенные виды расчета
Решение задачи
В свойствах данного плана видов расчета на Базовые планы видов расчета определять не нужно, т.к. план видов расчета Удержания от базы не зависит.
План видов расчета «Выплаты»
Основные свойства:

Реквизиты: Тип
«ПеречислениеСсылка.ТипыВидовРасчета»).
Формы: ФормаСписка, ФормаВидаРасчета.
(тип
Предопределенные виды расчета

В свойствах данного плана видов расчета Базовые планы видов расчета определять не нужно, т.к. план видов расчета Выплаты от базы не зависит.
101
Конфигурирование в системе " 1С:Предприятие 8.0". Решение расчетных задач
Предопределенные табличные части
Заполним предопределенные табличные части в каждом вновь созданном плане видов расчета (ПВР).
Базовые виды расчета. ПВР ОсновныеНачисления


ПВР Премии
ПВР Удержания Базовых нет.
ПВР Выплаты Базовых нет.
Вытесняющие виды расчета. ПВР ОсновныеНачисления

ПВР Премии Вытесняющих нет.
ПВР Удержания Вытесняющих нет.
ПВР Выплаты 102
Вытесняющих нет.
Замечание. Вытесняющие виды расчета должны быть в рамках одного плана видов расчета.
ПВР Премии

Ведущие виды расчета. ПВР ОсновныеНачисления

ПВР Удержания Ведущих нет.
ПВР Выплаты Ведущих нет.
Регистры расчета
Создадим несколько регистров расчета.
Каждый регистр расчета будет привязан к соответствующему ранее созданному плану видов расчета.
Создадим вместо одного четыре регистра расчета:
Замечание. В реальных задачах вовсе не обязательно создавать для каждого плана видов расчета «свой» регистр расчета. С одним и тем же планом видов расчета могут быть связаны несколько регистров расчета.
103
Конфигурирование в системе " 1 С:Предприятие 8.0". Решение расчетных задач
Конфигурирование в системе
Регистр расчета «ОсновныеНачисления»
Основные свойства:
104

Измерения:
о «Подразделение» тип
«СправочникСсылка.Подразделения»;
о «Должность тип СправочникСсылка.Должности»;
о «Сотрудник» тип
«СправочникСсылка.ФизическиеЛица».
Ресурсы:
о «Результат» тип Число длиной 10 точностью 2. Реквизиты:
о «График» тип
«СправочникСсылка.ГрафикиРаботы». Связь с графиком: «ГрафикРаботы».
Решение задачи

о «ПараметрРасчета»
точностью 2. Формы: ФормаСписка.
Перерасчеты: не имеется.
Регистр расчета «Премии»
Основные свойства:
тип Число длиной 10

Премии у нас не зависят от отработанного сотрудником времени, поэтому период действия и график не определяем. А вот базовый период нужен, т.к. имеется «ПремияПроцентом» (а процент берется от базы).
Измерения:
о «Подразделение» тип
«СправочникСсылка.Подразделения»;
о «Должность тип «СправочникСсылка.Должности»;
о «Сотрудник» тип
«СправочникСсылка. Физические Лица».
Ресурсы:
105
о «Результат» тип Число длиной 10 точностью 2. Реквизиты:
о «ПараметрРасчета» тип Число длиной 10
точностью 2. Формы: ФормаСписка.
Перерасчеты: «Перерасчет». Измерения:
о «Подразделение», о «Должность», о «Сотрудник».
Определжм связь измерений «Перерасчета» с измерениями регистра и данными базовых регистров.


106
Базовым регистром является регистр расчета «ОсновныеНачисления».
Регистр расчета Удержания
Основные свойства:
Решение задачи

Удержания не зависят от отработанного сотрудником времени, поэтому период действия и график не определяем. Базовый период также не нужен, т.к. вид расчета «Штраф» вводится суммой.
Измерения:
о «Подразделение» тип
«СправочникСсылка.Подразделения»;
о «Должность» тип
«СправочникСсылка. Должности»;
о «Сотрудник» тип
«СправочникСсылка. Физические Лица».
Ресурсы:
о «Результат» тип Число длиной 10 точностью 2. Реквизиты:
о «ПараметрРасчета» тип Число длиной 10 точностью 2.
Формы: ФормаСписка. Перерасчеты: Отсутствуют.
107
Конфигурирование в системе "1 С:Предприятие 8.0", Решение расчетных задач
Регистр расчета Выплаты
Основные свойства:

Выплаты (как и удержания) не зависят от отработанного сотрудником времени, поэтому период действия и график не определяем. Базовый период также не нужен, т.к. вид расчета «Выплата» вводится суммой.
Измерения:
о «Подразделение» тип
«СправочникСсылка.Подразделения»;
о «Должность» тип
«СправочникСсылка. Должности»;
о «Сотрудник» тип
«СправочникСсылка.ФизическиеЛица».
Ресурсы:
о «Результат» тип Число длиной 10 точностью 2. Реквизиты:
о «ПараметрРасчета» тип Число длиной 10 точностью 2.
Формы: ФормаСписка. Перерасчеты: Отсутствуют.
Документы для ввода записей в регистры расчета
Для ввода записей в регистры расчета создадим несколько новых
документов:
108
«ВводОсновныхНачисленийИУдержаний», «НачислениеПремий»,
Решение задачи
«Выплаты».
Замечание. Количество документов может быть и иным. Вообще количество и функциональность документов определяются не структурой и количеством регистров расчета и планов видов расчета, а скорее составом и функционалом реальных «бумажных» документов, используемых в организации.
Документ «ВводОсновныхНачисленийИУдержаний»
Данный документ будет использоваться для ввода записей в регистр расчета «ОсновныеНачисления» (будут вводиться начисления, определенные в плане видов расчета «ОсновныеНачисления» -«Оклады» и «Отпуска») и в регистр расчета «Удержания» (будут вводиться удержания, определенные в плане видов расчета «Удержания» - «Штрафы»).
Основные свойства:
Имя: «ВводОсновныхНачисленийИУдержаний».
Реквизиты:
о «ПериодРегистрации» тип Дата. Табличные части:
о Начисления
a «Размер»: тип Число длина 10 точность 2, о Удержания
109
Конфигурирование в системе "1С-.Предприятие 8.0"'. Решение расчетных задач
р
Формы:
о ФормаСписка, о ФормаДокумента.

Назначим обработчик события При изменении поля ввода Сотрудник в табличном поле Начисления.
Также назначим обработчик события При изменении поля ввода Сотрудник в табличном поле Удержания.
В модуле формы документа заполним соответствующие процедуры-обработчики событий.
Процедура НачисленияСотрудникПриИзменении(Элемент)
СписокСотрудникПриИзменении(Элемент,ЭлементыФормы.Начисления); КонецПроцедуры
Процедура УдержанияСотрудникПриИзменении(Элемент)
СписокСотрудникПриИзменении(Элемент,ЭлементыФормы.Удержания); КонецПроцедуры
Добавим в модуль
СписокСотрудникПриИзменении.
формы