Почему при поиске ссылок на организацию выводятся документы без этого реквизита и как их очистить?

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

При администрировании и ведении учета в базах данных на платформе «1С:Предприятие 8» (особенно в конфигурациях «Бухгалтерия предприятия 3.0», «Комплексная автоматизация» или «ERP») администраторы и разработчики часто сталкиваются с задачей удаления неиспользуемых организаций. Процедура кажется стандартной: помечаем организацию на удаление, запускаем стандартную обработку «Удаление помеченных объектов», но система блокирует операцию. В списке связанных объектов внезапно появляются документы, в которых физически нет и никогда не было реквизита Организация. Ярким примером такого поведения является документ Установка цен номенклатуры.

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

Выясняем причину: как документ без реквизита связывается с организацией

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

К таким таблицам относятся:

  1. Реквизиты шапки и табличных частей документов.
  2. Измерения и ресурсы регистров сведений, накопления, расчета и бухгалтерии.
  3. Таблицы регистрации и границ последовательностей документов.

Именно в третьем пункте кроется разгадка нашей проблемы. В типовых конфигурациях существует механизм контроля хронологии — последовательность документов ДокументыОрганизаций. Данная последовательность имеет измерение Организация.

Документ Установка цен номенклатуры является «глобальным» для информационной базы. Изменение цен потенциально влияет на расчет себестоимости, продажи и партионный учет по всем юридическим лицам. Поэтому данный документ включен разработчиками в состав последовательности ДокументыОрганизаций.

Логика работы платформы при проведении такого документа выглядит следующим образом:

Почему нельзя использовать стандартную замену ссылок?

Некоторые специалисты пытаются решить проблему «в лоб» — использовать обработку «Поиск и замена значений», чтобы заменить удаляемую организацию на действующую в найденных ссылках. Рассмотрим, почему этот путь ошибочен и приведет к системному сбою.

Для каждого документа запись в таблице регистрации последовательности уникальна по ключевому полю, состоящему из комбинации Регистратор (сам документ) и измерений (в данном случае — Организация). Поскольку документ Установка цен номенклатуры уже успешно зарегистрирован по всем «живым» организациям при своем проведении, попытка заменить удаляемую организацию на действующую вызовет дублирование ключа записи. Платформа выдаст ошибку уникальности данных, и замена будет отклонена. Запись по удаляемой организации нужно именно полностью удалять из последовательности, а не заменять.

Пошаговое руководство по удалению скрытых связей

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

Шаг 1. Сброс границы последовательности

Прежде всего необходимо сдвинуть границу последовательности ДокументыОрганизаций по удаляемому юридическому лицу на самый верх (в начало времен — на дату 01.01.0001). Это освободит таблицу границ от ссылки на организацию. Выполним это с помощью следующего программного кода:


ГраницаНачалаВремен = Новый МоментВремени('00010101');
ОтборПоследовательности = Новый Структура("Организация", СсылкаНаУдаляемуюОрганизацию);
Последовательности.ДокументыОрганизаций.УстановитьГраницу(ГраницаНачалаВремен, ОтборПоследовательности);

Шаг 2. Очистка записей регистрации документов в последовательности

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


// ВНИМАНИЕ: Данный код вызовет ошибку выполнения!
НаборЗаписей = Последовательности.ДокументыОрганизаций.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Организация.Установить(СсылкаНаУдаляемуюОрганизацию); // Ошибка: Поле отбора недоступно

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

Чтобы обойти это ограничение, мы применим правильный двухэтапный алгоритм:

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

Рассмотрим детальный программный код, реализующий этот алгоритм:


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

Запрос.УстановитьПараметр("УдаляемаяОрганизация", СсылкаНаУдаляемуюОрганизацию);
РезультатЗапроса = Запрос.Выполнить();

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

Рекомендации по проведению операции удаления

После выполнения вышеописанного кода все скрытые связи между глобальными документами (такими как Установка цен номенклатуры) и вашей организацией будут разорваны. Однако для успешного завершения удаления организации крайне важно придерживаться следующих правил:

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

← На главную