Как реализовать проверку дублей контрагентов в 1С и корректно обрабатывать пустые значения ИНН и КПП?

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

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

Анализ проблемы: почему стандартной проверки по ИНН недостаточно?

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

Рассмотрим правильный подход: дублем считается сочетание ИНН + КПП. Если оба поля заполнены, они должны быть уникальны. Если же они пустые (например, для физлиц), проверка должна работать по иным критериям или пропускать запись.

Шаг 1. Создание функции проверки наличия контрагента в базе

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


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

Обратите внимание на параметр ТекущаяСсылка. Проанализируем ситуацию: если мы редактируем уже существующего контрагента и нажимаем «Записать», запрос без этого условия найдет текущую карточку и система выдаст ошибку «Дубль найден». Исключение текущей ссылки из поиска — обязательное условие корректной работы.

Шаг 2. Обработка пустых значений перед вызовом запроса

Теперь выясним причину, по которой запрос может работать некорректно при пустых значениях. Если мы передадим в запрос пустые строки, он найдет первого попавшегося контрагента с пустым ИНН (например, любого розничного покупателя) и заблокирует запись. Чтобы этого избежать, добавим проверку в процедуру ПередЗаписью или ОбработкаПроверкиЗаполнения.

Рассмотрим пример реализации логики в модуле объекта:


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

Шаг 3. Использование необязательных параметров в запросе

Иногда требуется более сложная логика: например, если КПП заполнен — проверять по паре, если не заполнен — только по ИНН. Мы можем реализовать это прямо внутри языка запросов, используя логические условия. Посмотрим на пример такого условия в секции ГДЕ:


ГДЕ 
    Контрагенты.ИНН = &ИНН
    И (&ПроверятьКПП = ЛОЖЬ ИЛИ Контрагенты.КПП = &КПП)
    И Контрагенты.Ссылка <> &ТекущаяСсылка

В данном случае в параметр &ПроверятьКПП мы передаем результат функции ЗначениеЗаполнено(Объект.КПП). Это позволяет сделать запрос гибким и избежать написания нескольких разных текстов запросов для разных ситуаций.

Шаг 4. Учет дополнительных факторов (Наименование и Тип контрагента)

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

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

  1. Используйте функцию СокрЛП() для удаления лишних пробелов в начале и конце строк.
  2. Приводите строки к единому формату (удаляйте лишние спецсимволы, если это необходимо для вашей специфики).
  3. Проверяйте свойство ОбменДанными.Загрузка. Если в базу загружаются данные из внешних систем (например, из клиент-банка), жесткие блокировки могут остановить весь процесс загрузки. В таких случаях лучше записывать данные «как есть», а затем использовать типовую обработку «Поиск и удаление дублей».

Шаг 5. Оптимизация производительности (Индексирование)

Выясним, как наш код будет вести себя в базе с 100 000 контрагентов. Если поля ИНН и КПП не индексированы, каждый вызов функции будет приводить к полному сканированию таблицы (Full Scan), что создаст значительную нагрузку на SQL-сервер.

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

Резюме

Мы проанализировали процесс создания надежной системы контроля дублей. Подведем итоги:

Используя эти методы, вы создадите стабильный механизм контроля чистоты данных, который не будет мешать пользователям вводить уникальные записи (даже с пустыми реквизитами там, где это допустимо) и при этом надежно защитит базу от ошибок ввода.

← На главную