Свертка информационной базы — одна из наиболее ответственных процедур обслуживания конфигураций 1С. Нередко после выполнения свертки стандартными обработками пользователи и программисты сталкиваются с ситуацией, когда стандартные отчеты (например, ведомости по партиям, складам или взаиморасчетам) начинают показывать некорректные или «фантомные» начальные остатки на дату свертки, хотя в самой таблице движений регистра эти данные отсутствуют или свернуты правильно.
Разберем подробно, почему возникает подобное рассогласование данных, чем отличаются различные методы пересчета итогов в платформе «1С:Предприятие 8» и как гарантированно устранить ошибки в регистрах накопления.
Проанализируем внутреннее устройство регистров накопления остатков. Платформа 1С хранит информацию в базе данных СУБД в нескольких связанных таблицах:
Когда мы формируем отчет за неограниченный период («без периода»), платформа считывает данные из таблицы актуальных итогов или выполняет прямое суммирование движений. Однако, когда мы задаем конкретный интервал отчета (например, с 01.01.2016), механизм виртуальной таблицы остатков платформы берет зафиксированные остатки из таблицы месячных итогов на эту границу и накладывает движения за выбранный интервал.
Если в процессе свертки документы и движения за прошлые периоды были физически удалены или заменены документом ввода остатков, но таблица месячных итогов за прошлые годы не очистилась полностью, виртуальная таблица возвращает старое сальдо. В результате в отчете на дату начала периода появляется остаток, которого фактически нет в таблице движений регистратора.
Многие разработчики выполняют штатную процедуру «Тестирование и исправление» (ТиИ) в конфигураторе с установленным флагом пересчета итогов или вызывают метод менеджера регистра ПересчитатьИтоги(). Однако стандартный пересчет не всегда решает проблему «зависших» месячных срезов глубоких прошлых периодов.
Выясним различия между методами менеджера регистра накопления:
ПересчитатьИтоги() — обновляет только текущие (актуальные) итоги в рамках установленной границы рассчитанных итогов. Если в старых периодах остались рассогласованные записи, они могут остаться нетронутыми в таблице месячных итогов СУБД.ПересчитатьИтогиЗаПериод(<НачалоПериода>, <КонецПериода>) — выполняет принудительный помесячный пересчет за указанный интервал. Если метод вызван без параметров, платформа полностью пересчитывает абсолютно все месячные итоги регистра от самого первого движения до текущего момента на основании реально существующих записей в таблице движений.Рассмотрим наиболее надежный программный способ очистки и перестроения таблицы итогов конкретного регистра. Сначала мы временно отключаем использование итогов (это очищает агрегатные таблицы в СУБД), затем включаем их обратно и принудительно рассчитываем заново по всей истории движений.
Выполним следующий фрагмент кода во внешней обработке (обязательно в монопольном режиме):
ИмяРегистра = "ПартииТоваровНаСкладахБухгалтерскийУчет";
МенеджерРегистра = РегистрыНакопления[ИмяРегистра];
// Отключаем и включаем итоги для физической очистки таблиц в СУБД
МенеджерРегистра.УстановитьИспользованиеИтогов(Ложь);
МенеджерРегистра.УстановитьИспользованиеИтогов(Истина);
// Выполняем полный помесячный пересчет без параметров
МенеджерРегистра.ПересчитатьИтогиЗаПериод();
Если требуется выполнить данную операцию для всех регистров накопления конфигурации после масштабной свертки, применим циклический обход метаданных:
Для Каждого МетаданноеРегистра Из Метаданные.РегистрыНакопления Цикл
Менеджер = РегистрыНакопления[МетаданноеРегистра.Имя];
// Проверяем, поддерживает ли регистр остатки
Если МетаданноеРегистра.ВидРегистра = Метаданные.СвойстваОбъектов.ВидРегистраНакопления.Остатки Тогда
Менеджер.УстановитьИспользованиеИтогов(Ложь);
Менеджер.УстановитьИспользованиеИтогов(Истина);
Менеджер.ПересчитатьИтогиЗаПериод();
КонецЕсли;
КонецЦикла;
Рассмотрим интерактивный способ без написания программного кода через режим «1С:Предприятие»:
Иногда при прерывании процесса свертки или некорректном удалении объектов в базе могут остаться записи движений, у которых документ-регистратор был удален, но признак Активность = Истина сохранился. В интерфейсе такие записи не видны в разрезе документов, но они продолжают влиять на виртуальные остатки.
Проанализируем базу на наличие «битых» записей с помощью запроса в консоли запросов:
ВЫБРАТЬ
Регистр.Регистратор КАК Регистратор,
Регистр.Период КАК Период
ИЗ
РегистрНакопления.ПартииТоваровНаСкладахБухгалтерскийУчет КАК Регистр
ГДЕ
Регистр.Регистратор.Ссылка ЕСТЬ NULL
Если запрос возвращает строки, необходимо очистить набор записей по данным регистраторам программным путем, установив пустой отбор по проблемной ссылке и записав пустой набор.
Обратим внимание на важный нюанс позиционирования документов свертки по временной шкале:
КорректировкаЗаписейРегистров или ВводНачальныхОстатков) должны быть проведены строго последней секундой свернутого периода — 31.12.2015 23:59:59.01.01.2016 00:00:00, то при формировании отчета с отбором на начало дня 01.01.2016 (с исключением границы времени) данные ввода остатков могут не попасть в начальное сальдо отчета.Важное предостережение: операции полного отключения и пересчета итогов накладывают монопольные блокировки на таблицы СУБД. Выполняйте эти регламентные действия только при отсутствии активных сеансов пользователей в информационной базе.