Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Павел Чистов. Конспект к курсу Комплексная подг...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
28.21 Mб
Скачать

Занятие 3.30

Оптимизация работы с Регистрами расчета

Общий модуль «Расчеты» - процедура «Рассчитать»:

Данные по Норме и Факту дней, а также дополнительные данные, которые нам понадобятся для расчета записей регистра, получим с помощью запроса:

Чтобы между этим запросом и запросом, который будет получать Базу, можно было передавать данные, получим Менеджер временных таблиц. В запросе нам надо получить то же самое, что мы получали при расчете Основных начислений:

Можно обратиться к реальной таблице или таблице «ДанныеГрафика». Они практически идентичны, но у таблицы «ДанныеГрафика» есть дополнительные поля. Они автоматически рассчитываются системой и представляют собой Количество отработанных дней за указанный период:

  • Действия.

  • Фактический.

  • Базовый.

  • Регистрации.

Установим параметры виртуальной таблицы «НачисленияСотрудниковДанныеГрафика»:

В параметрах установим отбор по документу-регистратору и по периоду регистрации. Отбор по периоду регистрации не повлияет на результат выборки, но увеличит скорость отработки, т.к. Индекс таблицы Данные графика составной:

  • Документ + ПериодРегистрации.

Поля:

НомерСтроки – нужен для получения результата записи – суммы.

Приоритет – нужен для отбора данных при получении таблицы Базы (ограничение данных Базы только нужным Приоритетом).

ПризнакПериодДействия – норма дней.

ПризнакФактическийПериодДействия – факт дней.

Назначим псевдонимы:

Итого процедура «Рассчитать»:

Процедура Рассчитать(Регистратор) Экспорт

// получим копию набора записей регистра

НаборЗаписей = РегистрыРасчета.НачисленияСотрудников.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(Регистратор);

НаборЗаписей.Прочитать();

Запрос = Новый Запрос;

МВТ = Новый МенеджерВременныхТаблиц;

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

Запрос.Текст =

"ВЫБРАТЬ

| НачисленияСотрудниковДанныеГрафика.НомерСтроки,

| НачисленияСотрудниковДанныеГрафика.ВидРасчета.Способ КАК Способ,

| НачисленияСотрудниковДанныеГрафика.ВидРасчета.УвеличиваетОтработанныеДни

КАК УвеличиваетОтработанныеДни,

| НачисленияСотрудниковДанныеГрафика.ВидРасчета.Приоритет КАК Приоритет,

| НачисленияСотрудниковДанныеГрафика.Сторно,

| НачисленияСотрудниковДанныеГрафика.Параметр,

| НачисленияСотрудниковДанныеГрафика.ПризнакПериодДействия КАК НормаДней,

| НачисленияСотрудниковДанныеГрафика.ПризнакФактическийПериодДействия КАК ФактДней

|ПОМЕСТИТЬ ДанныеГрафика

|ИЗ

| РегистрРасчета.НачисленияСотрудников.ДанныеГрафика(

| Регистратор = &Регистратор

| И ПериодРегистрации = &ПериодРегистрации) КАК НачисленияСотрудниковДанныеГрафика";

Запрос.УстановитьПараметр("Регистратор", Регистратор);

Запрос.УстановитьПараметр("ПериодРегистрации", НачалоМесяца(Регистратор.Дата));

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

//Получим копию набора записей регистра

ДопНаборЗаписей = РегистрыРасчета.ДопНачисления.СоздатьНаборЗаписей();

ДопНаборЗаписей.Отбор.Регистратор.Установить(Регистратор);

ДопНаборЗаписей.Прочитать();

СписокПриоритетов = ПолучитьСписокПриоритетов(Регистратор);

Для Каждого Приоритет Из СписокПриоритетов Цикл

РассчитатьОсновные(НаборЗаписей, МВТ, Приоритет);

РассчитатьДополнительные(ДопНаборЗаписей, Приоритет);

КонецЦикла;

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

Параметр «ПериодРегистрации» - берем дату документа-регистратора. Значение параметра должно быть равно первому числу периода, за который будут вычисляться данные.

Результат запроса поместим во временную таблицу «ДанныеГрафика»:

|ПОМЕСТИТЬ ДанныеГрафика

Поместим объект с результатом запроса (МВТ) в память – выполним запрос:

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

МВТ передадим в процедуру «РассчитатьОсновные()».

В процедуре «РассчитатьОсновные()» объектный метод получения Базы заменим на запрос:

Было:

ОтборПоИзмерениям = Новый Структура;

ОтборПоИзмерениям.Вставить("Сотрудник", "НачисленияСотрудников.Сотрудник");

СписокРесурсов = Новый Массив(2);

