Приветствую Вас ГостьВторник, 14.05.2024, 21:37

Каталог статей


Пример заполнения регистра расчета из документа

Пример заполнения регистра расчета из документа

Из формы документа вызывается метод РассчитатьОсновныеНачисления() в модуле объекта документа

//РАСЧЕТНЫЕ ПРОЦЕДУРЫ
Процедура РассчитатьОсновныеНачисления() Экспорт
    
    //расчет записей выполняется в транзакции
    НачатьТранзакцию();
    
    //создается набор записей регистра расчета
    НаборОсновныеНачисления = РегистрыРасчета.ОсновныеНачисленияРегл.СоздатьНаборЗаписей();
    НаборОсновныеНачисления.Отбор.Регистратор.Значение = Ссылка;
    
    ВыборкаОсновныеНачисления = ОбщегоНазначения.СформироватьЗапросПоТабличнойЧасти(ЭтотОбъект, "ОсновныеНачисления").Выбрать();
    
    Пока ВыборкаОсновныеНачисления.Следующий() Цикл
        
         ДобавитьСтрокуОсновныхНачислений(ВыборкаОсновныеНачисления, НаборОсновныеНачисления);
        
    КонецЦикла;
    
    
    ТаблицаСторно = НаборОсновныеНачисления.ПолучитьДополнение();
    
    Для Каждого СтрокаСторно из ТаблицаСторно Цикл
        
        ДобавитьСтрокуСторноОсновныхНачислений(СтрокаСторно, НаборОсновныеНачисления, ОсновныеНачисления);
        
    КонецЦикла;
    
    //передача набора записей в процедуру общего модуля для расчета
    Расчеты.РассчитатьЗаписиРегистраРасчета("ОсновныеНачисленияРегл", НаборОсновныеНачисления, ОсновныеНачисления);
    
    //удаление движений по регистру
    НаборОсновныеНачисления.Очистить();
    НаборОсновныеНачисления.Записать();
    
    ЗафиксироватьТранзакцию();
    
КонецПроцедуры // РассчитатьОсновныеНачисления
 

Процедура Перерассчитать(Физлица = Неопределено) Экспорт
    
    // перерасчет выполняется в транзакции
    НачатьТранзакцию();

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

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

//ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ

//процедура добавляет запись в регистр основных начислений
Процедура ДобавитьСтрокуОсновныхНачислений(ДанныеСтроки, НаборЗаписей)

    Движение = НаборЗаписей.Добавить();
    
    //Предопределенные поля
    Движение.ПериодРегистрации          = ПериодРегистрации;
    Движение.ПериодДействияНачало       = ДанныеСтроки.ДатаНачало;
    Движение.ПериодДействияКонец         = ДанныеСтроки.ДатаКонец;
    Движение.ВидРасчета                    = ДанныеСтроки.ВидРасчета;
    Движение.Сторно                        = ДанныеСтроки.Сторно;

    // Измерения
    Движение.ФизЛицо                    = ДанныеСтроки.ФизЛицо;
    Движение.Организация                = Организация;

    // Ресурсы
    Движение.Результат                    = ДанныеСтроки.Результат;
    
    // Реквизиты
    Движение.ГрафикРаботы                = ДанныеСтроки.ФизЛицо.ГрафикРаботы;
    Движение.Размер                      = ДанныеСтроки.Размер;
    Движение.ВидУчетаВремени              = ДанныеСтроки.ВидРасчета.ВидУчетаВремени;
    Движение.Подразделение                = ДанныеСтроки.Подразделение;
     Движение.СтатьяЗатрат                = ДанныеСтроки.ВидРасчета.СтатьяЗатрат;

    
КонецПроцедуры  //ДобавитьСтрокуОсновныхНачислений

 

