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