СписокРесурсов[0] = "НачисленияСотрудников.Сумма";

СписокРесурсов[1] = "НачисленияСотрудников.ОтработаноДней";

ОтборПоРегистратору = Новый Структура;

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

ОтборПоРегистратору.Вставить("Регистратор", Регистратор);

ТЗ_База = РегистрыРасчета.НачисленияСотрудников.ПолучитьБазу(

ОтборПоРегистратору,

СписокРесурсов,

ОтборПоИзмерениям);

В конструкторе запроса опишем виртуальную таблицу «ДанныеГрафика», которую мы передали в процедуру:

К ней надо присоединить таблицу с Базой регистра расчета «НачисленияСотрудников». Опишем параметры данной виртуальной таблицы:

Первые два параметра – это как отбор по измерениям в объектной модели. Базу надо получать только по одному сотруднику, поэтому в измерения Основного и Базового регистра надо передать два массива:

1. «ИзмеренияОсновногоРегистра» - названия полей набора записей регистра, который содержит значения отбора. В примере это поле «Сотрудник».

2. «ИзмеренияБазовогоРегистра» - названия измерений в Базовом регистре, в котором установится отбор.

Т.к. в примере Базу получаем саму из себя, то отбор устанавливается также по Измерению «Сотрудник».

Условия:

«Регистратор = &Регистратор» - это отбор по документу, т.к. База нам нужна только по одному документу.

«ПериодРегистрации = &ПериодРегистрации» - для увеличения быстродействия. Поле «ПериодРегистрации» состоит в индексе таблицы регистра.

«ВидРасчета.Приоритет = &Приоритет» - это отбор по определенному Приоритету.

НомерСтроки – это единственное поле, точно идентифицирующее запись по позиции регистратора.

Поля:

  • НормаДней

  • ФактДней

  • База

  • БазаДней

могут быть не рассчитаны, т.е. вернут NULL, поэтому воспользуемся функцией ЕСТЬNULL.

Итого запрос:

ВЫБРАТЬ

ДанныеГрафика.НомерСтроки,

ДанныеГрафика.Способ,

ДанныеГрафика.УвеличиваетОтработанныеДни,

ДанныеГрафика.Приоритет,

ДанныеГрафика.Сторно,

ДанныеГрафика.Параметр,

ЕСТЬNULL(ДанныеГрафика.НормаДней, 0) КАК НормаДней,

ЕСТЬNULL(ДанныеГрафика.ФактДней, 0) КАК ФактДней,

ЕСТЬNULL(НачисленияСотрудниковБазаНачисленияСотрудников.СуммаБаза, 0) КАК База,

ЕСТЬNULL(НачисленияСотрудниковБазаНачисленияСотрудников.ОтработаноДнейБаза, 0) КАК БазаДней

ИЗ

ДанныеГрафика КАК ДанныеГрафика

ЛЕВОЕ СОЕДИНЕНИЕ РегистрРасчета.НачисленияСотрудников.БазаНачисленияСотрудников(

&МассивМзмерений,

&МассивМзмерений,

,

Регистратор = &Регистратор

И ПериодРегистрации = &ПериодРегистрации

И ВидРасчета.Приоритет = &Приоритет) КАК НачисленияСотрудниковБазаНачисленияСотрудников

ПО ДанныеГрафика.НомерСтроки = НачисленияСотрудниковБазаНачисленияСотрудников.НомерСтроки

ГДЕ

ДанныеГрафика.Приоритет = &Приоритет

Итого код:

Процедура Рассчитать(Регистратор) Экспорт

// получим копию набора записей регистра

НаборЗаписей = РегистрыРасчета.НачисленияСотрудников.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(Регистратор);

НаборЗаписей.Прочитать();

//ОтборПоРегистратору = Новый Структура;

//ОтборПоРегистратору.Вставить("Регистратор", Регистратор);

//

//ТЗ_ФактДней = РегистрыРасчета.НачисленияСотрудников.ПолучитьДанныеГрафика(

//ОтборПоРегистратору,

//ВидПериодаРегистраРасчета.ФактическийПериодДействия);

//

//ТЗ_НормаДней = РегистрыРасчета.НачисленияСотрудников.ПолучитьДанныеГрафика(

//ОтборПоРегистратору,

//ВидПериодаРегистраРасчета.ПериодДействия);

//ТЗ_БазаДней = РегистрыРасчета.НачисленияСотрудников.ПолучитьДанныеГрафика(

//ОтборПоРегистратору,

//ВидПериодаРегистраРасчета.БазовыйПериод);

Запрос = Новый Запрос;

МВТ = Новый МенеджерВременныхТаблиц;

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

Запрос.Текст =

"ВЫБРАТЬ

| НачисленияСотрудниковДанныеГрафика.НомерСтроки,

