Почему не схлопываются остатки в регистре накопления и как найти скрытые различия в измерениях

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

В практике разработчика и аналитика 1С часто встречается ситуация: в виртуальной таблице остатков регистра накопления висят две строки, которые в сумме дают ноль. Визуально все измерения — Организация, Сотрудник, Статья расходов — кажутся идентичными, но платформа упорно отказывается «сворачивать» их в одну нулевую запись. Проанализируем, почему это происходит, и разберем по шагам методы диагностики этой проблемы.

Природа виртуальных таблиц и механизм «схлопывания»

Для начала вспомним, как работает платформа 1С:Предприятие 8. Виртуальная таблица Остатки формируется на лету на основании физической таблицы итогов или движений. Платформа группирует записи по всем измерениям регистра. Если хотя бы одно поле в базе данных отличается хотя бы на один бит, СУБД (будь то MS SQL или PostgreSQL) воспримет их как разные записи, и группировка не произойдет.

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

  1. Разные ссылки при одинаковом представлении. У двух элементов справочника может быть одинаковое наименование, но разные УникальныйИдентификатор (GUID).
  2. Различие между Неопределено и Пустой ссылкой. В составных типах данных (например, ДокументОснование) значение может быть не заполнено, но технически в одном случае это будет Неопределено, а в другом — пустая ссылка конкретного типа.
  3. Скрытые измерения. В регистре могут быть измерения, которые не выведены в текущий отчет, но присутствуют в структуре регистра.
  4. Разные типы пустых ссылок. Если измерение имеет составной тип из нескольких документов, то пустая ссылка на «Больничный лист» не равна пустой ссылке на «Начисление зарплаты».

Шаг 1: Проверка уникальных идентификаторов (GUID)

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

Напишем запрос, который выведет идентификаторы для подозрительных измерений:


ВЫБРАТЬ
    ЗарплатаКВыплатеОстатки.Сотрудник КАК Сотрудник,
    ЗарплатаКВыплатеОстатки.Сотрудник.УникальныйИдентификатор() КАК СотрудникGUID,
    ЗарплатаКВыплатеОстатки.СуммаВзаиморасчетовОстаток КАК Остаток
ИЗ
    РегистрНакопления.ЗарплатаКВыплате.Остатки КАК ЗарплатаКВыплатеОстатки

Если в результате запроса мы увидим разные значения в колонке СотрудникGUID при одинаковых именах, значит, в справочнике есть дубли. В системе ЗУП это часто случается, когда создаются разные карточки сотрудников для одного и того же физического лица (например, при внутреннем совместительстве).

Шаг 2: Анализ типов данных в составных измерениях

Одной из самых коварных проблем является различие типов в пустых значениях. Рассмотрим измерение ДокументОснование в регистре «Зарплата к выплате». Это измерение имеет составной тип. Если одна запись была сделана документом, который не заполнил это измерение (значение Неопределено), а вторая запись была сделана «Переносом данных», где была выбрана пустая ссылка конкретного типа документа, они не схлопнутся.

Выясним причину, используя функцию ТИПЗНАЧЕНИЯ в консоли запросов:


ВЫБРАТЬ
    ТИПЗНАЧЕНИЯ(ЗарплатаКВыплатеОстатки.ДокументОснование) КАК ТипДокумента,
    ЗарплатаКВыплатеОстатки.ДокументОснование КАК ЗначениеДокумента,
    ЗарплатаКВыплатеОстатки.СуммаВзаиморасчетовОстаток КАК Остаток
ИЗ
    РегистрНакопления.ЗарплатаКВыплате.Остатки КАК ЗарплатаКВыплатеОстатки

В результате мы можем увидеть следующую картину: в одной строке тип будет NULL или Неопределено, а во второй — Документ.НачислениеЗарплаты. Для платформы это фундаментально разные данные, несмотря на то, что в колонке «Значение» в обоих случаях будет пусто.

Шаг 3: Обращение к физической таблице движений

Когда работа с виртуальной таблицей остатков не дает ответа, нужно проанализировать «первоисточник» — физическую таблицу регистра. Это позволит увидеть, какие именно документы (регистраторы) создали эти записи и в какие периоды.

Рассмотрим пример запроса к основной таблице регистра:


ВЫБРАТЬ
    ЗарплатаКВыплате.Период КАК Период,
    ЗарплатаКВыплате.Регистратор КАК Регистратор,
    ЗарплатаКВыплате.ВидДвижения КАК ВидДвижения,
    ЗарплатаКВыплате.Сотрудник КАК Сотрудник,
    ЗарплатаКВыплате.СуммаВзаиморасчетов КАК Сумма
ИЗ
    РегистрНакопления.ЗарплатаКВыплате КАК ЗарплатаКВыплате
ГДЕ
    ЗарплатаКВыплате.Сотрудник = &Сотрудник
    И ЗарплатаКВыплате.Организация = &Организация

Проанализируем результаты. Особое внимание уделим колонке ВидДвижения. Иногда пользователи пытаются «обнулить» остаток, вводя запись с тем же знаком, но противоположным видом движения (например, вместо «Расход 30» вводят «Приход -30»). Хотя математически это дает ноль, технически в регистре остатков такие записи могут вести себя некорректно в зависимости от настроек конфигурации.

Шаг 4: Специфика регистратора «Начальная задолженность» в ЗУП

Как показывает практика разбора сложных случаев в ЗУП 3.1, часто проблема кроется в документе Начальная задолженность. Этот документ специфичен тем, что он может оставлять измерение ДокументОснование действительно пустым (тип Неопределено). В то же время универсальный документ Перенос данных при попытке очистить поле составного типа часто подставляет туда пустую ссылку первого доступного типа из списка метаданных.

Важный момент: если вы пытаетесь схлопнуть остаток, созданный Начальной задолженностью, с помощью Переноса данных, убедитесь, что в Переносе данных поле Документ-основание очищено полностью (клавишей Shift+F4), чтобы там установилось значение Неопределено, а не пустая ссылка на какой-нибудь «Больничный лист».

Шаг 5: Пересчет итогов и «битые» записи

Если запросы показывают абсолютную идентичность всех полей, включая типы и ГУИДы, но остаток все равно двоится, возможно повреждение таблицы итогов. Это случается при аварийном завершении работы сервера или сбоях СУБД.

Рассмотрим шаги по исправлению:

  1. Пересчет итогов: Через «Администрирование» — «Обслуживание» — «Управление итогами» выполните полный пересчет для конкретного регистра.
  2. Тестирование и исправление (ТиИС): Выполните процедуру «Пересчет итогов» в режиме Конфигуратора. Это принудительно очистит физические таблицы итогов (те, что с префиксом _AccumRegTotals в SQL) и заполнит их заново на основе таблицы движений.

Итоги диагностики

Подведем итог. Чтобы «схлопнуть» зависшие строки, выполним последовательность действий:

Помните, что регистр накопления в 1С — это строгая математическая модель. Если записи не соединяются, значит, между ними есть хотя бы минимальное техническое различие, которое нужно локализовать с помощью консоли запросов.

← На главную