Почему расходятся остатки в виртуальных таблицах 1С "Остатки" и "ОстаткиИОбороты"?

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

При работе с регистрами накопления в 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С не пересчитывает все движения регистра каждый раз, а хранит заранее рассчитанные остатки на определенные моменты времени (например, на начало каждого месяца). Когда вы запрашиваете данные у таблицы ОстаткиИОбороты, платформа выполняет следующие действия:

  1. Находит ближайшую рассчитанную точку итогов к началу вашего периода (&НачДата).
  2. Берет остаток из этой точки.
  3. "Досчитывает" обороты между точкой итогов и началом вашего периода, чтобы получить точный НачальныйОстаток.
  4. Рассчитывает обороты внутри вашего периода.
  5. Складывает начальный остаток и обороты для получения конечного остатка.

Основная причина расхождений — повреждение или неактуальность данных в таблице итогов. Если из-за сбоя, некорректного обновления или других причин итоги за какой-то месяц (в нашем случае, вероятно, за начало января) рассчитаны неверно, то виртуальная таблица ОстаткиИОбороты, опираясь на эти неверные данные, выдаст некорректный начальный, а следовательно, и конечный остаток. В то же время таблица Остатки на ту же дату может использовать другую точку итогов или другой алгоритм расчета, что и приводит к разным результатам.

Решение: пересчет итогов регистра накопления

Самый надежный и правильный способ исправить эту проблему — заставить платформу полностью перестроить таблицы итогов на основе первичных данных из таблицы движений регистра. Эта операция называется пересчетом итогов.

ВНИМАНИЕ: Перед выполнением этой операции обязательно сделайте резервную копию вашей информационной базы. На больших базах данных процесс может занять продолжительное время и создать значительную нагрузку на сервер.

Рассмотрим, как выполнить пересчет итогов через Конфигуратор.

  1. Запустите 1С в режиме «Конфигуратор».
  2. В главном меню выберите «Администрирование» → «Тестирование и исправление...».
  3. В открывшемся окне установите переключатель в положение «Тестирование и исправление».
  4. В списке проверок найдите и установите флажок напротив пункта «Пересчет итогов». Остальные флажки рекомендуется снять, если вы не преследуете цель полной проверки базы.
  5. Убедитесь, что внизу выбран режим «Тестирование и исправление», а не «Только тестирование».
  6. Нажмите кнопку «Выполнить».

Процесс может занять от нескольких минут до нескольких часов в зависимости от размера базы и производительности оборудования. В разобранном нами случае для базы размером 180 Гб пересчет занял около 25 минут.

После завершения пересчета итогов проблема была полностью решена. Запрос к виртуальной таблице ОстаткиИОбороты стал возвращать корректные и консистентные данные, совпадающие с результатами таблицы Остатки.

Итоговый результат после пересчета:

Теперь конечный остаток (15) совпадает с тем, что возвращает таблица Остатки, независимо от начальной даты периода.

Дополнительные рекомендации

Таким образом, если вы столкнулись с необъяснимым расхождением данных в остатках, первым делом стоит проверить и пересчитать итоги соответствующего регистра. В большинстве случаев это решает проблему.

← На главную