Способы решения задач по регистрам расчета (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, Дата)
            
            КонецЕсли; 
         
         КонецЦикла;  
    
    КонецЕсли; 

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

Еще должен быть РС ПроцентыДляПремии, состоящий из: 
   Измерения
      - Сотрудник
   Ресурсы
      - Процент


Т.е. при расчете премии: если процент установлен для сотрудника, то берется он. Если не установлен, то значит берется "размер" из документа.

Состав РегРасчета ОсновныеНачисления:

   Измерения
      - Сотрудник
      - Должность
      - Подразделение
   Ресурсы
      - Результат
   Реквизиты
      - Размер
      - ГрафикРаботы