Сбои в работе серверного оборудования или файловой системы часто приводят к частичному повреждению базы данных 1С. Одной из самых неприятных последствий такой ситуации является появление «битых ссылок» (надписей вида «Объект не найден...») в регистрах бухгалтерии. Особенно критично это для счетов расчетов (например, 62 «Расчеты с покупателями»), где аналитика ведется в разрезе документов расчетов. Если ссылка на такой документ повреждена, закрыть задолженность в типовой конфигурации становится невозможно.
В данной статье мы подробно рассмотрим, как программно выявить и исправить поврежденные записи в регистре бухгалтерии, почему нельзя полагаться на виртуальные таблицы при восстановлении данных и как правильно использовать объектную модель 1С для внесения изменений. Если необходимо быстро восстановить данные без разработки собственного кода, можно воспользоваться обработкой для восстановления битых ссылок.
Рассмотрим ситуацию: при попытке сформировать отчет или программно прочитать данные через виртуальную таблицу РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты, мы видим, что поле Регистратор содержит значение Неопределено, а в поле Субконто3 красуется «Объект не найден». Попытка установить отбор в наборе записей по значению Неопределено закономерно приводит к ошибке: «Не установлен отбор по регистратору».
Проанализируем причину. Виртуальные таблицы (остатки и обороты) строятся платформой на лету на основании итогов и физических движений. Если связь между записью в таблице итогов и физической проводкой нарушена из-за сбоя, платформа не может сопоставить данные и выдает Неопределено. Для исправления ситуации нам нужно работать только с физической таблицей регистра.
Первым делом нам необходимо найти все записи в регистре бухгалтерии, где в качестве аналитики (субконто) выступает битая ссылка. Важно искать именно в физической таблице движений РегистрБухгалтерии.Хозрасчетный, так как в ней поле Регистратор всегда заполнено ссылкой (даже если сам документ-регистратор удален, ссылка на него в таблице регистра остается).
Разберем пример запроса для поиска проводок по счету 62, где третье субконто («Документы расчетов с контрагентами») повреждено:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Хозрасчетный.Регистратор КАК Регистратор,
| Хозрасчетный.НомерСтроки КАК НомерСтроки,
| Хозрасчетный.Организация КАК Организация,
| Хозрасчетный.Субконто1 КАК Контрагент,
| Хозрасчетный.Субконто2 КАК Договор
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.СчетДт = &Счет
| И Хозрасчетный.Субконто3.Ссылка ЕСТЬ NULL
| И НЕ Хозрасчетный.Субконто3 = ЗНАЧЕНИЕ(Документ.ДокументРасчетовСКонтрагентом.ПустаяСсылка)";
Запрос.УстановитьПараметр("Счет", ПланыСчетов.Хозрасчетный.РасчетыСПокупателями);
РезультатЗапроса = Запрос.Выполнить();
Обратите внимание на условие Субконто3.Ссылка ЕСТЬ NULL. Это классический способ в 1С определить «битую» ссылку: сама ссылка в базе есть (ее GUID), но в таблице объекта, на который она указывает, записи не существует.
Поскольку мы не можем просто «починить» удаленный объект (его данных больше нет в базе), нам необходимо создать новый технический документ, который заменит собой битую ссылку. В конфигурации «Бухгалтерия предприятия 3.0» для этих целей идеально подходит ДокументРасчетовСКонтрагентом.
Рассмотрим функцию создания такого документа:
Функция СоздатьТехническийДокументРасчетов(Организация, Контрагент, Договор)
НовыйДок = Документы.ДокументРасчетовСКонтрагентом.СоздатьДокумент();
НовыйДок.Дата = '20231231235959'; // Устанавливаем дату конца периода
НовыйДок.Организация = Организация;
НовыйДок.Контрагент = Контрагент;
НовыйДок.Договор = Договор;
НовыйДок.Комментарий = "Создано автоматически для исправления битой ссылки";
Попытка
НовыйДок.Записать(РежимЗаписиДокумента.Запись);
Возврат НовыйДок.Ссылка;
Исключение
Сообщить("Ошибка при записи документа: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
КонецФункции
Теперь перейдем к самому ответственному моменту — модификации записей регистра. В 1С записи регистра бухгалтерии изменяются только через НаборЗаписей с обязательным отбором по Регистратору. Мы не можем изменить одну конкретную строку, не прочитав весь набор записей по данному документу.
Проанализируем алгоритм:
НаборЗаписей.Субконто3 повреждено, и подставляем наш новый документ.
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем новый документ расчетов для каждой уникальной пары Контрагент-Договор
// (В реальной задаче лучше кешировать ссылки, чтобы не создавать лишнего)
НоваяСсылка = СоздатьТехническийДокументРасчетов(Выборка.Организация, Выборка.Контрагент, Выборка.Договор);
Если НоваяСсылка = Неопределено Тогда Продолжить; КонецЕсли;
Набор = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(Выборка.Регистратор);
Набор.Прочитать();
БылиИзменения = Ложь;
Для Каждого Запись Из Набор Цикл
// Проверяем, является ли субконто битым в данной строке
Если Запись.СчетДт = ПланыСчетов.Хозрасчетный.РасчетыСПокупателями Тогда
// Проверка через ПолучитьОбъект() - надежный способ выявить битую ссылку
Если Запись.СубконтоДт[3] <> Неопределено И Запись.СубконтоДт[3].ПолучитьОбъект() = Неопределено Тогда
Запись.СубконтоДт[3] = НоваяСсылка;
БылиИзменения = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если БылиИзменения Тогда
Набор.Записать();
Сообщить("Исправлены записи в документе: " + Выборка.Регистратор);
КонецЕсли;
КонецЦикла;
Иногда ситуация хуже: повреждена не просто аналитика, а сам Регистратор. В этом случае в физической таблице вместо ссылки на реальный документ мы видим GUID, которого нет в базе. Прочитать такой набор записей стандартным методом Набор.Прочитать() может не получиться, либо 1С выдаст ошибку при записи. Для решения этой проблемы можно использовать обработку для удаления зависших проводок после удаления документов.
Рассмотрим варианты решения этой проблемы:
После того как мы программно исправили все движения в физической таблице РегистрБухгалтерии.Хозрасчетный, данные в отчетах (например, в ОСВ по счету 62) все еще могут отображаться некорректно. Это происходит потому, что таблицы итогов хранят старые, поврежденные значения.
Важный момент: Пересчет итогов не требует перепроведения документов. Это чисто техническая операция по актуализации агрегированных данных.
Для выполнения пересчета перейдите в раздел «Администрирование» — «Обслуживание» — «Управление итогами». Выберите нужный регистр и выполните полный пересчет за проблемный период. Только после этого шага виртуальные таблицы начнут возвращать корректные данные без значений Неопределено.
Любые манипуляции с регистрами бухгалтерии напрямую (через наборы записей) могут нарушить баланс, если код написан неверно. Перед выполнением исправлений обязательно сделайте резервную копию базы данных. Если база находится на SQL-сервере, рассмотрите возможность выполнения операции в транзакции или сначала протестируйте код на копии, восстановленной из бэкапа. При обслуживании нескольких баз процесс создания резервных копий и проверок можно автоматизировать с помощью программы для автоматического архивирования и тестирования баз 1С.
Проанализировав ситуацию, мы выяснили, что ключ к исправлению битых ссылок лежит в использовании физических таблиц и объектной модели НаборЗаписей. Комбинация запроса по физической таблице и точечного исправления субконто позволяет восстановить учет без необходимости массового перепроведения документов, что особенно важно для закрытых периодов.