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