Как найти физическое лицо или покупателя по номеру телефона в 1С:Розница?

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

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

Почему не работает прямой запрос к справочнику

Рассмотрим типичные причины, из-за которых запрос к контактным данным завершается неудачей:

  1. Обращение к табличной части через точку от ссылки. Контактная информация в современных конфигурациях на базе БСП хранится не в регистре сведений и не в простых реквизитах шапки, а в табличной части КонтактнаяИнформация. Обращение вида ФизическиеЛица.КонтактнаяИнформация.НомерТелефонаБезКодов в секции ГДЕ некорректно, так как запрос должен адресоваться напрямую к таблице Справочник.ФизическиеЛица.КонтактнаяИнформация.
  2. Особенности реквизита НомерТелефонаБезКодов. По стандартам разработки данный реквизит содержит исключительно номер абонента без кода страны, префикса и кода города (например, для номера +7 (999) 123-45-67 в реквизит записывается только 1234567). Попытка сопоставить это поле с 10- или 11-значным номером приведет к пустому результату. Кроме того, если контакт вводился вручную без использования специализированной формы ввода телефона, этот реквизит может вовсе оставаться незаполненным.
  3. Поиск выполняется не в том объекте метаданных. В конфигурации «1С:Розница» справочник ФизическиеЛица используется преимущественно для учета сотрудников (кассиров, администраторов). Покупатели розничной сети чаще всего хранятся в справочнике Контрагенты (с признаком ЮрФизЛицо = ФизЛицо) либо их телефоны привязаны к справочнику ИнформационныеКарты (карты лояльности).
  4. Разнородный формат записи. Номера могут сохраняться в базе с кодом +7, с восьмеркой, с дефисами или скобками. Попытка поиска через точное равенство = без очистки строки от спецсимволов обычно не дает результата.

Способ 1. Запрос к табличной части с нормализацией строки

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


// 1. Нормализация входного номера телефона
ОчищенныйНомер = СокрЛП(ВходящийТелефон);
ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, "-", "");
ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, " ", "");
ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, "(", "");
ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, ")", "");
ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, "+", "");
ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, Символы.НПП, "");

// Берем последние 10 цифр номера (без префикса страны)
МаскаПоиска = "%" + Прав(ОчищенныйНомер, 10) + "%";

// 2. Выполнение запроса к табличной части
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ФизическиеЛицаКИ.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.ФизическиеЛица.КонтактнаяИнформация КАК ФизическиеЛицаКИ
    |ГДЕ
    |    ФизическиеЛицаКИ.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
    |    И ФизическиеЛицаКИ.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонФизическогоЛица)
    |    И ФизическиеЛицаКИ.Представление ПОДОБНО &МаскаПоиска";

Запрос.УстановитьПараметр("МаскаПоиска", МаскаПоиска);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка найденной ссылки
    СсылкаНаФизЛицо = Выборка.Ссылка;
КонецЦикла;

Обратим внимание на ключевые моменты этого кода:

  1. Мы явно фильтруем записи по реквизиту Тип с проверкой на Перечисление.ТипыКонтактнойИнформации.Телефон, чтобы исключить адреса электронной почты и почтовые адреса.
  2. Фильтрация по реквизиту Вид позволяет ограничить область поиска нужным видом контактной информации (например, ТелефонФизическогоЛица).
  3. Использование Прав(ОчищенныйНомер, 10) отсекает различия в префиксах (+7, 8, 7), а спецсимволы % обеспечивают совпадение вне зависимости от наличия пробелов или скобок в поле Представление.

Способ 2. Поиск по реквизиту «НомерТелефона»

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


ОчищенныйНомер = СокрЛП(ВходящийТелефон);
// Удаляем символы форматирования
СимволыДляУдаления = "- ()+";
Для Сч = 1 По СтрДлина(СимволыДляУдаления) Цикл
    ОчищенныйНомер = СтрЗаменить(ОчищенныйНомер, Сред(СимволыДляУдаления, Сч, 1), "");
КонецЦикла;

// Ищем совпадение по 10 цифрам в конце строки
МаскаПоиска = "%" + Прав(ОчищенныйНомер, 10);

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    КИ.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.ФизическиеЛица.КонтактнаяИнформация КАК КИ
    |ГДЕ
    |    КИ.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
    |    И КИ.НомерТелефона ПОДОБНО &МаскаПоиска";

Запрос.УстановитьПараметр("МаскаПоиска", МаскаПоиска);
РезультатЗапроса = Запрос.Выполнить();

Способ 3. Поиск среди покупателей (Контрагентов) и карт лояльности

Если поиск среди физических лиц не дал результатов, проверим справочник Контрагенты и карты лояльности. В розничной торговле покупатели фиксируются именно там:


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

Запрос.УстановитьПараметр("МаскаПоиска", "%" + Прав(ОчищенныйНомер, 10) + "%");
Результат = Запрос.Выполнить();

Если в конфигурации ведется учет дисконтных карт, номер телефона покупателя часто хранится в реквизитах справочника ИнформационныеКарты или связанных с ними регистрах сведений. В таких случаях поиск следует направить на соответствующую таблицу карт лояльности.

Использование штатных механизмов БСП

В конфигурациях 1С для разбора и обработки контактных данных предусмотрен общий модуль УправлениеКонтактнойИнформацией:

  1. Метод УправлениеКонтактнойИнформацией.СведенияОТелефоне(КонтактнаяИнформация) позволяет разобрать строку или JSON-структуру записи на составляющие: код страны, код города, номер абонента и добавочный номер.
  2. Метод УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов(...) возвращает готовую таблицу значений с контактными данными переданного массива ссылок.
  3. Если в информационной базе активна подсистема взаимодействий, можно воспользоваться функцией Взаимодействия.ПолучитьВсеКонтактыПоТелефону(...) для сквозного поиска объектов по всей базе.

Рекомендации по производительности и правам доступа

При внедрении поиска обратим внимание на важные архитектурные нюансы:

  1. Влияние оператора ПОДОБНО с маской "%...". Поиск с символом процента в начале строки исключает использование индексов СУБД (B-tree) и приводит к полному сканированию таблицы (Full Table Scan). Если база насчитывает сотни тысяч контрагентов, для высоконагруженных сценариев (например, всплывающее окно при входящем звонке) рекомендуется задействовать полнотекстовый поиск 1С через объект ПолнотекстовыйПоиск либо создать отдельный независимый регистр сведений, хранящий очищенный номер телефона и ссылку на объект.
  2. Ограничения доступа на уровне записей (RLS). Если у пользователя ограничены права, типовой запрос вернет пустой результат, даже если запись существует. Для гарантированного поиска в сервисных алгоритмах (при интеграции с АТС) следует использовать вызов УстановитьПривилегированныйРежим(Истина).
← На главную