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

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

В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача контроля уникальности данных. Одной из наиболее типичных ситуаций является проверка номера телефона клиента на предмет дублирования. Если номера хранятся не в основном реквизите, а в табличной части справочника, стандартные механизмы уникальности не работают, и нам требуется программная реализация. Рассмотрим подробно, как организовать такую проверку правильно и эффективно.

Анализ постановки задачи

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

Для решения этой задачи мы разберем следующие этапы:

  1. Создание поискового запроса к табличной части.
  2. Правильная передача параметров в запрос.
  3. Организация вызова проверки из формы (клиент-серверное взаимодействие).
  4. Нормализация данных для корректного сравнения.

Шаг 1: Подготовка запроса для поиска дублей

Проанализируем структуру запроса. Нам нужно обратиться не к самому справочнику, а к его табличной части. В языке запросов 1С табличные части представляются как отдельные таблицы вида Справочник.[ИмяСправочника].[ИмяТабличнойЧасти]. Основное условие поиска — совпадение номера телефона, но при этом мы должны исключить из поиска текущего клиента (того, чью карточку мы сейчас редактируем), иначе система найдет тот же самый номер, который мы только что ввели.

Рассмотрим пример правильного текста запроса:


ВЫБРАТЬ
    КлиентыНомераТелефона.Ссылка КАК КлиентСсылка,
    КлиентыНомераТелефона.НомерТелефонаКлиента КАК Номер
ИЗ
    Справочник.Клиенты.НомераТелефонаКлиента КАК КлиентыНомераТелефона
ГДЕ
    КлиентыНомераТелефона.НомерТелефонаКлиента = &НомерДляПоиска
    И КлиентыНомераТелефона.Ссылка <> &ТекущаяСсылка

Здесь &НомерДляПоиска — это значение, которое ввел пользователь, а &ТекущаяСсылка — ссылка на редактируемого клиента (Объект.Ссылка). Использование оператора <> (не равно) критически важно, так как без него при записи уже существующего клиента программа всегда будет находить "саму себя" и выдавать ложное сообщение о дубле.

Шаг 2: Реализация серверной функции поиска

Так как запросы могут выполняться только на стороне сервера, создадим в модуле формы функцию с директивой &НаСервере. Мы должны передать в неё номер телефона и ссылку на текущий объект. Обратите внимание на использование метода УстановитьПараметр — это единственный верный способ передачи переменных в запрос в 1С 8.3.

Разберем программный код функции:


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

В данном коде мы использовали конструкцию ВЫБРАТЬ ПЕРВЫЕ 1, так как для проверки факта наличия дубля нам достаточно найти хотя бы одно совпадение. Это повышает производительность системы, особенно на больших объемах данных.

Шаг 3: Вызов проверки из формы (события интерфейса)

Теперь выясним, в какой момент лучше всего вызывать эту проверку. Наиболее подходящим событием является ПередОкончаниемРедактирования табличной части на форме. Это позволит уведомить пользователя сразу после ввода номера, до того как он нажмет кнопку сохранения всего документа.

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


&НаКлиенте
Процедура НомераТелефонаПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
    
    Если ОтменаРедактирования Тогда
        Возврат;
    КонецЕсли;
    
    ТекущиеДанные = Элементы.НомераТелефона.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Вызываем серверную функцию для поиска дублей
    Дубликат = НайтиДубликатНомераНаСервере(ТекущиеДанные.НомерТелефонаКлиента, Объект.Ссылка);
    
    Если ЗначениеЗаполнено(Дубликат) Тогда
        ТекстСообщения = СтрШаблон("Данный номер телефона уже закреплен за клиентом: %1", Дубликат);
        ПоказатьПредупреждение(, ТекстСообщения);
        // Если бизнес-логика требует запретить ввод дублей, можно раскомментировать строку ниже:
        // Отказ = Истина; 
    КонецЕсли;
    
КонецПроцедуры

Важные нюансы и рекомендации

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

  1. Нормализация данных. Как справедливо замечено в профессиональных обсуждениях, пользователи могут вводить номера в разном формате: +7 (999) 111-22-33, 89991112233 или 79991112233. Обычный запрос не сопоставит эти строки. Перед поиском и перед сохранением рекомендуется очищать номер от всех символов, кроме цифр. Для этого можно использовать функцию СтрЗаменить() или регулярные выражения.
  2. Индексирование. Если в справочнике Клиенты тысячи или десятки тысяч записей, поиск по неиндексированной табличной части будет работать медленно. Убедитесь, что в конфигураторе для реквизита НомерТелефонаКлиента установлено свойство Индексировать.
  3. Использование БСП. В современных типовых конфигурациях (например, УТ 11 или БП 3.0) для работы с телефонами используется подсистема Контактная информация. В настройках вида контактной информации (например, "Телефон партнера") есть штатная галочка "Запрещать ввод дублей". Если ваша конфигурация построена на БСП, рекомендуется использовать этот стандартный механизм вместо написания собственного кода.
  4. Целостность данных. Проверка в форме защищает только от ручного ввода. Если данные загружаются через обработку или обмен, проверка в форме не сработает. Для гарантированной защиты от дублей логику поиска следует продублировать в модуле объекта в обработчике ПередЗаписью.

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

← На главную