Как получить данные расчетной базы для начислений в 1С с помощью запроса?

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке собственных документов для расчета зарплаты или других зависимых начислений часто возникает задача: как получить сумму базовых начислений, от которых зависит текущий расчет? Например, для расчета премии в процентах от оклада нужно сначала получить сам оклад за определенный период или выполнить перенос среднего заработка. В платформе 1С для этого существуют специальные механизмы, но не всегда очевидно, как их правильно использовать. Многие разработчики сталкиваются с функцией ПрочитатьБазу() и пытаются ее применить, но это неверный подход. Разберемся, как правильно получать данные расчетной базы с помощью запросов.

Почему не стоит использовать метод ПрочитатьБазу()?

Первое, что нужно понять: метод ПрочитатьБазу() является внутренним, служебным механизмом платформы. Он не предназначен для прямого вызова в коде разработчика. Этот метод автоматически вызывается самой платформой в момент проведения документа, когда происходит запись движений в регистр расчета (например, при выполнении кода Движения.ОсновныеНачисления.Записать()). Его задача — собрать данные из виртуальных таблиц регистра расчета, таких как ДанныеГрафика, и подготовить их для расчета текущей записи.

Ключевые моменты:

Правильный подход: запрос к виртуальным таблицам регистра расчета

Результаты всех расчетов, которые могут выступать в качестве базы для других начислений, хранятся в основной таблице регистра расчета. Для удобного получения этих данных платформа предоставляет специальные виртуальные таблицы. Основная из них, которая нам понадобится, — это ДанныеГрафика.

Эта таблица содержит записи регистра расчета с учетом их фактического периода действия и вытеснения. Именно из нее удобнее всего получать данные для расчета базы. Рассмотрим несколько практических примеров.

Пример 1: Простой запрос для получения базы по конкретному регистратору

Проанализируем простейший случай, когда нам нужно получить сумму базовых начислений, которые были введены тем же документом, что и наш текущий расчет. Это может быть актуально, например, для расчета районного коэффициента на оклад, где оклад и коэффициент рассчитываются в одном документе.

Задача: получить сумму базовых начислений для сотрудника, зарегистрированных определенным документом.


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

// Устанавливаем параметры запроса
Запрос.УстановитьПараметр("Регистратор", СсылкаНаДокумент); 
// В параметрах виртуальной таблицы можно указать дополнительные отборы, например, по сотруднику
Запрос.УстановитьПараметр("Параметры", Новый Структура("Сотрудник", НужныйСотрудник)); 

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Если Выборка.Следующий() Тогда
    База = Выборка.РезультатБаза;
    Сообщить("Сумма базы: " + База);
КонецЕсли;

В этом запросе мы обращаемся к виртуальной таблице РегистрРасчета.ОсновныеНачисления.ДанныеГрафика и суммируем поле Результат. Фильтрация по полю Регистратор позволяет получить только те записи, которые введены нашим документом.

Пример 2: Получение базы с учетом настроек плана видов расчета

Более правильный и универсальный подход — получать базу с учетом настроек, заданных в плане видов расчета. Для каждого вида расчета (например, "Премия") на закладке "Прочее" указывается список базовых видов расчета (например, "Оклад"). Наш запрос должен учитывать эту связь, чтобы случайно не включить в базу лишние начисления.

Задача: получить базу для расчета "Премия", которая зависит от "Оклада" и "Надбавки за выслугу лет".

Для этого нам понадобится соединить виртуальную таблицу ДанныеГрафика с таблицей базовых видов расчета.


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

// Указываем, для какого вида расчета мы ищем базу
Запрос.УстановитьПараметр("ВидРасчетаДляКоторогоСчитаемБазу", ПланыВидовРасчета.ОсновныеНачисления.Премия);
Запрос.УстановитьПараметр("Сотрудник", ТекущийСотрудник);

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

Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 0 Тогда
    СуммаБазы = Результат[0].База;
КонецЕсли;

Разберем этот запрос подробнее:

  1. ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПланВидовРасчета.ОсновныеНачисления.БазовыеВидыРасчета — мы соединяем наши данные с табличной частью "БазовыеВидыРасчета" из плана видов расчета.
  2. ПО ОсновныеНачисленияДанныеГрафика.ВидРасчета = ОсновныеНачисленияБазовыеВидыРасчета.Ссылка — условие соединения. Мы связываем вид расчета из регистра с базовым видом расчета из настроек.
  3. ГДЕ ОсновныеНачисленияБазовыеВидыРасчета.ВидРасчета = &ВидРасчетаДляКоторогоСчитаемБазу — это ключевое условие. Мы отбираем только те базовые начисления, которые указаны в настройках нашего текущего вида расчета (в примере это "Премия").

Такой подход гарантирует, что в базу попадут только те начисления, которые должны там быть согласно методологии расчета. Также рекомендуется проводить анализ конфигураций на наличие ошибок в вызовах процедур.

Пример 3: Получение базы за произвольный период для списка сотрудников

Рассмотрим еще один распространенный случай: необходимо рассчитать начисление для целого списка сотрудников по итогам прошедшего квартала.

Задача: получить суммарную базу по окладу для списка сотрудников за первый квартал года.


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

// Устанавливаем параметры
Запрос.УстановитьПараметр("ДатаНачала", '20230101');
Запрос.УстановитьПараметр("ДатаОкончания", '20230331');
Запрос.УстановитьПараметр("ВидРасчетаОклад", ПланыВидовРасчета.ОсновныеНачисления.Оклад);
Запрос.УстановитьПараметр("СписокСотрудников", МассивСотрудников);

РезультатЗапроса = Запрос.Выполнить();

В этом примере мы использовали другую виртуальную таблицу — БазаОсновныеНачисления. Она также удобна для получения базовых данных. Обратите внимание на параметры, которые передаются прямо в определении таблицы: (&ДатаНачала, &ДатаОкончания, ВидРасчета = &ВидРасчетаОклад). Это позволяет платформе эффективно отфильтровать данные еще до их получения запросом.

Условие ГДЕ ОсновныеНачисленияБаза.Сотрудник В (&СписокСотрудников) позволяет сделать отбор сразу по всему списку сотрудников, переданному в виде массива.

Итоги и рекомендации

Подведем итог. Для программного получения данных расчетной базы в 1С придерживайтесь следующих правил:

  1. Не используйте служебный метод ПрочитатьБазу(). Он предназначен для внутреннего использования платформой.
  2. Используйте запросы к виртуальным таблицам регистра расчета, таким как ДанныеГрафика или База....
  3. Для получения корректной базы связывайте запрос с настройками плана видов расчета, чтобы отбирать только те виды начислений, которые являются базовыми для текущего расчета.
  4. Всегда используйте параметры в запросах (&Сотрудник, &Период и т.д.) — это безопасно и оптимизирует выполнение запроса.
  5. Четко различайте поля ПериодРегистрации (дата документа) и ПериодДействия (период, к которому относится начисление). Используйте для отбора то поле, которое соответствует вашей бизнес-логике.

Применяя эти подходы, вы сможете надежно и правильно получать данные для самых сложных алгоритмов расчета в 1С.

← На главную