Как найти и удалить скрытую ссылку на организацию в 1С, если ее нет в реквизитах документа?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

При ведении учета в многофирменных базах данных 1С часто возникает задача удаления одной из организаций. Это может быть связано с ее ликвидацией, реорганизацией или выделением бизнеса в отдельную информационную базу. Процесс очистки базы кажется тривиальным: пометить объекты на удаление и запустить стандартную обработку "Удаление помеченных объектов". Однако на практике разработчики сталкиваются с ситуацией, когда система наотрез отказывается удалять организацию, ссылаясь на документы других, вполне активных фирм.

Самое загадочное в этой ситуации — визуальное отсутствие связи. Мы открываем документ, на который указывает платформа, но там указана совершенно другая организация. Мы выгружаем документ в XML-формат, ищем GUID удаляемой организации внутри файла — и снова ничего не находим. В этой статье мы подробно разберем, почему возникают такие "фантомные" ссылки и как очистить базу данных от нежелательных связей.

В чем суть проблемы: почему стандартный поиск бессилен?

Когда мы запускаем процедуру НайтиПоСсылкам() или штатную обработку удаления, платформа 1С сканирует все таблицы базы данных, в которых может содержаться тип ссылки на удаляемый справочник СправочникСсылка.Организации. Сюда входят не только реквизиты шапки и табличных частей документов, но и движения регистров, последовательности, системные журналы, а также служебные таблицы механизмов версионирования.

Проблема кроется в том, что в процессе жизнедеятельности документа его реквизиты могли меняться. Например, бухгалтер по ошибке создал документ по ликвидированной фирме, провел его, а затем осознал ошибку, перевыбрал правильную организацию и перепровел документ. Визуально в документе все чисто. Но в системных таблицах базы данных информация о первой (ошибочной) организации могла сохраниться в скрытом виде.

Давайте подробно проанализируем основные места, где могут прятаться такие ссылки, и разберем по шагам методы их устранения.

Решение 1. Очистка истории версий (Версионирование объектов БСП)

Как показывает практика практикующих разработчиков, это самая частая причина появления фантомных ссылок в типовых конфигурациях (таких как "Бухгалтерия предприятия 3.0", "ERP" или "Комплексная автоматизация").

Если в системе включена опция версионирования объектов, то при каждом изменении и сохранении документа программа записывает его предыдущее состояние. Эти данные хранятся в регистре сведений РегистрСведений.ВерсииОбъектов. Данные самой версии сжимаются и записываются в реквизит с типом ХранилищеЗначений в формате XML или двоичных данных.

Поскольку платформа анализирует связи внутри этого хранилища, поиск ссылок указывает на сам документ-источник. При этом в текущем состоянии документа организации уже давно нет, а в xml-файле выгрузки самого документа ее тоже не будет, так как выгружается только текущая активная версия.

Для устранения этой проблемы нам потребуется программно очистить историю версий для проблемных документов. Рассмотрим пример кода, который решает эту задачу:


// Определим проблемный документ, на который ругается система
ПроблемныйДокумент = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("0000-0001", ТекущаяДата());

Если Не ПроблемныйДокумент.Пустая() Тогда
    // Создаем набор записей регистра версий объектов с отбором по нашему документу
    НаборЗаписей = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Объект.Установить(ПроблемныйДокумент);
    
    // Прочитаем существующие версии
    НаборЗаписей.Прочитать();
    
    Если НаборЗаписей.Количество() > 0 Тогда
        КоличествоВерсий = НаборЗаписей.Количество();
        // Очищаем набор записей
        НаборЗаписей.Очистить();
        НаборЗаписей.Записать();
        Сообщить("Успешно удалено версий: " + КоличествоВерсий + " для документа " + ПроблемныйДокумент);
    Иначе
        Сообщить("История версий для документа отсутствует.");
    КонецЕсли;
КонецЕсли;

После удаления записей из этого регистра версий повторно запустите поиск ссылок на организацию. В большинстве случаев фантомная связь исчезнет.

Решение 2. Системный механизм "История данных" платформы

Начиная с версии платформы 8.3.11, в 1С реализован встроенный механизм истории данных (Data History). Он работает на уровне самой СУБД независимо от БСП. Если для метаданных документа включена история данных, платформа сериализует изменяемые данные и хранит их в системных таблицах.

Эти таблицы недоступны через обычные запросы 1С, но контролируются платформой при поиске ссылок. Чтобы очистить эту историю программно, воспользуемся методом встроенного языка:


// Очистка истории изменений объекта на уровне платформы
ПроблемныйДокумент = Документы.РеализацияТоваровУслуг.НайтиПоРеквизиту("Номер", "0000-0001");

