Базовый период в регистре расчёта 1С — это интервал, за который платформа собирает «базу» для расчёта начисления: например, сумму оклада за два предыдущих месяца, от которой считается премия. Включается флагом «Базовый период» у регистра расчёта, а сама база читается из виртуальной таблицы База<ИмяБазовогоРегистра>. Перерасчёт — подчинённый регистру объект, куда платформа автоматически записывает начисления, которые нужно пересчитать, если ведущие начисления изменились задним числом.
В статье соберём сквозной пример: ежемесячная премия в процентах от оклада за два прошлых месяца, её расчёт через таблицу базы и проверка того, как перерасчёт ловит изменение оклада. Пример учебный, на «чистой» конфигурации, но механизм тот же, что работает внутри ЗУП.
Исходные данные примера
Предполагаем, что в конфигурации уже есть:
- план видов расчёта
ОсновныеНачисленияс видомОклад(использует период действия); - регистр расчёта
ОсновныеНачисленияс измерениемСотрудник, ресурсомСумма, графиком работы; - документ
НачислениеЗарплатыс реквизитомПериодРегистрации, который пишет оклад в этот регистр.
Задача: добавить премию, которая начисляется раз в месяц и равна проценту от оклада за указанный период (например, за два предыдущих месяца).
Шаг 1. План видов расчёта для разовых начислений
Премия не протяжённа во времени, поэтому хранить её в плане с периодом действия не стоит. Создаём план видов расчёта ДополнительныеНачисления. На вкладке «Расчёт»:
| Свойство | Значение | Почему |
|---|---|---|
| Использует период действия | Нет | Премия — разовое начисление |
| Зависимость от базы | Зависит по периоду действия | База берётся за месяцы, к которым относится оклад |
| Базовые планы видов расчёта | ОсновныеНачисления, ДополнительныеНачисления | В базу попадают оклад и прошлые премии |
Про «Зависимость от базы» стоит понимать разницу. По периоду действия — база собирается по фактическому периоду действия базовых записей: если оклад за февраль доначислили в апреле, он всё равно относится к февралю. По периоду регистрации — база собирается по полю ПериодРегистрации: доначисление за февраль, зарегистрированное в апреле, попадёт в апрельскую базу.
Создаём предопределённый вид расчёта Премия и заполняем две вкладки:
- Базовые —
ОкладиПремия: от них считается база. Базовыми могут быть и протяжённые, и непротяжённые виды расчёта. - Ведущие —
ОкладиПремия: при их изменении текущая премия становится неактуальной и должна попасть в перерасчёт.
Шаг 2. Регистр расчёта с базовым периодом
Создаём регистр расчёта ДополнительныеНачисления:
- план видов расчёта —
ДополнительныеНачисления; - периодичность — месяц;
- флаг «Базовый период» — включён; у регистра появляются поля
БазовыйПериодНачалоиБазовыйПериодКонец; - регистратор — документ
НачислениеЗарплаты; - измерение
Сотрудник, ресурсСумма, реквизитПараметр(процент премии).