//Добавляет сторно-записи в набор и в табличную часть
Процедура ДобавитьСтрокуСторноОсновныхНачислений(ДанныеСтроки, НаборЗаписей, ТабличнаяЧасть = Неопределено)

    Движение = НаборЗаписей.Добавить();
    
    //Предопределенные поля
    Движение.ПериодРегистрации          = ДанныеСтроки.ПериодРегистрацииСторно;
    Движение.ПериодДействияНачало       = ДанныеСтроки.ПериодДействияНачалоСторно;
    Движение.ПериодДействияКонец         = ДанныеСтроки.ПериодДействияКонецСторно;
    Движение.ВидРасчета                    = ДанныеСтроки.ВидРасчета;
    Движение.Сторно                        = Истина;

    // Измерения
    Движение.ФизЛицо                    = ДанныеСтроки.ФизЛицо;
    Движение.Организация                = ДанныеСтроки.Организация;

    // Реквизиты
    Движение.ГрафикРаботы                = ДанныеСтроки.ГрафикРаботы;
    Движение.Размер                      = ДанныеСтроки.Размер;
    Движение.ВидУчетаВремени              = ДанныеСтроки.ВидУчетаВремени;
    Движение.Подразделение                = ДанныеСтроки.Подразделение;
     Движение.СтатьяЗатрат                = ДанныеСтроки.СтатьяЗатрат;

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


 

Общий модуль ОбщегоНазначения

// Формирует запрос по табличной части документа.
//
// Параметры: 
//  ДокументОбъект        - объект проводимого документа, 
//  ИмяТабличнойЧасти     - строка, имя табличной части,
//
// Возвращаемое значение:
//  Результат запроса.
//
Функция СформироватьЗапросПоТабличнойЧасти(ДокументОбъект, ИмяТабличнойЧасти) Экспорт

    ТекстЗапроса = "";

    Для Каждого Реквизит Из ДокументОбъект.Метаданные().ТабличныеЧасти[ИмяТабличнойЧасти].Реквизиты Цикл

        ТекстЗапроса  = ТекстЗапроса + ",
        |Док." + Реквизит.Имя;

    КонецЦикла;


    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ 
                    | Док.НомерСтроки " + ТекстЗапроса + "
                    | ИЗ 
                    |      Документ." + ДокументОбъект.Метаданные().Имя + "."+ СокрЛП(ИмяТабличнойЧасти) + 
                    " КАК Док 
                    |     ГДЕ Док.Ссылка = &ДокументСсылка";


    // Установим параметры запроса.
    Запрос.УстановитьПараметр("ДокументСсылка" , ДокументОбъект.Ссылка);

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

КонецФункции // СформироватьЗапросПоТабличнойЧасти()
 

Общий модуль Расчет:

