Почему конечный остаток в запросе 1С зависит от начальной даты и как это исправить

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет
← На главную

В практике разработчика 1С иногда встречается парадоксальная ситуация: при выполнении запроса к виртуальной таблице ОстаткиИОбороты регистра накопления значение конечного остатка изменяется в зависимости от того, какую начальную дату мы указываем в параметрах. На первый взгляд это кажется невозможным, ведь остаток на конкретный момент времени — величина фиксированная и не должна зависеть от того, за какой предыдущий период мы смотрим обороты. Разберем подробно, почему это происходит и как привести данные в порядок.

Суть проблемы и анализ запроса

Рассмотрим классический пример запроса к регистру накопления (например, ПартииТоваровНаСкладахБухгалтерскийУчет), с которым столкнулся автор темы:


ВЫБРАТЬ
    ПартииТоваров.Номенклатура,
    ПартииТоваров.Склад,
    ПартииТоваров.КоличествоНачальныйОстаток,
    ПартииТоваров.КоличествоПриход,
    ПартииТоваров.КоличествоРасход,
    ПартииТоваров.КоличествоКонечныйОстаток
ИЗ
    РегистрНакопления.ПартииТоваровНаСкладахБухгалтерскийУчет.ОстаткиИОбороты(
            &ДатаНач,
            &ДатаКон,
            ,
            ,
            Номенклатура = &Номенклатура И Склад = &Склад
    ) КАК ПартииТоваров

Проблема проявляется следующим образом: если установить &ДатаНач на 01.02.2018 00:00:00, конечный остаток на 02.02.2018 23:59:59 равен 98. Однако, если изменить &ДатаНач всего на одну секунду или на следующий день (02.02.2018 00:00:00), конечный остаток внезапно превращается в 106. При этом &ДатаКон в обоих случаях остается неизменной.

Почему так происходит: механизм работы итогов

Чтобы понять причину, проанализируем, как платформа 1С работает с итогами. Физически данные в регистре накопления хранятся в двух основных таблицах: таблице движений и таблице итогов. Таблица итогов содержит рассчитанные значения остатков на начало каждого месяца (01.01, 01.02, 01.03 и т.д.).

Когда мы обращаемся к виртуальной таблице ОстаткиИОбороты, система не всегда считает всё с нуля по движениям. Она пытается оптимизировать запрос:

  1. Если дата начала совпадает с началом месяца: Платформа может взять готовое значение из таблицы итогов на эту дату.
  2. Если дата начала не совпадает с точкой хранения итогов: Система берет ближайшие итоги и «докручивает» их, прибавляя или вычитая обороты из таблицы движений.

Если в базе произошло рассогласование итогов (когда сумма движений за январь не соответствует разнице между итогами на 01.01 и 01.02), мы получаем разные результаты. В первом случае (с 1-го числа) запрос «доверился» битым итогам на 01.02. Во втором случае (со 2-го числа) запрос начал расчет от другой точки (например, от итогов на 01.03 назад или от актуальных текущих итогов), и ошибка исчезла.

Способ 1: Полный пересчет итогов через Конфигуратор

Это самый надежный метод решения проблемы. Простой вызов метода ПересчитатьТекущиеИтоги() часто оказывается бесполезным, так как он затрагивает только актуальный период, а проблема может крыться в итогах многолетней давности. Рассмотрим пошагово, как выполнить полное исправление:

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

Важно: Данная операция требует монопольного доступа к базе и может занять значительное время (от нескольких часов до суток на очень больших базах). Поэтому выполнять её рекомендуется в периоды минимальной нагрузки (например, в выходные).

Способ 2: Управление итогами в пользовательском режиме

Если вы не можете остановить работу всей компании для Тестирования и исправления, попробуйте выполнить выборочный пересчет для конкретного регистра. Проанализируем, как это сделать через стандартный интерфейс:

  1. Откройте «Функции для технического специалиста» (или «Все функции»).
  2. Найдите стандартную обработку Управление итогами.
  3. Найдите в списке ваш регистр (ПартииТоваровНаСкладахБухгалтерскийУчет).
  4. Обратите внимание на дату «Период рассчитанных итогов».
  5. Попробуйте выполнить действие Установить период рассчитанных итогов на более раннюю дату (например, на начало года), а затем верните её на текущий месяц. Это инициирует пересчет данных за указанный промежуток.

Способ 3: Программный сброс и включение итогов

Иногда штатные средства пересчета «вылетают» по таймауту или из-за блокировок. В таком случае можно прибегнуть к радикальному, но эффективному методу: полному отключению и включению использования итогов для конкретного регистра. Рассмотрим пример кода:


// Отключаем использование итогов - это физически очистит таблицу итогов регистра
РегистрыНакопления.ПартииТоваровНаСкладахБухгалтерскийУчет.УстановитьИспользованиеИтогов(Ложь);

// Включаем обратно - система начнет полный пересчет таблицы итогов на основании движений
РегистрыНакопления.ПартииТоваровНаСкладахБухгалтерскийУчет.УстановитьИспользованиеИтогов(Истина);

После выполнения этого кода записи в таблице итогов будут гарантированно соответствовать записям в таблице движений. Выясним причину расхождений заранее: чаще всего они возникают при массовой загрузке данных в режиме ОбменДанными.Загрузка = Истина или при аварийных завершениях работы сервера SQL во время записи транзакций.

Особенности работы с границами периодов

При написании запросов к виртуальным таблицам важно помнить о типе данных параметров ДатаНач и ДатаКон. Рассмотрим, как правильно передавать параметры, чтобы избежать захвата лишних секунд или потери документов, записанных в ту же секунду:

Вместо передачи простого значения Дата, рекомендуется использовать объект Граница. Это особенно критично для ДатаКон, так как документ может иметь время 23:59:59, но при этом располагаться в «конце» этой секунды.


ГраницаКон = Новый Граница(КонецДня(ПараметрДатаКон), ВидГраницы.Включая);
Запрос.УстановитьПараметр("ДатаКон", ГраницаКон);

Резюме

Если вы обнаружили, что остатки «плывут» при изменении периода отчета — это диагноз: рассогласование итогов. Не пытайтесь исправить это программными фильтрами в запросе или изменением метода дополнения периодов. Единственный верный путь — полный пересчет итогов. Начните с обработки «Управление итогами», и если она не поможет, планируйте проведение «Тестирования и исправления» в Конфигураторе.

← На главную