При работе с регистрами накопления в 1С разработчики часто сталкиваются с ситуацией, когда два, казалось бы, аналогичных запроса к разным виртуальным таблицам возвращают разные данные по остаткам на одну и ту же дату. Это может ввести в заблуждение и привести к серьезным ошибкам в отчетах. Рассмотрим типичный пример такой проблемы и разберем, почему так происходит и как это исправить.
Представим, что нам нужно получить остаток товара на определенную дату. Для этого мы можем использовать виртуальную таблицу Остатки или ОстаткиИОбороты. Логично ожидать, что остаток из первой таблицы будет равен конечному остатку из второй. Но на практике это не всегда так.
Проанализируем ситуацию, с которой столкнулся автор. Есть два запроса к регистру накопления ТоварыНаСкладах.
Запрос 1: Получение остатков через виртуальную таблицу Остатки на дату &КонДата.
ВЫБРАТЬ
ТоварыНаСкладахОстатки.Склад,
ТоварыНаСкладахОстатки.Номенклатура,
ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&КонДата, Номенклатура = &Номенклатура) КАК ТоварыНаСкладахОстатки
Результат выполнения на 20.01.21:
Запрос 2: Получение остатков и оборотов за период с &НачДата по &КонДата.
ВЫБРАТЬ
ТоварыНаСкладахОстаткиИОбороты.Склад,
ТоварыНаСкладахОстаткиИОбороты.Номенклатура,
ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток,
ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачДата, &КонДата, , , Номенклатура = &Номенклатура) КАК ТоварыНаСкладахОстаткиИОбороты
Результат выполнения за период с 01.01.21 по 20.01.21:
Как мы видим, конечный остаток по Складу 1 в первом запросе (15) не совпадает с конечным остатком во втором (5). При этом автор отмечает, что если во втором запросе установить начальную дату позже, например, 02.01.21, то конечные остатки начинают совпадать. Это ключевой момент для диагностики.
Дальнейшее исследование показало еще более странное поведение. Сравним два запуска второго запроса с разницей в начальной дате всего в одну секунду.
Период: 01.01.21 00:00:00 - 20.01.21 00:00:00
Период: 01.01.21 00:00:01 - 20.01.21 00:00:00
Обратите внимание: оборот за период не изменился (-165), но начальный остаток изменился на 10 единиц, что, в свою очередь, изменило и конечный остаток. Это прямо указывает на то, что проблема кроется в расчете начального остатка для виртуальной таблицы ОстаткиИОбороты.
Механизм работы виртуальных таблиц сильно зависит от служебных данных — таблиц итогов. Для ускорения получения данных 1С не пересчитывает все движения регистра каждый раз, а хранит заранее рассчитанные остатки на определенные моменты времени (например, на начало каждого месяца). Когда вы запрашиваете данные у таблицы ОстаткиИОбороты, платформа выполняет следующие действия:
&НачДата).НачальныйОстаток.Основная причина расхождений — повреждение или неактуальность данных в таблице итогов. Если из-за сбоя, некорректного обновления или других причин итоги за какой-то месяц (в нашем случае, вероятно, за начало января) рассчитаны неверно, то виртуальная таблица ОстаткиИОбороты, опираясь на эти неверные данные, выдаст некорректный начальный, а следовательно, и конечный остаток. В то же время таблица Остатки на ту же дату может использовать другую точку итогов или другой алгоритм расчета, что и приводит к разным результатам.
Самый надежный и правильный способ исправить эту проблему — заставить платформу полностью перестроить таблицы итогов на основе первичных данных из таблицы движений регистра. Эта операция называется пересчетом итогов.
ВНИМАНИЕ: Перед выполнением этой операции обязательно сделайте резервную копию вашей информационной базы. На больших базах данных процесс может занять продолжительное время и создать значительную нагрузку на сервер.
Рассмотрим, как выполнить пересчет итогов через Конфигуратор.
Процесс может занять от нескольких минут до нескольких часов в зависимости от размера базы и производительности оборудования. В разобранном нами случае для базы размером 180 Гб пересчет занял около 25 минут.
После завершения пересчета итогов проблема была полностью решена. Запрос к виртуальной таблице ОстаткиИОбороты стал возвращать корректные и консистентные данные, совпадающие с результатами таблицы Остатки.
Итоговый результат после пересчета:
Теперь конечный остаток (15) совпадает с тем, что возвращает таблица Остатки, независимо от начальной даты периода.
Граница для явного указания, включать или не включать момент времени в период. Например, ГРАНИЦА(&КонДата, ВИДГРАНИЦЫ.ВКЛЮЧАЯ). Это помогает избежать неоднозначности на границах периодов и может помочь в диагностике подобных проблем.Таким образом, если вы столкнулись с необъяснимым расхождением данных в остатках, первым делом стоит проверить и пересчитать итоги соответствующего регистра. В большинстве случаев это решает проблему.