| НачисленияСотрудниковДанныеГрафика.ВидРасчета.Способ КАК Способ,

| НачисленияСотрудниковДанныеГрафика.ВидРасчета.УвеличиваетОтработанныеДни

КАК УвеличиваетОтработанныеДни,

| НачисленияСотрудниковДанныеГрафика.ВидРасчета.Приоритет КАК Приоритет,

| НачисленияСотрудниковДанныеГрафика.Сторно,

| НачисленияСотрудниковДанныеГрафика.Параметр,

| НачисленияСотрудниковДанныеГрафика.ПризнакПериодДействия КАК НормаДней,

| НачисленияСотрудниковДанныеГрафика.ПризнакФактическийПериодДействия КАК ФактДней

|ПОМЕСТИТЬ ДанныеГрафика

|ИЗ

| РегистрРасчета.НачисленияСотрудников.ДанныеГрафика(

| Регистратор = &Регистратор

| И ПериодРегистрации = &ПериодРегистрации) КАК НачисленияСотрудниковДанныеГрафика";

Запрос.УстановитьПараметр("Регистратор", Регистратор);

Запрос.УстановитьПараметр("ПериодРегистрации", НачалоМесяца(Регистратор.Дата));

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

//Получим копию набора записей регистра

ДопНаборЗаписей = РегистрыРасчета.ДопНачисления.СоздатьНаборЗаписей();

ДопНаборЗаписей.Отбор.Регистратор.Установить(Регистратор);

ДопНаборЗаписей.Прочитать();

СписокПриоритетов = ПолучитьСписокПриоритетов(Регистратор);

Для Каждого Приоритет Из СписокПриоритетов Цикл

РассчитатьОсновные(НаборЗаписей, МВТ, Приоритет);

РассчитатьДополнительные(ДопНаборЗаписей, Приоритет);

КонецЦикла;

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

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

//ОтборПоИзмерениям = Новый Структура;

//ОтборПоИзмерениям.Вставить("Сотрудник", "НачисленияСотрудников.Сотрудник");

//

//СписокРесурсов = Новый Массив(2);

//СписокРесурсов[0] = "НачисленияСотрудников.Сумма";

//СписокРесурсов[1] = "НачисленияСотрудников.ОтработаноДней";

//

//ОтборПоРегистратору = Новый Структура;

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

//ОтборПоРегистратору.Вставить("Регистратор", Регистратор);

//

//ТЗ_База = РегистрыРасчета.НачисленияСотрудников.ПолучитьБазу(

//ОтборПоРегистратору,

//СписокРесурсов,

//ОтборПоИзмерениям);

Запрос = Новый Запрос;

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

Запрос.Текст =

"ВЫБРАТЬ

| ДанныеГрафика.НомерСтроки,

| ДанныеГрафика.Способ,

| ДанныеГрафика.УвеличиваетОтработанныеДни,

| ДанныеГрафика.Приоритет,

| ДанныеГрафика.Сторно,

| ДанныеГрафика.Параметр,

| ЕСТЬNULL(ДанныеГрафика.НормаДней, 0) КАК НормаДней,

| ЕСТЬNULL(ДанныеГрафика.ФактДней, 0) КАК ФактДней,

| ЕСТЬNULL(НачисленияСотрудниковБазаНачисленияСотрудников.СуммаБаза, 0) КАК База,

| ЕСТЬNULL(НачисленияСотрудниковБазаНачисленияСотрудников.ОтработаноДнейБаза, 0) КАК БазаДней

|ИЗ

| ДанныеГрафика КАК ДанныеГрафика

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрРасчета.НачисленияСотрудников.БазаНачисленияСотрудников(

| &МассивМзмерений,

| &МассивМзмерений,

| ,

| Регистратор = &Регистратор

| И ПериодРегистрации = &ПериодРегистрации

| И ВидРасчета.Приоритет = &Приоритет)

КАК НачисленияСотрудниковБазаНачисленияСотрудников

| ПО ДанныеГрафика.НомерСтроки = НачисленияСотрудниковБазаНачисленияСотрудников.НомерСтроки

|ГДЕ

| ДанныеГрафика.Приоритет = &Приоритет";

Массив = Новый Массив(1);

Массив[0] = "Сотрудник";

Запрос.УстановитьПараметр("МассивМзмерений", Массив);

Запрос.УстановитьПараметр("Регистратор", НаборЗаписей.Отбор.Регистратор.Значение);

Запрос.УстановитьПараметр("ПериодРегистрации", НачалоМесяца(НаборЗаписей.Отбор.Регистратор.Значение.Дата));

Запрос.УстановитьПараметр("Приоритет", Приоритет);

