Поиск по номеру телефона — одна из самых частых задач при автоматизации работы с клиентами. Кажется, что достаточно простого запроса к справочнику Контрагенты, но на практике разработчики часто сталкиваются с ситуацией, когда запрос ничего не возвращает, хотя данные в базе точно есть. В этой статье мы подробно разберем причины возникновения таких ошибок, проанализируем типичные промахи и составим правильный алгоритм поиска, учитывающий особенности хранения данных в современных конфигурациях на базе БСП (Библиотеки стандартных подсистем), таких как 1С:УНФ.
Рассмотрим ситуацию, с которой столкнулся автор темы. В его исходном коде была допущена критическая ошибка при установке параметров запроса. Проанализируем этот фрагмент:
Запрос.УстановитьПараметр("Телефон", ЗначениеЗаполнено(Объект.Телефон));
Функция ЗначениеЗаполнено() возвращает булево значение: Истина или Ложь. Таким образом, вместо номера телефона (строки) в запрос передается логический тип. В результате запрос пытается найти в справочнике контрагента, у которого в поле номера телефона написано "Да", что, естественно, не дает результатов. Важно помнить: параметры запроса должны строго соответствовать типам данных, хранящимся в реквизитах базы данных.
Следующая неочевидная проблема связана с тем, как 1С преобразует числа в строки. Если номер телефона в документе или обработке хранится в числовом формате, прямое приведение к строке через Строка(Объект.Телефон) может добавить в результат неразрывные пробелы (НПП). Это стандартное поведение платформы для удобства визуального чтения больших чисел.
Например, число 89001234567 превратится в строку "8 900 123 45 67". Если в базе номер хранится без пробелов, прямое сравнение через оператор = не сработает.
Для решения этой проблемы мы рекомендуем использовать функцию Формат() с отключением группировки разрядов. Рассмотрим правильный способ подготовки параметра:
// Вместо Строка(Объект.Телефон) используем форматирование
ТелефонДляПоиска = Формат(Объект.Телефон, "ЧГ=0");
Запрос.УстановитьПараметр("Телефон", ТелефонДляПоиска);
Параметр "ЧГ=0" в строке формата гарантирует, что число будет преобразовано в строку «как есть», без лишних символов и пробелов.
Номера телефонов в базе могут быть записаны в разных форматах: со скобками, с дефисами или начинаясь с разных префиксов (+7, 8 или просто 9). Чтобы сделать поиск более гибким, вместо строгого равенства лучше использовать оператор ПОДОБНО.
Проанализируем ситуацию: если мы ищем номер, введенный пользователем, нам нужно подставить спецсимволы %, которые в языке запросов 1С означают любую последовательность символов. Посмотрим на пример кода:
ТекстЗапроса = "ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.НомерТелефона ПОДОБНО &Телефон";
// Очищаем номер и добавляем проценты для поиска подстроки
ЧистыйНомер = РаботаСКонтактнойИнформациейКлиентСервер.ТолькоЦифры(Объект.Телефон);
Запрос.УстановитьПараметр("Телефон", "%" + ЧистыйНомер + "%");
Такой подход позволит найти контрагента, даже если в базе номер записан как "(900) 123-45-67", а пользователь ввел просто "9001234567".
В современных конфигурациях (УНФ, ERP, КА, УТ 11) контактная информация (телефоны, адреса, e-mail) обычно хранится не в основном реквизите справочника, а в табличной части КонтактнаяИнформация. Это позволяет хранить неограниченное количество телефонов для одного контрагента.
Разберем структуру правильного запроса для поиска по этой табличной части. Выясним, как искать сразу по нескольким номерам (например, по основному и дополнительному), исключая при этом пустые значения:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| КИ.Ссылка КАК Контрагент
|ИЗ
| Справочник.Контрагенты.КонтактнаяИнформация КАК КИ
|ГДЕ
| (КИ.НомерТелефона ПОДОБНО &Телефон1 И &Телефон1Заполнен)
| ИЛИ (КИ.НомерТелефона ПОДОБНО &Телефон2 И &Телефон2Заполнен)";
// Подготовка параметров
Номер1 = Формат(Объект.Телефон1, "ЧГ=0");
Номер2 = Формат(Объект.Телефон2, "ЧГ=0");
Запрос.УстановитьПараметр("Телефон1", "%" + Номер1 + "%");
Запрос.УстановитьПараметр("Телефон1Заполнен", ЗначениеЗаполнено(Номер1));
Запрос.УстановитьПараметр("Телефон2", "%" + Номер2 + "%");
Запрос.УстановитьПараметр("Телефон2Заполнен", ЗначениеЗаполнено(Номер2));
Обратите внимание на использование ВЫБРАТЬ РАЗЛИЧНЫЕ. Это необходимо, чтобы в результат не попал один и тот же контрагент дважды, если у него, к примеру, один и тот же номер указан и как рабочий, и как мобильный.
Для максимально качественного поиска в 1С:УНФ рекомендуется использовать механизмы, заложенные в БСП. В конфигурации существует специальное поле в табличной части контактной информации — НомерТелефона, которое автоматически заполняется только цифрами при записи объекта.
Рассмотрим рекомендации по реализации «профессионального» поиска:
РаботаСКонтактнойИнформациейКлиентСервер.ТолькоЦифры() перед тем, как передать строку в запрос. Это удалит скобки, тире и пробелы из поискового запроса.УправлениеКонтактнойИнформацией. Часто там есть готовые функции, которые учитывают все нюансы хранения (включая регистры сведений, если КИ вынесена туда для оптимизации)."%" в начале строки (например, "%900123...") работает медленно на больших базах, так как SQL-сервер не может использовать индекс. Если база содержит десятки тысяч контрагентов, лучше хранить номера в нормализованном виде (только цифры) и искать по точному соответствию последних 10 цифр номера.Мы проанализировали основные причины, по которым поиск по номеру телефона может не работать. Подведем итог: всегда проверяйте типы передаваемых параметров (избегайте передачи Булево там, где нужна Строка), используйте Формат(..., "ЧГ=0") для числовых реквизитов и задействуйте возможности табличной части КонтактнаяИнформация с оператором ПОДОБНО для повышения гибкости поиска.