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