При работе с виртуальными таблицами регистра бухгалтерии в 1С разработчики иногда сталкиваются с крайне странным поведением запросов. Вы выбираете данные из таблицы ОстаткиИОбороты за определенный период, накладываете фильтр по счету и субконто и видите в результате одну строку с заполненными оборотами (например, в поле СуммаОборот). Однако стоит вам добавить в список выбираемых полей поле Регистратор, как запрос возвращает абсолютно пустой результат.
Параллельно с этим в пользовательском режиме начинает «ломаться» Оборотно-сальдовая ведомость (ОСВ). На невалютных счетах (таких как 01, 02, 10, 41) внезапно появляются валютные суммы, хотя валютный учет для этих счетов в плане счетов отключен. В этой статье мы подробно разберем, почему возникает эта проблема, как локализовать некорректные записи с помощью запроса и как исправить базу данных несколькими способами.
Для того чтобы понять природу этой ошибки, нам необходимо заглянуть на уровень хранения данных СУБД. В платформе 1С:Предприятие для регистра бухгалтерии действуют строгие правила типизации полей в физических таблицах:
Валюта и ВалютнаяСумма хранятся соответствующие значения (ссылка на справочник валют и число).Валюта и ВалютнаяСумма по этой строке строго должно быть записано значение NULL.Если в силу каких-то причин (ошибки при программном переносе данных, некорректная работа обработок по поиску и замене дублей, сбои при обновлении метаданных) в эти поля вместо NULL записывается пустое значение (например, пустая ссылка на справочник валют или Неопределено), то логика СУБД нарушается.
Когда мы выполняем запрос к виртуальной таблице ОстаткиИОбороты без детализации по регистратору, платформа пытается рассчитать агрегированные итоги, опираясь на таблицы итогов регистра бухгалтерии. Из-за наличия некорректного значения в поле валюты расчет выдает фантомную сумму оборота. Но как только мы требуем вывести поле Регистратор, виртуальная таблица перестраивает sql-запрос так, чтобы соединить итоги с реальными записями физической таблицы регистра. В процессе этого соединения (из-за несоответствия типов и неявных фильтров платформы) некорректные записи просто отсекаются, и мы получаем пустую таблицу.
Прежде чем приступать к лечению базы данных, нам нужно убедиться, что проблема действительно кроется в некорректных валютных записях по невалютным счетам. Для этого воспользуемся консолью запросов и выполним следующий диагностический запрос к физической таблице регистра бухгалтерии:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Хозрасчетный.Регистратор КАК Регистратор,
Хозрасчетный.Счет КАК Счет,
Хозрасчетный.Валюта КАК Валюта,
Хозрасчетный.ВалютнаяСумма КАК ВалютнаяСумма
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
НЕ Хозрасчетный.Счет.Валютный
И (НЕ Хозрасчетный.Валюта ЕСТЬ NULL
ИЛИ НЕ Хозрасчетный.ВалютнаяСумма ЕСТЬ NULL)
Проанализируем этот запрос. Мы выбираем уникальные регистраторы и счета из таблицы проводок РегистрБухгалтерии.Хозрасчетный, где у счета выключен признак валютного учета, но при этом поля Валюта или ВалютнаяСумма содержат значения, отличные от NULL. Если запрос вернул строки — поздравляем, вы нашли причину сбоя.
Это самый простой, надежный и штатный метод исправления логической целостности базы данных, предусмотренный самой фирмой 1С. Выполнять его рекомендуется в монопольном режиме после создания резервной копии базы данных.
Во время тестирования платформа проанализирует все записи регистра бухгалтерии. Обнаружив строки, где по невалютным счетам заполнены валютные реквизиты, она автоматически перезапишет их значением NULL. В журнале регистрации при этом появятся системные сообщения об успешном исправлении записей.
Если ваша база данных имеет очень большой объем и запуск полного Тестирования и исправления требует слишком много времени, либо если невозможно получить монопольный доступ к системе на длительный период, проблему можно решить точечно с помощью программного скрипта.
Особенность платформы 1С состоит в том, что при записи набора записей регистра бухгалтерии система автоматически валидирует его состав. Если мы просто прочитаем движения по проблемному документу и запишем их обратно без изменений, платформа самостоятельно очистит некорректные валютные поля по невалютным счетам, установив туда требуемый NULL.
Напишем внешнюю обработку и запустим следующий код для автоматического исправления всех сбойных наборов записей:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Хозрасчетный.Регистратор КАК Регистратор
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| НЕ Хозрасчетный.Счет.Валютный
| И (НЕ Хозрасчетный.Валюта ЕСТЬ NULL
| ИЛИ НЕ Хозрасчетный.ВалютнаяСумма ЕСТЬ NULL)";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем набор записей по конкретному битому регистратору
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
// Прочитываем движения из базы данных
НаборЗаписей.Прочитать();
// Перезаписываем набор. При записи платформа принудительно
// установит NULL в поля Валюта и ВалютнаяСумма для невалютных счетов
Попытка
НаборЗаписей.Записать();
Сообщить("Успешно исправлены движения документа: " + Строка(Выборка.Регистратор));
Исключение
Сообщить("Не удалось перезаписать движения документа " + Строка(Выборка.Регистратор) + ". Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Этот метод чрезвычайно безопасен, поскольку он не вызывает перепроведения самих документов. Даты документов, их последовательность, ручные корректировки проводок и движения по другим регистрам останутся нетронутыми. Мы просто обновляем физические таблицы проводок, приводя их к правильному виду.
Существует еще один быстрый «обходной» маневр, который можно применить, если битые записи зафиксированы по какому-то одному конкретному счету. Этот способ заставляет платформу выполнить реструктуризацию данных по данному счету автоматически.
При отключении валютного признака система инициирует фоновый процесс очистки исторических данных по этому счету во всем регистре бухгалтерии и принудительно запишет NULL во все поля Валюта и ВалютнаяСумма по проводкам этого счета. Обратите внимание: на базах данных объемом в сотни гигабайт этот процесс может вызвать длительные транзакционные блокировки таблиц, поэтому данный способ рекомендуется применять только на небольших или средних информационных базах.
Каким бы из трех описанных способов вы ни воспользовались, после успешного исправления проводок необходимо выполнить пересчет бухгалтерских итогов, чтобы обновить агрегированные таблицы. Для этого перейдите в режим «1С:Предприятие», откройте меню Администрирование (или раздел Операции) — Управление итогами (в некоторых конфигурациях — Управление установкой периодов рассчитанных итогов) и выполните полный пересчет итогов по регистру бухгалтерии за все периоды, в которых были обнаружены ошибки.
После выполнения этих процедур попробуйте снова сформировать Оборотно-сальдовую ведомость и выполнить ваш запрос с полем Регистратор. Проблема с «невидимыми» регистраторами и зависшими валютными суммами будет полностью устранена!