Случайный ввод опечатки в поле даты (например, 216 год вместо 2016 года) — распространенная проблема при ручном заполнении документов или сбоях обмена данными. На первый взгляд кажется, что достаточно просто перевыбрать год в реквизите и перепровести документ. Однако на уровне платформы 1С:Предприятие проведение документа с датой из далекого прошлого вызывает серьезные скрытые технические последствия. Разберем по шагам, чем опасна эта ситуация, как правильно исправить данные и вернуть производительность информационной базы.
Проанализируем техническую сторону работы платформы 1С с регистрами накопления и бухгалтерии. Платформа формирует и хранит таблицы итогов с периодичностью в один календарный месяц. Когда в систему попадает проведенный документ, датированный, к примеру, 0216 годом, нижняя граница расчета итогов сдвигается на много веков назад.
В результате СУБД начинает хранить и поддерживать пустые помесячные срезы за весь образовавшийся период — от 216 до текущего года. Это приводит к следующим неприятным последствиям:
DATETIME не поддерживает значения ранее 1753 года, из-за чего платформа использует внутренние смещения дат, что создает дополнительную нагрузку при пересчете индексов.Прежде чем приступать к исправлению, выясним, затронула ли эта проблема другие документы или регистры. Ошибочная дата могла скопироваться в подчиненные структуры, движения или связанные периодические регистры сведений. Выполним поиск артефактов с помощью универсальной консоли запросов.
Посмотрим на пример текста запроса для поиска подозрительных документов:
ВЫБРАТЬ
Ссылка КАК ДокументСсылка,
Дата КАК ДатаДокумента,
Проведен КАК Проведен
ИЗ
Документ.ЗаказНаПеремещение
ГДЕ
ГОД(Дата) < 2000
Аналогичным образом проанализируем движения регистров накопления, по которым делает записи документ:
ВЫБРАТЬ
Регистратор,
Период
ИЗ
РегистрНакопления.ТоварыКПеремещению
ГДЕ
ГОД(Период) < 2000
Разберем порядок непосредственного исправления ошибочного объекта:
Важно: одного лишь исправления и перепроведения документа недостаточно! Платформа не удаляет автоматически пустые срезы итогов, которые уже были физически сгенерированы в таблицах базы данных за все прошлые века.
Чтобы физически очистить таблицы итогов от сформированного балласта, необходимо запустить процедуру управления итогами. Рассмотрим два способа выполнения этой процедуры.
Способ 1. Использование встроенных средств администрирования:
Способ 2. Программное управление итогами:
Для гарантированного сброса можно программно переключить итоги по регистру через код обработки:
Регистр = РегистрыНакопления.ТоварыКПеремещению;
// Отключаем итоги для очистки пустых срезов
Регистр.УстановитьИспользованиеИтогов(Ложь);
// Включаем итоги заново с пересчетом
Регистр.УстановитьИспользованиеИтогов(Истина);
Регистр.ПересчитатьИтоги();
После очистки итогов СУБД помечает освободившееся пространство как пустое, однако размер файлов базы данных на диске автоматически не уменьшается. Чтобы вернуть исходный размер базы и оптимизировать индексы, выполним следующие операции:
Переиндексация таблиц информационной базы, Пересчет итогов и Сжатие таблиц информационной базы.REBUILD INDEX) и операцию сжатия базы данных (SHRINK DATABASE) средствами MS SQL Server или PostgreSQL.Чтобы исключить повторение подобных сбоев, настроим превентивные механизмы защиты.
1. Настройка даты запрета изменения данных
Самый простой и эффективный способ для пользовательского ввода — включить механизм даты запрета редактирования (раздел Администрирование → Настройки пользователей и прав → Даты запрета изменения). Установка запрета на прошлые периоды не позволит провести документ с датой старше разрешенной границы.
2. Программный контроль через подписку на событие
Если документы создаются интеграциями или загрузками из внешних файлов в обход стандартных проверок, создадим подписку на событие ОбработкаПроверкиЗаполнения для всех документов метаданных:
Процедура ПроверитьКорректностьДатыПередЗаписью(Источник, Отказ, ПроверяемыеРеквизиты) Экспорт
МинимальныйГод = 2010;
Если ГОД(Источник.Дата) < МинимальныйГод Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
СтрШаблон("Год даты документа (%1) не может быть меньше %2!", Формат(Источник.Дата, "ДФ=yyyy"), МинимальныйГод),
Источник,
"Дата",
,
Отказ
);
КонецЕсли;
КонецПроцедуры
Использование события ОбработкаПроверкиЗаполнения предпочтительнее ПередЗаписью, так как оно корректно визуализирует ошибку на форме пользователя с подсветкой поля Дата и не вызывает аварийных прерываний системных транзакций.