РезультатЗапроса = Запрос.Выполнить();

Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл

Запись = НаборЗаписей[Выборка.НомерСтроки - 1];

База = Выборка.База;

СпособРасчета = Выборка.Способ;

ФактДней = Выборка.ФактДней;

НормаДней = Выборка.НормаДней;

БазаДней = Выборка.БазаДней;

Параметр = Выборка.Параметр;

УвеличиваетОтработанныеДни = Запись.ВидРасчета.УвеличиваетОтработанныеДни;

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

//

// Если Запись.ВидРасчета.Приоритет <> Приоритет Тогда

// Продолжить;

// КонецЕсли;

//

// //Индекс = Запись.НомерСтроки - 1;

// Индекс = НаборЗаписей.Индекс(Запись);

// База = ТЗ_База[Индекс].Сумма;

// СпособРасчета = Запись.ВидРасчета.Способ;

// ФактДней = ТЗ_ФактДней[Индекс].Признак;

// НормаДней = ТЗ_НормаДней[Индекс].Признак;

// //БазаДней = ТЗ_БазаДней[Индекс].Признак;

// БазаДней = ТЗ_База[Индекс].ОтработаноДней;

// Параметр = Запись.Параметр;

// УвеличиваетОтработанныеДни = Запись.ВидРасчета.УвеличиваетОтработанныеДни;

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

Запись.Сумма = База * Параметр / 100;

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

Запись.Сумма = Параметр;

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

Запись.Сумма = ФактДней * Параметр;

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

Запись.Сумма = ФактДней / НормаДней * Параметр;

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

Запись.Сумма = База / БазаДней * ФактДней * Параметр / 100;

КонецЕсли;

Если УвеличиваетОтработанныеДни тогда

Запись.ОтработаноДней = ФактДней;

КонецЕсли;

Если Запись.Сторно Тогда

Запись.Сумма = - Запись.Сумма;

Запись.ОтработаноДней = - Запись.ОтработаноДней;

КонецЕсли;

КонецЦикла;

НаборЗаписей.Записать( , , Ложь);

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

Процедура РассчитатьДополнительные(НаборЗаписей, Приоритет)

ОтборПоИзмерениям = Новый Структура;

ОтборПоИзмерениям.Вставить("Сотрудник", "НачисленияСотрудников.Сотрудник,

|ДопНачисления.Сотрудник");

СписокРесурсов = Новый Массив(1);

СписокРесурсов[0] = "НачисленияСотрудников.Сумма, ДопНачисления.Сумма";

ОтборПоРегистратору = Новый Структура;

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

ОтборПоРегистратору.Вставить("Регистратор", Регистратор);

ТЗ_База = РегистрыРасчета.ДопНачисления.ПолучитьБазу(

ОтборПоРегистратору,

СписокРесурсов,

ОтборПоИзмерениям);

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

Если Запись.ВидРасчета.Приоритет <> Приоритет Тогда

Продолжить;

КонецЕсли;

Индекс = НаборЗаписей.Индекс(Запись);

База = ТЗ_База[Индекс].Сумма;

СпособРасчета = Запись.ВидРасчета.Способ;

Параметр = Запись.Параметр;

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

Запись.Сумма = База * Параметр / 100;

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

Запись.Сумма = Параметр;

КонецЕсли;

Если Запись.Сторно Тогда

Запись.Сумма = - Запись.Сумма;

КонецЕсли;

КонецЦикла;

НаборЗаписей.Записать();

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

Функция ПолучитьСписокПриоритетов(Регистратор)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ВложенныйЗапрос.Приоритет КАК Приоритет

|ИЗ

| (ВЫБРАТЬ

| НачисленияСотрудников.ВидРасчета.Приоритет КАК Приоритет

| ИЗ

| РегистрРасчета.НачисленияСотрудников КАК НачисленияСотрудников

| ГДЕ

| НачисленияСотрудников.Регистратор = &Регистратор

|

| ОБЪЕДИНИТЬ

|

| ВЫБРАТЬ

| ДопНачисления.ВидРасчета.Приоритет

| ИЗ

| РегистрРасчета.ДопНачисления КАК ДопНачисления

| ГДЕ

| ДопНачисления.Регистратор = &Регистратор) КАК ВложенныйЗапрос

|

|УПОРЯДОЧИТЬ ПО

| Приоритет";

Запрос.УстановитьПараметр("Регистратор", Регистратор);

РезультатЗапроса = Запрос.Выполнить().Выгрузить();

Возврат РезультатЗапроса.ВыгрузитьКолонку("Приоритет");

КонецФункции

В режиме исполнения:

Перепроведем документ «Ввод произвольных начислений» № 000000007:

Было:

Стало:

Аналогично. Вывод: начисление считается правильно.