Почему в динамическом списке справочника Партнеры недоступны служебные поля контактной информации через Ссылку?

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

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

Суть проблемы заключается в следующем. Мы имеем справочник Партнеры с настроенным динамическим списком, использующим произвольный запрос. В списке включено автозаполнение доступных полей (флаг Автозаполнение доступных полей установлен). При этом в запросе выбрана табличная часть КонтактнаяИнформация. Однако, когда мы пытаемся настроить форму и заглядываем в доступные поля компоновщика настроек (в ветку Ссылка), мы обнаруживаем, что там отсутствуют некоторые служебные поля КИ, такие как НомерТелефонаБезКодов или ДоменноеИмяСервера, хотя стандартные поля вроде НомерТелефона или АдресЭП доступны без проблем.

Давайте проведем совместное исследование, выясним причину такого поведения платформы «1С:Предприятие» и подсистемы «Контактная информация» БСП, а также разберем практические способы решения этой задачи.

Выясняем причину: как работает механизм характеристик

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

  1. Откроем дерево метаданных конфигурации.
  2. Найдем справочник Партнеры и откроем его свойства.
  3. Перейдем на вкладку Данные.
  4. В нижней части окна нажмем кнопку Характеристики (или вызовем ее через контекстное меню справочника).

Здесь мы увидим настройки интеграции справочника с механизмом характеристик платформы. Именно этот механизм отвечает за виртуальное «подтягивание» видов контактной информации в дерево доступных полей компоновщика настроек динамического списка. Настройки выглядят так:

Важный архитектурный вывод: Платформенный механизм характеристик устроен так, что для одного свойства (вида КИ) он может сопоставить и вывести «через точку» от объекта только одно конкретное поле значения, заданное в конфигураторе. Платформа физически не умеет генерировать множественные колонки (такие как домен, регион, очищенный номер телефона, код страны) для одной характеристики в рамках этой технологии.

Именно поэтому стандартные реквизиты вроде полного представления телефона или адреса почты выводятся, а вспомогательные служебные поля БСП, предназначенные для индексации и внутреннего поиска, остаются недоступными для прямого выбора через свойства Ссылка.<ИмяХарактеристики>.

Назначение полей НомерТелефонаБезКодов и ДоменноеИмяСервера

Рассмотрим подробнее, для чего нужны эти поля в логике Библиотеки стандартных подсистем:

Поскольку эти поля носят сугубо технический характер, разработчики БСП справедливо не стали перегружать ими механизм характеристик.

Способы решения проблемы

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

Способ 1. Использование левого соединения в запросе динамического списка (Рекомендуемый)

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

Разберем процесс настройки по шагам. Откроем свойства динамического списка Список на форме и перейдем к редактированию текста запроса. Заменим автоматическую выборку КИ на явное соединение:


ВЫБРАТЬ
    СправочникПартнеры.Ссылка КАК Ссылка,
    СправочникПартнеры.Код КАК Код,
    СправочникПартнеры.Наименование КАК Наименование,
    СправочникПартнеры.ЮридическоеФизическоеЛицо КАК ЮридическоеФизическоеЛицо,
    
    // Получаем очищенный номер телефона из первой связи
    ПартнерыТелефон.НомерТелефонаБезКодов КАК НомерТелефонаБезКодов,
    
    // Получаем домен почты из второй связи
    ПартнерыEmail.ДоменноеИмяСервера КАК ДоменноеИмяСервера
ИЗ
    Справочник.Партнеры КАК СправочникПартнеры
    
    // Левое соединение для получения телефона партнера
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыТелефон
        ПО ПартнерыТелефон.Ссылка = СправочникПартнеры.Ссылка
        И ПартнерыТелефон.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонПартнера)
        
    // Левое соединение для получения Email партнера
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыEmail
        ПО ПартнерыEmail.Ссылка = СправочникПартнеры.Ссылка
        И ПартнерыEmail.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.EmailПартнера)

Важный нюанс: Обратите внимание, что мы делаем ЛЕВОЕ СОЕДИНЕНИЕ и обязательно накладываем фильтр по конкретному предопределенному виду контактной информации (например, ТелефонПартнера и EmailПартнера). Это гарантирует, что строки динамического списка не будут дублироваться, если у одного партнера заполнено несколько телефонов разного вида.

После сохранения запроса новые поля появятся в ветке первого уровня компоновщика настроек. Мы сможем легко перетащить их на форму в виде колонок.

Способ 2. Программное добавление полей через БСП при создании формы

В современных редакциях БСП предусмотрены программные методы для интеграции контактной информации в динамические списки. Мы можем задействовать их в модуле формы списка в обработчике события ПриСозданииНаСервере.

Посмотрим на пример реализации кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Инициализируем параметры вывода контактной информации в списке
    ПараметрыВывода = УправлениеКонтактнойИнформацией.ПараметрыВыводаКонтактнойИнформацииВСписке();
    ПараметрыВывода.ИмяТаблицыСписка = "Справочник.Партнеры";
    ПараметрыВывода.ИмяДинамическогоСписка = "Список";
    
    // Добавляем КИ в динамический список программно через БСП
    // Метод автоматически модифицирует запрос динамического списка
    УправлениеКонтактнойИнформацией.ПриСозданииНаСервере(ЭтотОбъект, ПараметрыВывода);
    
КонецПроцедуры

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

Способ 3. Динамическое получение данных в событии ПриПолученииДанныхНаСервере

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

Для этого добавим обработчик события динамического списка ПриПолученииДанныхНаСервере:


&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // Соберем ссылки на партнеров, отображаемые на экране
    МассивПартнеров = Новый Массив;
    Для Каждого КлючИЗначение Из Строки Цикл
        МассивПартнеров.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;
    
    // Запрашиваем служебные поля пакетом из базы данных
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   КИ.Ссылка КАК Партнер,
        |   КИ.НомерТелефонаБезКодов КАК НомерТелефонаБезКодов
        |ИЗ
        |   Справочник.Партнеры.КонтактнаяИнформация КАК КИ
        |ГДЕ
        |   КИ.Ссылка В(&МассивПартнеров)
        |   И КИ.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонПартнера)";
        
    Запрос.УстановитьПараметр("МассивПартнеров", МассивПартнеров);
    ТаблицаДанных = Запрос.Выполнить().Выгрузить();
    
    // Заполняем полученные значения в оформление соответствующих строк формы
    Для Каждого СтрокаСписка Из Строки Цикл
        СтрокаДанных = ТаблицаДанных.Найти(СтрокаСписка.Ключ, "Партнер");
        Если СтрокаДанных <> Неопределено Тогда
            СтрокаСписка.Value.Данные["ТелефонБезКодов"] = СтрокаДанных.НомерТелефонаБезКодов;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Важное предупреждение по производительности: Мы категорически не рекомендуем использовать данный способ, если пользователям требуется выполнять интерактивную фильтрацию, поиск или сортировку по колонке НомерТелефонаБезКодов. Поскольку эти данные получаются «на лету» только для видимых строк, стандартные механизмы отбора платформы не смогут обработать эти значения по всему списку. Используйте этот способ исключительно для вывода справочной информации без возможности поиска по ней.

Резюме

Мы выяснили, почему в УТ 11.4 некоторые служебные поля контактной информации отсутствуют в доступных полях выбора компоновщика настроек «через точку» от Ссылки — это обусловлено ограничениями платформенного механизма Характеристик. Для решения этой задачи рекомендуется использовать явное левое соединение в запросе динамического списка (Способ 1), так как оно обеспечивает максимальную производительность базы данных и позволяет пользователям полноценно искать, фильтровать и сортировать данные в списке.

← На главную