Шаг 3. Движения документа
В документ добавляем табличную часть ДополнительныеНачисления с колонками Сотрудник, ВидРасчета (тип ПланВидовРасчетаСсылка.ДополнительныеНачисления), БазовыйПериодНачало, БазовыйПериодКонец, ПроцентПремии. В обработке проведения формируем движения без суммы — сумму посчитаем следующим шагом:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// ... движения по регистру ОсновныеНачисления формируются выше.
Движения.ДополнительныеНачисления.Записывать = Истина;
Для Каждого СтрокаНачисления Из ДополнительныеНачисления Цикл
Движение = Движения.ДополнительныеНачисления.Добавить();
Движение.Сторно = Ложь;
Движение.ПериодРегистрации = ПериодРегистрации;
Движение.ВидРасчета = СтрокаНачисления.ВидРасчета;
Движение.Сотрудник = СтрокаНачисления.Сотрудник;
Движение.БазовыйПериодНачало = НачалоДня(СтрокаНачисления.БазовыйПериодНачало);
Движение.БазовыйПериодКонец = КонецДня(СтрокаНачисления.БазовыйПериодКонец);
Движение.Параметр = СтрокаНачисления.ПроцентПремии;
КонецЦикла;
Движения.Записать();
РасчетЗарплаты.РассчитатьОклад(Ссылка, Движения.ОсновныеНачисления);
РасчетЗарплаты.РассчитатьПремию(Ссылка, Движения.ДополнительныеНачисления);
КонецПроцедурыДва момента. КонецДня у конца базового периода обязателен: без него последний день периода не войдёт в базу. И порядок расчёта важен — сначала оклад, потом премия, иначе база окажется пустой.
Шаг 4. Расчёт премии через виртуальную таблицу базы
Поскольку для плана ДополнительныеНачисления базовым указан ОсновныеНачисления, у регистра появляется виртуальная таблица БазаОсновныеНачисления. Её параметры:
- Измерения основного регистра — массив имён измерений текущего регистра;
- Измерения базового регистра — массив соответствующих измерений базового регистра;
- Разрезы — дополнительные разрезы базы (здесь не нужны);
- Условие — отбор записей основного регистра.
Измерения сопоставляются по порядку элементов массивов: в нашем случае Сотрудник текущего регистра соответствует Сотрудник базового.
// Рассчитывает премию процентом от базы за базовый период.
Процедура РассчитатьПремию(Регистратор, НаборЗаписей) Экспорт
ИзмеренияОсновного = Новый Массив;
ИзмеренияОсновного.Добавить("Сотрудник");
ИзмеренияБазового = Новый Массив;
ИзмеренияБазового.Добавить("Сотрудник");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| База.НомерСтроки КАК НомерСтроки,
| ЕСТЬNULL(База.СуммаБаза, 0) КАК СуммаБаза
|ИЗ
| РегистрРасчета.ДополнительныеНачисления.БазаОсновныеНачисления(
| &ИзмеренияОсновного,
| &ИзмеренияБазового,
| ,
| Регистратор = &Регистратор
| И ВидРасчета = &Премия) КАК База";
Запрос.УстановитьПараметр("ИзмеренияОсновного", ИзмеренияОсновного);
Запрос.УстановитьПараметр("ИзмеренияБазового", ИзмеренияБазового);
Запрос.УстановитьПараметр("Регистратор", Регистратор);
Запрос.УстановитьПараметр("Премия", ПланыВидовРасчета.ДополнительныеНачисления.Премия);
БазаПоСтрокам = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
БазаПоСтрокам.Вставить(Выборка.НомерСтроки, Выборка.СуммаБаза);
КонецЦикла;
Для Каждого Запись Из НаборЗаписей Цикл
Если Запись.ВидРасчета <> ПланыВидовРасчета.ДополнительныеНачисления.Премия Тогда
Продолжить;
КонецЕсли;
СуммаБазы = БазаПоСтрокам.Получить(Запись.НомерСтроки);
Запись.Сумма = ?(СуммаБазы = Неопределено, 0, Окр(СуммаБазы * Запись.Параметр / 100, 2));
КонецЦикла;
// Набор уже сформирован, нужно только записать рассчитанные суммы.
НаборЗаписей.Записать(Истина, Истина);
КонецПроцедурыПоле СуммаБаза — это ресурс Сумма базового регистра с суффиксом «База». Вместо поиска по выборке в цикле (НайтиСледующий + Сбросить на каждой записи) я складываю результат в соответствие по номеру строки: при сотнях сотрудников разница по времени заметна.
Проверка на числах: если по сотруднику за январь и февраль начислено 120 000 ₽ оклада, а процент премии 10, премия за март составит 12 000 ₽.
Шаг 5. Перерасчёт: как поймать изменения задним числом
Предположим, оклад за февраль исправили с 60 000 на 80 000 ₽. Мартовская премия теперь посчитана от неверной базы. Чтобы это не прошло незамеченным, у регистра ДополнительныеНачисления создаём перерасчёт ПерерасчетПремии:
- В ветке регистра «Перерасчёты» добавляем перерасчёт.
- Добавляем измерение перерасчёта
Сотрудник. - Связываем его с измерением
Сотрудниксамого регистра и с измерениями ведущих регистров.
Связь измерений определяет точность: при изменении оклада Иванова в перерасчёт попадёт премия Иванова, а не премии всех сотрудников.

