В практике разработчика 1С нередко возникает ситуация, когда виртуальная таблица Остатки регистра накопления возвращает данные, которые, на первый взгляд, противоречат здравому смыслу. Например, движения по регистру начинаются только в текущем месяце, но запрос на начало этого же месяца упорно показывает некоторую сумму. Разберем детально, почему так происходит и какие шаги необходимо предпринять для устранения этой проблемы.
Рассмотрим пример запроса, который вызывает вопросы. Разработчик пытается получить остаток на определенную дату, используя следующий код:
ВЫБРАТЬ
"Остаток на начало периода",
ЕСТЬNULL(ДоходыИРасходыОстатки.СуммаОстаток, 0),
0
ИЗ
РегистрНакопления.ДоходыИРасходы.Остатки(&НачалоПериода, ) КАК ДоходыИРасходыОстатки
Несмотря на то, что первые записи в регистре, по мнению пользователя, появляются позже даты &НачалоПериода, система возвращает ненулевое значение. Подобные ситуации часто вызывают недоумение, но они имеют под собой четкие технические причины, связанные с архитектурой хранения данных в 1С:Предприятие.
Первое, что нам необходимо сделать — это убедиться, что наше представление о "первых записях" соответствует действительности. Виртуальные таблицы Остатки и ОстаткиИОбороты скрывают от нас реальное положение дел в базе данных. Чтобы увидеть истинную картину, проанализируем основную (физическую) таблицу регистра накопления.
Важно понимать: записи могли быть введены ошибочно с очень ранней датой (например, в 1612 году или в 0001 году) или программно без должного контроля периода. Выполним запрос к основной таблице движений без ограничения по периоду "сверху":
ВЫБРАТЬ
ДоходыИРасходы.Период,
ДоходыИРасходы.Регистратор,
ДоходыИРасходы.Сумма,
ДоходыИРасходы.ВидДвижения
ИЗ
РегистрНакопления.ДоходыИРасходы КАК ДоходыИРасходы
ГДЕ
ДоходыИРасходы.Период < &НачалоПериода
Если этот запрос вернет хотя бы одну строку, значит, причина найдена. Часто такие записи появляются из-за ошибок в обработках загрузки данных, когда в поле Дата документа попадает пустое значение, которое 1С интерпретирует как 01.01.0001. Такие записи не видны в стандартных отчетах за текущий год, но они напрямую влияют на остаток.
Если запрос к физической таблице не выявил записей до начала периода, значит, проблема кроется в механизме расчета итогов. Платформа 1С не вычисляет остатки с самого начала времен при каждом запросе — это было бы слишком медленно. Вместо этого в базе данных существуют специальные таблицы итогов (обычно с суффиксом Totals), где хранятся рассчитанные значения на конец каждого месяца.
Проанализируем ситуацию: когда вы запрашиваете остаток на 1 марта, система берет итоги на конец февраля. Если в таблице итогов произошел сбой (например, из-за аварийного завершения транзакции или некорректного обновления конфигурации), данные в ней могут перестать соответствовать сумме движений в основной таблице.
Выяснив причину, перейдем к решению. Основным инструментом здесь является пересчет итогов. Рассмотрим основные способы выполнения этой процедуры:
УстановитьПериодРассчитанныхИтогов или ПересчитатьИтоги для конкретного регистра.Рассмотрим пример программного обращения к методам управления итогами:
РегистрыНакопления.ДоходыИРасходы.УстановитьИспользованиеИтогов(Ложь);
РегистрыНакопления.ДоходыИРасходы.УстановитьИспользованиеИтогов(Истина);
Совет: Иногда простого пересчета недостаточно. В сложных случаях помогает полное отключение итогов, сохранение конфигурации и последующее их включение. Это принудительно очищает таблицы Totals и заполняет их заново на основе таблицы движений.
Разберем еще один важный нюанс, который может влиять на результат запроса — это использование объекта Граница. Если движения по регистру происходят ровно в ту же секунду, на которую мы запрашиваем остаток, результат будет зависеть от того, включена ли эта секунда в срез.
Посмотрим на пример установки параметра запроса с использованием исключающей границы:
Запрос.УстановитьПараметр("НачалоПериода", Новый Граница(НачалоДня(НачПериода), ВидГраницы.Исключая));
Если мы используем ВидГраницы.Исключая, то документы, созданные в 00:00:00 этого дня, не попадут в расчет остатка. Если используем просто дату или ВидГраницы.Включая — они будут учтены. Проанализируем, нет ли в вашем регистре документов с временем 00:00:00 даты начала периода.
Если вышеперечисленные шаги не помогли, стоит обратить внимание на более редкие, но возможные факторы:
Подведем итог нашему исследованию. Если вы столкнулись с некорректным остатком, действуйте по следующему плану:
.Остатки).&НачалоПериода..dt и загрузку обратно, что приведет к полной перестройке индексов и итогов.Соблюдение этого порядка действий позволяет гарантированно найти причину расхождения и восстановить корректность учетных данных в системе.