Почему запрос к справочнику Контактные лица не возвращает данные по контрагенту в 1С

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

При разработке отчетов или сервисных обработок в конфигурациях 1С (таких как 1С:Бухгалтерия предприятия, 1С:ERP или 1С:Управление торговлей) разработчики часто сталкиваются с ситуацией: визуально в карточке контрагента отображаются контактные лица и их контактная информация (телефоны, e-mail, адреса), однако простой запрос к базе данных или объектный отбор возвращает пустой результат. Рассмотрим подробно причину такого поведения платформы и разберем по шагам, как выявить и исправить эту проблему.

Проблема: Запрос и объектный отбор возвращают пустую выборку

Проанализируем типичный сценарий. Разработчик пытается получить контактные данные или список контактных лиц конкретного контрагента. В конфигурациях на базе Библиотеки Стандартных Подсистем (БСП) справочник КонтактныеЛица является независимым, а связь с контрагентом или физическим лицом осуществляется через реквизит ОбъектВладелец составного типа (СправочникСсылка.Контрагенты, СправочникСсылка.ФизическиеЛица, СправочникСсылка.Пользователи и др.).

Посмотрим на пример запроса, который на первый взгляд выглядит абсолютно корректным:


ВЫБРАТЬ
	КонтактныеЛицаКонтактнаяИнформация.Представление КАК Представление
ИЗ
	Справочник.КонтактныеЛица.КонтактнаяИнформация КАК КонтактныеЛицаКонтактнаяИнформация
ГДЕ
	КонтактныеЛицаКонтактнаяИнформация.Ссылка.ОбъектВладелец = &Контрагент

Или аналогичный вариант программного отбора через объектную модель 1С:


Отбор = Новый Структура("ОбъектВладелец");
Отбор.ОбъектВладелец = НужныйКонтрагент;

Выборка = Справочники.КонтактныеЛица.Выбрать(,, Отбор);
_Ссылки = Новый Массив;

Пока Выборка.Следующий() Цикл
    _Ссылки.Добавить(Выборка.Ссылка);
КонецЦикла;

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

Выясняем причину: Дубли контрагентов и особенности составных типов

Разберем, почему возникает расхождение между тем, что мы видим на форме, и тем, что получает запрос.

В платформе «1С:Предприятие 8» равенство ссылочных типы данных определяется не по визуальному представлению (наименованию, ИНН или коду), а по уникальному идентификатору записи (GUID / UUID). В интерфейсе два элемента справочника могут выглядеть абсолютно одинаково — например, ООО «Вектор». Однако с точки зрения СУБД это два совершенно разных объекта.

Причина описываемой проблемы заключается в **наличии дублей элементов в справочнике Контрагенты**:

  1. Контактное лицо в базе данных было привязано к **Элементу А** (первый контрагент).
  2. В параметре запроса &Контрагент или структуре отбора передается **Элемент Б** (дублирующий контрагент с таким же наименованием).
  3. Поскольку идентификаторы у Элемента А и Элемента Б различаются, условие ОбъектВладелец = &Контрагент возвращает ЛОЖЬ для всех записей.

При этом в пользовательском интерфейсе оператор мог открыть карточку **Элемента А** и видеть контактные лица, а при проверке программного кода в качестве аргумента передавался **Элемент Б** (например, выбранный из другого документа или формы списка).

Как диагностировать проблему в отладчике и консоли запросов

Рассмотрим по шагам алгоритм локализации этой ошибки.

Шаг 1. Выполним запрос без отбора по контрагенту.
Чтобы убедиться, к какому именно объекту привязаны контактные лица, выполним запрос без фильтрации по конкретной ссылке:


ВЫБРАТЬ
	КонтактныеЛица.Ссылка КАК КонтактноеЛицо,
	КонтактныеЛица.ОбъектВладелец КАК Владелец,
	КонтактныеЛица.ОбъектВладелец.Код КАК КодВладельца,
	КонтактныеЛица.ОбъектВладелец.ИНН КАК ИННВладельца
