Каждый разработчик 1С рано или поздно сталкивается с ситуацией, когда при построении отчета или выполнении запроса к виртуальным таблицам регистра накопления (например, ОстаткиИОбороты) внезапно появляются странные фантомные записи. В поле Регистратор при этом отображается пустое значение или вовсе Неопределено, а показатели прихода, расхода или остатка удваиваются, искажая финансовую картину.
Самое интересное начинается при попытке раскопать проблему глубже: мы открываем основную таблицу движений регистра, но там этих записей просто нет! В этой статье мы подробно разберем, почему возникает этот сбой, проанализируем физическую природу механизма итогов 1С и изучим по шагам три надежных способа решения данной проблемы.
Чтобы понять, откуда берутся пустые строки, давайте проанализируем физическую структуру базы данных 1С. В СУБД (будь то MS SQL Server, PostgreSQL или IBM DB2) под каждый регистр накопления выделяется несколько физических таблиц:
Когда мы обращаемся к виртуальной таблице ОстаткиИОбороты, платформа 1С не считывает все движения напрямую. Она берет готовые данные из таблицы текущих итогов на начало периода и прибавляет к ним обороты из таблицы движений за выбранный интервал времени. Если в результате какого-то системного сбоя, некорректной транзакции или динамического обновления базы данных в таблице итогов "застряли" хвосты, а в таблице движений эти записи были удалены, мы получаем несоответствие. Эти незакрытые в ноль остатки платформа пытается сопоставить с временной шкалой и выводит их как движения с пустым регистратором.
Рассмотрим поочередно три эффективных метода борьбы с этой неполадкой.
Многие разработчики совершают типичную ошибку: пытаются отключить и заново включить использование итогов в режиме "1С:Предприятие" или запускают стандартный пересчет программными методами менеджера регистра. Зачастую это не приносит результата, поскольку система пытается пересчитать итоги "вперед", не затрагивая прошлые битые периоды.
Гарантированно очистить фантомные записи помогает полное тестирование и исправление базы данных из режима конфигуратора. Давайте разберем этот процесс по шагам:
Во время этого процесса 1С полностью очищает таблицы итогов и заново выстраивает их структуру на основании только тех записей, которые физически существуют в таблице движений. Фантомные строки с пустыми регистраторами исчезнут.
Иногда появление пустых строк — это не сбой базы данных, а штатное поведение платформы, вызванное ошибкой в самом тексте запроса. Проанализируем пример запроса, с которым часто возникают проблемы:
ВЫБРАТЬ
АЭ_Взаиморасчеты.Регистратор КАК Регистратор,
АЭ_Взаиморасчеты.СуммаПриход КАК СуммаПриход,
АЭ_Взаиморасчеты.СуммаРасход КАК СуммаРасход,
АЭ_Взаиморасчеты.СуммаКонечныйОстаток КАК СуммаКонечныйОстаток
ИЗ
РегистрНакопления.АЭ_ВзаиморасчетыПоГрафикуЗаймов.ОстаткиИОбороты(, &МоментВремени, Регистратор, , ) КАК АЭ_Взаиморасчеты
Обратите внимание на параметры виртуальной таблицы ОстаткиИОбороты. Если в параметрах детально указана периодичность (например, Регистратор), а четвертый параметр (МетодДополнения) не задан или установлен в значение ДвиженияИПериоды, платформа 1С будет принудительно дополнять выборку временными интервалами. Если в каком-то периоде движений по регистратору не было, но по аналитике висит остаток, система выведет пустую строку с регистратором Неопределено для соблюдения целостности временного ряда.
Как это исправить:
Период или вовсе откажитесь от детализации по регистратору в параметрах ВТ, если это возможно.Движения. В этом случае пустые строки, генерируемые механизмами дополнения периодов, выводиться не будут.Бывают ситуации, когда запись в таблице движений действительно существует, но сам документ-регистратор был физически удален из базы данных (например, при непосредственном удалении без контроля ссылочной целостности). В этом случае в поле регистратора отображается надпись <Объект не найден> с длинным буквенно-цифровым кодом в скобках. Это уникальный идентификатор (GUID) удаленного документа.
Попытка очистить движения с помощью объекта РегистрНакопленияНаборЗаписей напрямую вызовет ошибку Не установлен отбор по регистратору, так как установить отбор по битой ссылке платформа не позволяет. С обойдем это ограничение с помощью проверенного лайфхака:
Шаг 1. Восстанавливаем документ-пустышку с нужным UUID. Получив уникальный идентификатор из битой ссылки, мы можем программно создать новый документ того же типа с этим же идентификатором. Рассмотрим пример кода:
// Предположим, битая ссылка вела на документ "РасходныйКассовыйОрдер"
ИмяДокумента = "РасходныйКассовыйОрдер";
ИдентификаторСтрокой = "строка_с_GUID_из_битой_ссылки"; // Например: "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
НовыйUID = Новый УникальныйИдентификатор(ИдентификаторСтрокой);
ДокументСсылка = Документы[ИмяДокумента].ПолучитьСсылку(НовыйUID);
// Проверяем, действительно ли объекта нет в базе данных
Если ДокументСсылка.ПолучитьОбъект() = Неопределено Тогда
// Создаем новый документ-пустышку
НовыйДокумент = Документы[ИмяДокумента].СоздатьДокумент();
НовыйДокумент.УстановитьСсылкуНового(ДокументСсылка);
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Документ-пустышка успешно восстановлен!");
КонецЕсли;
Шаг 2. Очищаем движения. Теперь, когда в базе данных появился реальный физический документ (пусть и незаполненный), мы можем легко обратиться к его набору записей и очистить их:
НаборЗаписей = РегистрыНакопления.АЭ_ВзаиморасчетыПоГрафикуЗаймов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
// Записываем пустой набор записей, тем самым удаляя движения
НаборЗаписей.Записать(Истина);
Сообщить("Движения по регистратору успешно удалены!");
Шаг 3. Удаляем документ-пустышку. После того как движения стерты, восстанавливающий документ больше не нужен. Мы можем окончательно удалить его из базы данных стандартным способом (желательно через непосредственное удаление, чтобы не оставлять мусор в базе).
Проанализировав эти три метода, можно сделать вывод: в подавляющем большинстве случаев проблема "фантомных" записей решается простым пересчетом итогов в Конфигураторе или правильным позиционированием параметров метода дополнения в запросе. Применяйте данные подходы последовательно, и ваши регистры всегда будут находиться в идеальном порядке!