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