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