Способы решения задач по регистрам расчета (1С Специалист)
Источник: http://www.forum.mista.ru/topic.php?id=308277
В общем, пишут что данные графика и базы надо обязательно получать одним запросом для каждого вида расчета, а не функциями ПолучитьБазу и ПолучитьДанныеГрафика.
Ибо:
Получение информации, хранящейся в информационной базе, (остатков, оборотов, данных базы, данных графика и т.п.) в цикле2,0 штрафных балла
'Источник: '''''
В принципе, это то же самое, только делается сразу для всего документа. Отбор по регистратору и виду расчета. В результат запроса выгружается колонка НомерСтроки, и по этому номеру ищутся и модифицируются записи набора данных регистра.
Модуль документа:
Процедура ОбработкаПроведения(Отказ, Режим)
Для Каждого ТекСтрокаОсновныеНачисления Из ОсновныеНачисления Цикл
// регистр ОсновныеНачисления
Движение = Движения.ОсновныеНачисления.Добавить();
Движение.Сторно = Ложь;
Движение.ВидРасчета = ТекСтрокаОсновныеНачисления.ВидРасчета;
Движение.ПериодДействияНачало = ТекСтрокаОсновныеНачисления.ДатаНачала;
Движение.ПериодДействияКонец = ТекСтрокаОсновныеНачисления.ДатаОкончания;
Движение.ПериодРегистрации = ПериодРегистрации;
Движение.БазовыйПериодНачало = ?(ТекСтрокаОсновныеНачисления.ВидРасчета=ПланыВидовРасчета.ОсновныеНачисления.Отпуск, НачалоМесяца(ДобавитьМесяц(ТекСтрокаОсновныеНачисления.ДатаНачала,-3)), ТекСтрокаОсновныеНачисления.ДатаНачала);
Движение.БазовыйПериодКонец = ?(ТекСтрокаОсновныеНачисления.ВидРасчета=ПланыВидовРасчета.ОсновныеНачисления.Отпуск, КонецМесяца(ДобавитьМесяц(ТекСтрокаОсновныеНачисления.ДатаОкончания,-1)), ТекСтрокаОсновныеНачисления.ДатаОкончания);
Движение.Сотрудник = ТекСтрокаОсновныеНачисления.Сотрудник;
Движение.Подразделение = ТекСтрокаОсновныеНачисления.Подразделение;
Движение.Должность = ТекСтрокаОсновныеНачисления.Должность;
Движение.Результат = 0;
Движение.Размер = ТекСтрокаОсновныеНачисления.Размер;
Движение.ГрафикРаботы = ТекСтрокаОсновныеНачисления.ГрафикРаботы;
Движение.ТипРасчета = ТекСтрокаОсновныеНачисления.ТипРасчета;
КонецЦикла;
Движения.ОсновныеНачисления.Записать();
ТаблицаСторно=Движения.ОсновныеНачисления.ПолучитьДополнение();
Если ТаблицаСторно.Количество()>0 Тогда
ТаблицаСторно.ВыбратьСтроку();
Для каждого СтрокаСторно Из ТаблицаСторно Цикл
Движение = Движения.ОсновныеНачисления.Добавить();
Движение.Сторно = Истина;
Движение.ВидРасчета = СтрокаСторно.ВидРасчета;
Движение.ПериодДействияНачало = СтрокаСторно.ПериодДействияНачалоСторно;
Движение.ПериодДействияКонец = СтрокаСторно.ПериодДействияКонецСторно;
Движение.ПериодРегистрации = СтрокаСторно.ПериодРегистрацииСторно;
Движение.БазовыйПериодНачало = СтрокаСторно.БазовыйПериодНачало;
Движение.БазовыйПериодКонец = СтрокаСторно.БазовыйПериодКонец;
Движение.Сотрудник = СтрокаСторно.Сотрудник;
Движение.Подразделение = СтрокаСторно.Подразделение;
Движение.Должность = СтрокаСторно.Должность;
Движение.Результат = 0;
Движение.Размер = СтрокаСторно.Размер*(-1);
Движение.ГрафикРаботы = СтрокаСторно.ГрафикРаботы;
КонецЦикла;
Движения.ОсновныеНачисления.Записать();
КонецЕсли;
РасчитатьНачисления(Движения.ОсновныеНачисления, ПланыВидовРасчета.ОсновныеНачисления.Оклад);
Движения.ОсновныеНачисления.Записать(,Истина);
РасчитатьНачисления(Движения.ОсновныеНачисления, ПланыВидовРасчета.ОсновныеНачисления.Отпуск);
Движения.ОсновныеНачисления.Записать(,Истина);
РасчитатьНачисления(Движения.ОсновныеНачисления, ПланыВидовРасчета.ОсновныеНачисления.Премия);
Движения.ОсновныеНачисления.Записать(,Истина);
РасчитатьНачисления(Движения.ОсновныеНачисления, ПланыВидовРасчета.ОсновныеНачисления.Штраф);
Движения.ОсновныеНачисления.Записать(,Истина);
КонецПроцедуры
Общий модуль:
//Это нужно чтоб перевести 100 баксов штрафа в рубли
Функция РасчитатьЭквивалентВалюты(Валюта, ВалСумма, Дата) Экспорт
Курс=РегистрыСведений.Валюты.ПолучитьПоследнее(Дата, Новый Структура("Валюта",Валюта)).Курс;
Возврат Курс*ВалСумма;
КонецФункции // ()
Процедура РасчитатьНачисления(НаборЗаписейРегистра, ВидРасчета) Экспорт
Регистратор = НаборЗаписейРегистра.Отбор.Регистратор.Значение;
Если ВидРасчета=ПланыВидовРасчета.ОсновныеНачисления.Оклад Тогда
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ОсновныеНачисленияДанныеГрафика.НомерСтроки,
| ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.ЗначениеПериодДействия, 0) КАК Норма,
| ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.ЗначениеФактическийПериодДействия, 0) КАК Факт,
| ЕСТЬNULL(ОсновныеНачисленияДанныеГрафика.Размер, 0) КАК Размер
|ИЗ
| РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(
| Регистратор = &Регистратор
| И ВидРасчета = &ВидРасчета) КАК ОсновныеНачисленияДанныеГрафика
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления
| ПО ОсновныеНачисленияДанныеГрафика.НомерСтроки = НачислениеЗарплатыОсновныеНачисления.НомерСтроки
|ГДЕ
| НачислениеЗарплатыОсновныеНачисления.Ссылка = &Регистратор";
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Запрос.УстановитьПараметр("ВидРасчета", ВидРасчета);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
ТЗ=Результат.Выгрузить();
ТЗ.ВыбратьСтроку();
Пока Выборка.Следующий() Цикл
Если Выборка.Норма=0 Тогда
Сообщить("В этом периоде нет рабочих дней");
Продолжить;
КонецЕсли;
ЗаписьРегистра=НаборЗаписейРегистра.Получить(Выборка.НомерСтроки-1);
ЗаписьРегистра.Результат=ЗаписьРегистра.Размер/Выборка.Норма*Выборка.Факт;
КонецЦикла;
ИначеЕсли ВидРасчета=ПланыВидовРасчета.ОсновныеНачисления.Премия Тогда
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ЕСТЬNULL(ОсновныеНачисленияБазаОсновныеНачисления.РезультатБаза, 0) КАК База,
| ОсновныеНачисленияБазаОсновныеНачисления.НомерСтроки,
| ЕСТЬNULL(ОсновныеНачисленияБазаОсновныеНачисления.Размер, 0) КАК Размер,
| ЕСТЬNULL(ПроцентыДляПремииСрезПоследних.Процент, 0) КАК Процент
|ИЗ
| РегистрРасчета.ОсновныеНачисления.БазаОсновныеНачисления(
| &Измер,
| &Измер,
| ,
| ВидРасчета = &ВидРасчета
| И Регистратор = &Регистратор) КАК ОсновныеНачисленияБазаОсновныеНачисления
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления
| ПО ОсновныеНачисленияБазаОсновныеНачисления.НомерСтроки = НачислениеЗарплатыОсновныеНачисления.НомерСтроки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПроцентыДляПремии.СрезПоследних(
| &Период,
| Сотрудник В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| НачислениеЗарплатыОсновныеНачисления.Сотрудник
| ИЗ
| Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления
| ГДЕ
| НачислениеЗарплатыОсновныеНачисления.Ссылка = &Ссылка)) КАК ПроцентыДляПремииСрезПоследних
| ПО ОсновныеНачисленияБазаОсновныеНачисления.Сотрудник = ПроцентыДляПремииСрезПоследних.Сотрудник
|ГДЕ
| НачислениеЗарплатыОсновныеНачисления.Ссылка = &Регистратор";
Измер = Новый Массив(3);
Измер[0]= "Сотрудник";
Измер[1]= "Должность";
Измер[2]= "Подразделение";
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Запрос.УстановитьПараметр("ВидРасчета", ВидРасчета);
Запрос.УстановитьПараметр("Измер", Измер);
Запрос.УстановитьПараметр("Ссылка",Регистратор.Ссылка);
Запрос.УстановитьПараметр("Период", Регистратор.Ссылка.ПериодРегистрации);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
ТЗ=Результат.Выгрузить();
ТЗ.ВыбратьСтроку();
Пока Выборка.Следующий() Цикл
База=Выборка.База;
Процент=Выборка.Процент;
Размер=Выборка.Размер;
ЗаписьРегистра=НаборЗаписейРегистра.Получить(Выборка.НомерСтроки-1);
Если Процент<>0 Тогда
ЗаписьРегистра.Результат=База/100*Процент;
Иначе
ЗаписьРегистра.Результат=База/100*Размер;
КонецЕсли;
КонецЦикла;
ИначеЕсли ВидРасчета=ПланыВидовРасчета.ОсновныеНачисления.Отпуск Тогда
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ОсновныеНачисленияБазаОсновныеНачисления.РезультатБаза,
| ОсновныеНачисленияБазаОсновныеНачисления.НомерСтроки
|ИЗ
| РегистрРасчета.ОсновныеНачисления.БазаОсновныеНачисления(
| &Измер,
| &Измер,
| ,
| ВидРасчета = &ВидРасчета
| И Регистратор = &Регистратор) КАК ОсновныеНачисленияБазаОсновныеНачисления
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления
| ПО ОсновныеНачисленияБазаОсновныеНачисления.НомерСтроки = НачислениеЗарплатыОсновныеНачисления.НомерСтроки
|ГДЕ
| НачислениеЗарплатыОсновныеНачисления.Ссылка = &Регистратор";
Измер = Новый Массив(3);
Измер[0]= "Сотрудник";
Измер[1]= "Должность";
Измер[2]= "Подразделение";
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Запрос.УстановитьПараметр("ВидРасчета", ВидРасчета);
Запрос.УстановитьПараметр("Измер", Измер);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
ТЗ=Результат.Выгрузить();
ТЗ.ВыбратьСтроку();
Пока Выборка.Следующий() Цикл
ЗаписьРегистра=НаборЗаписейРегистра.Получить(Выборка.НомерСтроки-1);
ЗаписьРегистра.Результат=Выборка.РезультатБаза/3;
КонецЦикла;
ИначеЕсли ВидРасчета=ПланыВидовРасчета.ОсновныеНачисления.Штраф Тогда
Дата=Регистратор.Ссылка.ПериодРегистрации;
Для каждого ЗаписьРегистра Из НаборЗаписейРегистра Цикл
Если ЗаписьРегистра.ВидРасчета=ВидРасчета Тогда
ВалДолл=Справочники.Валюты.НайтиПоНаименованию("Доллар");
ЗаписьРегистра.Результат=РасчитатьЭквивалентВалюты(ВалДолл, 100, Дата)
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Еще должен быть РС ПроцентыДляПремии, состоящий из:
Измерения
- Сотрудник
Ресурсы
- Процент
Т.е. при расчете премии: если процент установлен для сотрудника, то берется он. Если не установлен, то значит берется "размер" из документа.
Состав РегРасчета ОсновныеНачисления:
Измерения
- Сотрудник
- Должность
- Подразделение
Ресурсы
- Результат
Реквизиты
- Размер
- ГрафикРаботы