Если Не ПроблемныйДокумент.Пустая() Тогда
    // Используем менеджер истории данных для удаления всех версий объекта
    ИсторияДанных.Очистить(ПроблемныйДокумент);
    Сообщить("История данных платформы для объекта успешно очищена.");
КонецЕсли;

Решение 3. Проверка последовательностей документов

Еще одно неочевидное место обитания скрытых ссылок — последовательности документов (например, последовательность "ПартионныйУчет" или "ВосстановлениеРасчетов"). Последовательности имеют свои таблицы регистрации, где измерениями часто выступают организации.

Если документ когда-то был проведен по старой организации, запись в таблице регистрации последовательности могла зависнуть из-за некорректного проведения или сбоя транзакции в прошлом. Чтобы избавиться от таких записей, можно принудительно исключить документ из последовательности программным путем или временно распровести его, очистить движения и провести заново под корректной организацией.

Решение 4. Зависшие движения в регистрах (Проблема "Загрузка = Истина")

В практике обменов данными часто используется запись объектов в режиме загрузки:

ДокументОбъект.ОбменДанными.Загрузка = Истина;

При такой записи платформенные механизмы контроля и автоматического удаления движений могут не отрабатывать. В результате может возникнуть ситуация "сиротских" движений: документ изменен, в реквизитах указана новая организация, но в одном из регистров накопления или сведений осталась запись, где регистратором выступает наш документ, но в измерении "Организация" до сих пор записана старая удаляемая компания.

Выяснить это можно с помощью запроса по метаданным. Проанализируем все движения документа по регистрам:


// Проверим движения конкретного документа на наличие старой организации
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Взаиморасчеты.Организация КАК Организация,
    |	Взаиморасчеты.Регистратор КАК Регистратор
    |ИЗ
    |	РегистрНакопления.ВзаиморасчетыИначе КАК Взаиморасчеты
    |ГДЕ
    |	Взаиморасчеты.Регистратор = &ПроблемныйДокумент";

Запрос.УстановитьПараметр("ПроблемныйДокумент", ПроблемныйДокумент);
Результат = Запрос.Выполнить();

Если Не Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл
        Если Выборка.Организация = УдаляемаяОрганизацияСсылка Тогда
            Сообщить("Обнаружено некорректное движение в регистре взаиморасчетов!");
            // Здесь должен быть код перезаписи движений регистра
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Для исправления такой ситуации достаточно открыть документ, сделать его непроведенным, убедиться, что все движения полностью очистились, и провести его заново.

Решение 5. Разделение базы данных через механизм РИБ

Если база данных огромная, документов с фантомными ссылками слишком много и ручная или программная очистка истории версий занимает колоссальное количество времени, стоит рассмотреть кардинальный, но крайне эффективный метод разделения базы.

Использование механизма Распределенных Информационных Баз (РИБ) с фильтрацией по организации позволяет получить "чистую" рабочую базу без упоминания ликвидированной фирмы за минимальное количество шагов:

  1. Создаем в конфигураторе новый план обмена с фильтрацией данных по организации (или используем существующий в типовой конфигурации).
  2. Настраиваем узел РИБ, указывая в качестве разрешенных только те организации, которые должны остаться в рабочей базе.
  3. Создаем начальный образ подчиненного узла. Платформа автоматически перенесет в новую базу только те документы, справочники и движения, которые имеют отношение к разрешенным организациям. Все "мусорные" и скрытые связи ликвидированной фирмы просто не попадут в новую базу физически.
  4. После создания подчиненного узла и успешной проверки данных отвязываем его от главного узла, превращая в самостоятельную информационную базу. Для этого достаточно запустить базу с параметром запуска /ResetMasterNode или выполнить простую строчку кода в режиме предприятия:

// Отвязка подчиненного узла РИБ программным путем
ПланыОбмена.УстановитьГлавныйУзел(Неопределено);
Сообщить("База данных успешно переведена в режим главного узла.");

Этот метод гарантирует стопроцентное избавление от любых хвостов, скрытых записей в СУБД и оптимизирует размер базы данных.

Резюме

Столкнувшись со скрытыми ссылками при удалении объектов, не спешите паниковать и грешить на физическое повреждение базы данных. Пройдите по шагам предложенный нами чек-лист:

  1. Проверьте регистр сведений Версии объектов и очистите историю версий для документов, мешающих удалению.
  2. Очистите Историю данных на уровне платформы.
  3. Убедитесь, что сеанс запущен под пользователем с полными правами без RLS, чтобы исключить сокрытие данных правами доступа.
  4. Если объем ручной работы слишком велик — воспользуйтесь механизмом РИБ по организации для быстрого и чистого разделения баз.
← На главную