ИЗ
	Справочник.КонтактныеЛица КАК КонтактныеЛица
ГДЕ
	КонтактныеЛица.Наименование ПОДОБНО "%Иванов%"

Шаг 2. Сравним уникальные идентификаторы.
В отладчике 1С вычислим значение уникальных идентификаторов для контрагента из вашего параметра и владельца контактного лица:


// Значение 1: Идентификатор контрагента из параметра
ИдентификаторИзПараметра = ИскомыйКонтрагент.Ссылка.УникальныйИдентификатор();

// Значение 2: Идентификатор реального владельца контактного лица
ИдентификаторИзБазы = СсылкаНаКонтактноеЛицо.ОбъектВладелец.УникальныйИдентификатор();

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

Решение проблемы и устранение дублей

Для исправления ситуации необходимо устранить дублирование элементов справочника `Контрагенты` и перевесить подчиненные объекты (включая контактные лица и документы) на один правильный элемент.

Способ 1. Использование стандартной обработки «Поиск и удаление дублей»

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

  1. Перейдем в раздел Администрирование → Обслуживание → Корректировка данных.
  2. Откроем ссылку Поиск и удаление дублей.
  3. В качестве объекта поиска выберем справочник Контрагенты.
  4. Установим правило сравнения: совпадение по **ИНН** и **Наименованию**.
  5. Нажмем Найти дубли.
  6. В списке найденных элементов укажем один в качестве основного (оригинала), а остальные отметим как дубли.
  7. Нажмем кнопку Объединить. Программа автоматически заменит все ссылки на дубли во всех документах, табличных частях и независимых справочниках (включая реквизит ОбъектВладелец справочника КонтактныеЛица), после чего пометит дубли на удаление.

Способ 2. Программная замена ссылок (для разработчиков)

Если необходимо выполнить объединение дублей программно, задействуем механизм БСП — функцию ОбщегоНазначения.ЗаменитьСсылки():


// Правильный контрагент, который должен остаться в базе
Оригинал = Справочники.Контрагенты.НайтиПоКоду("00-000001");

// Дубль, от которого избавляемся
Дубликат = Справочники.Контрагенты.НайтиПоКоду("00-000002");

МассивДублей = Новый Массив;
МассивДублей.Добавить(Дубликат);

// Выполняем замену ссылок во всей базе данных
ОбщегоНазначения.ЗаменитьСсылки(Оригинал, МассивДублей);

// Помечаем дубликат на удаление
ОбъектДубль = Дубликат.ПолучитьОбъект();
ОбъектДубль.УстановитьПометкуУдаления(Истина);

Оптимизация запросов к составным полям

При работе с реквизитами составного типа (такими как ОбъектВладелец) рекомендуется явно указывать ожидаемый тип данных в запросе с помощью функции ВЫРАЗИТЬ(). Это позволяет платформе генерировать более эффективный SQL-код и избегать лишних соединений с таблицами всех возможных типов:


ВЫБРАТЬ
	КонтактныеЛица.Ссылка КАК КонтактноеЛицо,
	КонтактныеЛица.Наименование КАК ФИО,
	КонтактнаяИнформация.Представление КАК ТелефонИлиEmail
ИЗ
	Справочник.КонтактныеЛица КАК КонтактныеЛица
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛица.КонтактнаяИнформация КАК КонтактнаяИнформация
		ПО КонтактнаяИнформация.Ссылка = КонтактныеЛица.Ссылка
ГДЕ
	ВЫРАЗИТЬ(КонтактныеЛица.ОбъектВладелец КАК Справочник.Контрагенты) = &Контрагент

Использование ВЫРАЗИТЬ() гарантирует, что платформа 1С ограничит выборку объектами конкретного справочника и оптимизирует план выполнения запроса на СУБД.

← На главную