При разработке отчетов или обработок в конфигурациях, использующих механизм расчета зарплаты (например, 1С:ЗУП 3.1), разработчики часто сталкиваются с проблемой «лишних» строк в регистре расчета Начисления. Эти строки появляются из-за механизма автоматического пересчета: когда мы открываем документ (например, «Увольнение» или «Отпуск»), программа может автоматически доначислить или сторнировать суммы за прошлые периоды на специальных вкладках. В этой статье мы подробно разберем, как оставить в запросе только те данные, которые относятся к основной табличной части документа, и исключить все сторно и автоматические корректировки.
Проанализируем ситуацию: в регистр расчета Начисления данные попадают не только из основной вкладки «Начисления», но и из вкладок «Пересчет начислений» или «Перерасчет НДФЛ». Когда система видит изменения в кадровых данных или прошлых периодах, она создает корректирующие записи. В запросе они могут выглядеть как дублирующие строки с отрицательными (сторно) или положительными значениями, что искажает итоговые показатели отработанных часов и сумм.
Самый простой и эффективный способ в современных конфигурациях 1С основан на особенностях работы платформы с идентификаторами строк. Рассмотрим подробнее, как система нумерует записи:
Выясним, как применить это в коде. Достаточно добавить условие в блок ГДЕ вашего запроса. Это позволит отсечь все «служебные» записи, которые не были введены пользователем вручную в основную ТЧ.
ВЫБРАТЬ
Начисления.Сотрудник КАК Сотрудник,
Начисления.Результат КАК Результат,
Начисления.ОтработаноЧасов КАК ОтработаноЧасов
ИЗ
РегистрРасчета.Начисления КАК Начисления
ГДЕ
Начисления.ИдентификаторСтроки < 1000000
И Начисления.ПериодРегистрации МЕЖДУ &НачПериода И &КонПериода
Важный нюанс: Не пытайтесь вставить это условие внутрь оператора сравнения в соединении (JOIN), как это иногда делают новички. Это должно быть либо самостоятельное условие в ГДЕ, либо четко отделенное условие связи.
Если вам нужно гарантированно получить только те строки, которые видит пользователь в конкретной табличной части «Начисления», мы можем использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ регистра с данными документа-регистратора. Рассмотрим этот метод на примере документа «Увольнение».
Разберем по шагам логику построения запроса:
Начисления документа-основания по двум полям: Регистратор (ссылка на документ) и ИдентификаторСтроки.
// Помещаем данные регистра во временную таблицу
ВЫБРАТЬ
Начисления.Сотрудник,
Начисления.Регистратор,
Начисления.ИдентификаторСтроки,
Начисления.Результат
ПОМЕСТИТЬ ВТ_ДанныеРегистра
ИЗ
РегистрРасчета.Начисления КАК Начисления
ГДЕ
Начисления.ПериодРегистрации МЕЖДУ &НачПериода И &КонПериода;
////////////////////////////////////////////////////////////////////////////////
// Фильтруем данные через внутреннее соединение с ТЧ документа
ВЫБРАТЬ
ВТ.Сотрудник,
ВТ.Результат,
ВТ.Регистратор
ИЗ
ВТ_ДанныеРегистра КАК ВТ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Увольнение.Начисления КАК ТЧ_Увольнение
ПО ВТ.Регистратор = ТЧ_Увольнение.Ссылка
И ВТ.ИдентификаторСтроки = ТЧ_Увольнение.ИдентификаторСтрокиВидаРасчета
Такой подход позволяет исключить любые записи, которых нет в визуальной таблице «Начисления» документа, включая все скрытые движения, порожденные механизмом перерасчетов.
Иногда простого исключения по идентификатору недостаточно, особенно если в документе «Отпуск» данные разбиваются по периодам (например, переходящий отпуск). В этом случае возникают дубли строк, которые кажутся одинаковыми.
Проанализируем ситуацию с полем Сторно. В регистре расчета есть стандартный реквизит Сторно (булево). Казалось бы, достаточно поставить фильтр ГДЕ Сторно = ЛОЖЬ. Однако это ловушка: если программа сначала сторнировала старый оклад (минус), а потом начислила новый (плюс) в рамках перерасчета, то фильтр по ЛОЖЬ уберет минус, но оставит плюс, что приведет к завышению итоговой суммы.
Вместо использования ВЫБРАТЬ РАЗЛИЧНЫЕ, которое не всегда корректно отрабатывает при наличии скрытых различий в полях времени, мы рекомендуем использовать группировку. Посмотрим на пример правильной структуры запроса:
ВЫБРАТЬ
Начисления.Сотрудник КАК Сотрудник,
Начисления.ВидРасчета КАК ВидРасчета,
СУММА(ЕСТЬNULL(Начисления.ОтработаноЧасов, 0)) КАК ОтработаноЧасов,
СУММА(Начисления.Результат) КАК Результат
ИЗ
РегистрРасчета.Начисления КАК Начисления
ГДЕ
Начисления.ИдентификаторСтроки < 1000000
СГРУППИРОВАТЬ ПО
Начисления.Сотрудник,
Начисления.ВидРасчета
В документах типа «Отпуск» или «Командировка» начисления часто разбиваются на несколько строк, если период действия начисления охватывает разные календарные месяцы. Чтобы избежать дублей, при которых одна и та же сумма или часы выводятся дважды, необходимо:
ВЫБРАТЬ не осталось уникальных полей, таких как НомерСтроки.ОтработаноЧасов. Часто записи пересчета имеют заполненную сумму, но нулевые часы. Добавление фильтра ГДЕ Начисления.ОтработаноЧасов > 0 может помочь, но будьте осторожны — это может отсечь разовые премии, где часы изначально не предусмотрены.ИдентификаторСтроки < 1000000 и обязательную группировку по ключевым полям сотрудника и вида расчета.Резюмируя, наиболее надежным и универсальным методом для разработчика 1С является фильтрация по ИдентификаторСтроки < 1000000. Это позволяет не привязываться к конкретным типам документов (Увольнение, Отпуск, Больничный) и автоматически отсекать все данные, порожденные механизмом автоматического исправления прошлых периодов.