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