Функция ПолучитьДанныеДляРасчета(Запись)
    
    СпособРасчета = Запись.ВидРасчета.СпособРасчета;
    
    СтруктураДанных = Новый Структура;
    
    Если СпособРасчета = Перечисления.СпособыРасчета.ПоМесячнойСтавке Тогда
        
        //Получение данных графика
        Запрос = Новый Запрос("ВЫБРАТЬ
                              |    ДанныеГрафика.ЗначениеФактическийПериодДействия КАК ГрафикФакт,
                              |    ДанныеГрафика.ЗначениеПериодДействия КАК ГрафикНорма
                              |ИЗ
                              |    РегистрРасчета.ОсновныеНачисленияРегл.ДанныеГрафика(
                              |        Регистратор = &Регистратор
                              |            И НомерСтроки = &НомерСтроки) КАК ДанныеГрафика");
                              
        Запрос.УстановитьПараметр("Регистратор", Запись.Регистратор);
        Запрос.УстановитьПараметр("НомерСтроки", Запись.НомерСтроки);
        
        Выборка = Запрос.Выполнить().Выбрать();
        
        Если Выборка.Следующий() Тогда
            СтруктураДанных.Вставить("ОтработаноВремени", Выборка.ГрафикФакт);
            СтруктураДанных.Вставить("НормаВремени", Выборка.ГрафикНорма);
        Иначе
            СтруктураДанных.Вставить("ОтработаноВремени", 0);
            СтруктураДанных.Вставить("НормаВремени", 0);
        КонецЕсли;
        
    ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета.ПроцентомОтБазы Тогда    
                
        Запрос = Новый Запрос("ВЫБРАТЬ
                              |    База.РезультатБаза
                              |ИЗ
                              |    РегистрРасчета.ОсновныеНачисленияРегл.БазаОсновныеНачисленияРегл(
                              |        &Измерения,
                              |        &Измерения,
                              |        ,
                              |        Регистратор = &Регистратор
                              |            И НомерСтроки = &НомерСтроки) КАК База");
                              
                              
        Измерения = Новый Массив(2);
        Измерения[0]="ФизЛицо";
        Измерения[1]="Организация";
                              
        Запрос.УстановитьПараметр("Регистратор", Запись.Регистратор);
        Запрос.УстановитьПараметр("НомерСтроки", Запись.НомерСтроки);
        Запрос.УстановитьПараметр("Измерения", Измерения);
        
        Выборка = Запрос.Выполнить().Выбрать();
        
        Если Выборка.Следующий() Тогда
            СтруктураДанных.Вставить("База", Выборка.РезультатБаза);
        Иначе
            СтруктураДанных.Вставить("База", 0);
        КонецЕсли;
        
    ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета.ПоСдельнойВыработке Тогда
        
        //Получение данных регистра накопления
        //фактическая выработка за период действия записи
        Запрос = Новый Запрос("ВЫБРАТЬ
                              |    СУММА(СдельнаяВыработкаОбороты.ВыработкаОборот) КАК ВыработкаОборот
                              |ИЗ
                              |    РегистрНакопления.СдельнаяВыработка.Обороты(
                              |        &ДатаНачало,
                              |        &ДатаКонец,
                              |        ,
                              |        Организация = &Организация
                              |            И ФизЛицо = &ФизЛицо) КАК СдельнаяВыработкаОбороты");
                              
        Запрос.УстановитьПараметр("ДатаНачало", НачалоДня(Запись.ПериодДействияНачало));
        Запрос.УстановитьПараметр("ДатаКонец", КонецДня(Запись.ПериодДействияКонец));
        Запрос.УстановитьПараметр("ФизЛицо", Запись.ФизЛицо);
        Запрос.УстановитьПараметр("Организация", Запись.Организация);
        
        Выборка = Запрос.Выполнить().Выбрать();
        
        Если Выборка.Следующий() Тогда
            СтруктураДанных.Вставить("Выработка", Выборка.ВыработкаОборот);
        Иначе
            СтруктураДанных.Вставить("Выработка", 0);
        КонецЕсли;
    
    КонецЕсли;
    
    Возврат СтруктураДанных;
    
КонецФункции //ПолучитьДанныеДляРасчета

Процедура РассчитатьЗапись(Запись, ДанныеДляРасчета)
    
    СпособРасчета = Запись.ВидРасчета.СпособРасчета;
    
    Если СпособРасчета = Перечисления.СпособыРасчета.ПоМесячнойСтавке Тогда
        
        Если Не ДанныеДляРасчета.НормаВремени=0 Тогда 
            Результат = Запись.Размер * ДанныеДляРасчета.ОтработаноВремени / ДанныеДляРасчета.НормаВремени;
        Иначе
            Результат = 0;
        КонецЕсли;
        
    ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета.ПроцентомОтБазы Тогда
        
        Результат = Запись.Размер * ДанныеДляРасчета.База / 100;
        
    ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета.ФиксированнойСуммой Тогда
        
        Результат = Запись.Размер;
        
    ИначеЕсли СпособРасчета = Перечисления.СпособыРасчета.ПоСдельнойВыработке Тогда
        
        Результат = ДанныеДляРасчета.Выработка;
        
    КонецЕсли;
    
    Запись.Результат = Результат * ?(Запись.Сторно, -1, 1); 
    
КонецПроцедуры //Рассчитать запись

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

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

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

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

// Проверяет необходимость выполнения перерасчета документа
// если в таблицах перерасчета по документу ссылка на который передана 
// есть хоть одна запись - возращает Истина
// Параметры:
//  Регистратор - ссылка на документ
// Возвращаемое значение:
//  булево
//
Функция НеобходимостьПерерасчета(Регистратор) Экспорт

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

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

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

    Запрос.УстановитьПараметр("СписокФизлиц", Физлица);
    Запрос.УстановитьПараметр("Регистратор", Регистратор);
    
    ВыборкаПриоритетов = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    //для каждого значения приоритета выполняется расчет записей
    Пока ВыборкаПриоритетов.Следующий() Цикл
        
        ПерерассчитатьНаборЗаписей(НаборЗаписей, ВыборкаПриоритетов.Приоритет, ТабличнаяЧасть, Физлица);
        
        //запись набора в регистр для расчета записей следующего приоритета
        //фактический период действия не пересчитывается
        НаборЗаписей.Записать(Истина, Истина);
        
    КонецЦикла;
    
КонецПроцедуры

Категория: Регистры | Добавил: leshic (03.03.2023)
Просмотров: 210 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Вход на сайт
Поиск
Категории раздела
СКД [48]
Регистры [7]
Формы [41]
Администрирование [35]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [29]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0