Что попало в перерасчёт, видно запросом:
ВЫБРАТЬ
Перерасчет.ОбъектПерерасчета КАК Документ,
Перерасчет.ВидРасчета КАК ВидРасчета,
Перерасчет.Сотрудник КАК Сотрудник
ИЗ
РегистрРасчета.ДополнительныеНачисления.ПерерасчетПремии КАК ПерерасчетДо изменения оклада таблица пуста. После перепроведения февральского документа с новым окладом в ней появляется мартовский документ с видом расчёта Премия по Иванову.
Важно: платформа только отмечает, но не пересчитывает
Записи перерасчёта — это список дел, а не исправление. Дальше прикладной код должен:
- пересчитать отмеченные начисления — в ЗУП это делают специальными документами, в простых конфигурациях часто перепроведением исходного документа или отдельным документом доначисления;
- очистить записи перерасчёта по обработанным документам.
Очистка выполняется набором записей перерасчёта:
НаборПерерасчета = РегистрыРасчета.ДополнительныеНачисления.Перерасчеты.ПерерасчетПремии.СоздатьНаборЗаписей();
НаборПерерасчета.Отбор.ОбъектПерерасчета.Установить(ДокументПремии);
НаборПерерасчета.Записать(); // пустой набор с отбором удаляет записиКак проверить настройку на тестовых данных
Прежде чем отдавать механизм расчётчикам, я прогоняю короткий сценарий:
- Провести начисление оклада за два месяца по одному сотруднику.
- Провести премию за третий месяц и сверить сумму с ручным расчётом.
- Изменить оклад за один из прошлых месяцев и перепровести документ.
- Убедиться, что в таблице перерасчёта появилась премия именно этого сотрудника и никого лишнего.
- Пересчитать премию и проверить, что запись перерасчёта очистилась.
Пять шагов занимают полчаса, а ловят почти все ошибки настройки: неверные базовые виды, несвязанные измерения перерасчёта и забытый конец дня в базовом периоде.
Типичные ошибки
- Не задан конец дня у
БазовыйПериодКонец— последний день не входит в базу. - Перепутаны базовые и ведущие — база считается верно, но изменения задним числом не ловятся, или наоборот.
- Измерения перерасчёта не связаны с измерениями ведущих регистров — в перерасчёт попадает всё подряд или ничего.
- Записи перерасчёта не очищаются — таблица разрастается, и пользователи перестают ей доверять.
- Неверный порядок расчёта — премия считается раньше оклада и получает нулевую базу.
В типовой ЗУП этот механизм уже реализован, и вмешиваться в него стоит аккуратно, через доработку ЗУП с расширением, а не правкой типовых модулей. В собственных конфигурациях его удобно закладывать сразу при разработке конфигурации.
Итог
- Флаг «Базовый период» добавляет регистру поля
БазовыйПериодНачалоиБазовыйПериодКонец, а база читается из виртуальной таблицыБаза<Регистр>. - «Зависимость от базы» задаёт, по какому периоду собирать базу: по периоду действия или регистрации.
- Базовые виды расчёта отвечают за то, от чего считать, ведущие — за то, когда пересчитывать.
- Перерасчёт только отмечает устаревшие начисления; пересчитывает и очищает их прикладной код.




