Алгоритм проверки уникальности и корректности ИНН, КПП при записи контрагента для БП 1.6 и 2.0 через подписку на события

13.03.12

Разработка - Математика и алгоритмы

В УПП есть типовой механизм проверки контрагента на уникальность при записи.
В БП 2.0 такой типовой проверки нет, пришлось добавлять свою, к тому же логика УПП-шной проверки меня не совсем устраивает.

Предлагаю свой вариант алгоритма проверки ИНН и КПП при записи элемента справочника Контрагенты.

Ни на что не претендую, если инфа будет кому-то полезна, значит не зря потратил время :).
К тому же этот вопрос возникает с неизменной периодичностью на всех форумах.

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

Приведенный ниже код проверяет корректность в ИНН и КПП на:
    - длина
    - недопустимые символы
    - уникальность ИНН+КПП (для юрлица) или уникальность ИНН (для физлица)
    - проверка корректности ИНН на контрольный разряд

P.S. это первая публикация, сильно не ругайте, если есть замечания - сообщите

обновлено 13.03.2012 : добавлена проверка на Отказ, ОбменДанными.Загрузка,  ЭтоГруппа (спасибо http://forum.infostart.ru/forum24/topic51955/message616590/#message616590)

В конфигурации БП реализовал следующим образом:

1) создал подписку на событие

Источник: СправочникОбъект.Контрагенты

Событие: ПередЗаписью

Обработчик: МойОбщийМодуль.ПередЗаписьюКонтрагента (где МойОбщийМодуль - собственный общий модуль, но можно при желании можно и в один из типовых засунуть)

2) собственно сам обработчик

//добавлено - 11/05/2010 (проверка на корректность и уникальность ИНН и КПП)
Процедура ПередЗаписьюКонтрагента(Источник, Отказ) Экспорт

    Если Отказ ИЛИ Источник.ОбменДанными.Загрузка ИЛИ Источник.ЭтоГруппа Тогда
        Возврат;
    КонецЕсли;

    Если
Источник.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ФизЛицо Тогда
       
ЭтоФизлицо = Истина;
    Иначе
       
ЭтоФизлицо = Ложь;
    КонецЕсли;

   
// проверка ИНН на заполнение
   
ИНН = Источник.ИНН;
    Если
СтрДлина(ИНН) <> ?(ЭтоФизлицо, 12, 10) Тогда
       
СообщениеОНевозможностиЗаписи = "Неверное количество символов в реквизите ИНН!!!" + Символы.ПС
            + "Текущее количество символов: " + СтрДлина(ИНН) + Символы.ПС
            + "Требуемое количество символов для " + ?(ЭтоФизлицо, "Физлица: 12","Юрлица: 10");
       
ОбщегоНазначения.СообщитьОбОшибке(СообщениеОНевозможностиЗаписи);
       
Отказ = Истина;
        Возврат;
    КонецЕсли;

   
// проверка ИНН на недопустимые символы
   
Результат = Истина;
    Для
а = 1 По СтрДлина(ИНН) Цикл
        Если
Найти("0123456789", Сред(ИНН,а,1)) = 0 Тогда
           
НекорректныйСимвол = Сред(ИНН,а,1);
           
Результат = Ложь;
            Прервать;
        КонецЕсли;
    КонецЦикла;

    Если НЕ
Результат Тогда
        СообщениеОНевозможностиЗаписи = "Недопустимый символ в реквизите ИНН: <" + НекорректныйСимвол + "> !!!";
       
ОбщегоНазначения.СообщитьОбОшибке(СообщениеОНевозможностиЗаписи);
       
Отказ = Истина;
        Возврат;
    КонецЕсли;

   
// проверка ИНН на контрольный разряд

    Если НЕ РегламентированнаяОтчетность.ИННСоответствуетТребованиям(ИНН, ЮрФизЛицо) Тогда
        СообщениеОНевозможностиЗаписи = "ИНН задан неверно (не прошел проверку на контрольный разряд)!!!";
        ОбщегоНазначения.СообщитьОбОшибке(СообщениеОНевозможностиЗаписи);
       
Отказ = Истина;
        Возврат;
    КонецЕсли;

    Если НЕ
ЭтоФизлицо Тогда
   
// проверка КПП на заполнение
       
КПП = Источник.КПП;
        Если
СтрДлина(КПП) <> 9 Тогда
           
СообщениеОНевозможностиЗаписи = "Неверное количество символов в реквизите КПП!!!" + Символы.ПС
            + "Текущее количество символов: " + СтрДлина(КПП) + Символы.ПС
            + "Требуемое количество символов: 9";
           
ОбщегоНазначения.СообщитьОбОшибке(СообщениеОНевозможностиЗаписи);
           
Отказ = Истина;
            Возврат;
        КонецЕсли;

       
// проверка КПП на недопустимые символы
       
Результат = Истина;
        Для
а = 1 По СтрДлина(КПП) Цикл
            Если
Найти("0123456789", Сред(КПП,а,1)) = 0 Тогда
               
НекорректныйСимвол = Сред(КПП,а,1);
               
Результат = Ложь;
                Прервать;
            КонецЕсли;
        КонецЦикла;

        Если НЕ
Результат Тогда
            СообщениеОНевозможностиЗаписи = "Недопустимый символ в реквизите КПП: <" + НекорректныйСимвол + "> !!!";
           
ОбщегоНазначения.СообщитьОбОшибке(СообщениеОНевозможностиЗаписи);
           
Отказ = Истина;
            Возврат;
        КонецЕсли;
    КонецЕсли;

   
// поиск дубликатов в справочнике
   
Запрос = Новый Запрос();
   
Запрос.УстановитьПараметр("ТекущийИНН", ИНН);
   
Запрос.УстановитьПараметр("ТекущийКПП", КПП);
   
Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);

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

   
ВыборкаКонтрагентов = Запрос.Выполнить().Выбрать();

    Если
ВыборкаКонтрагентов.Количество() <> 0 Тогда
       
ВыборкаКонтрагентов.Следующий();
       
СообщениеОНевозможностиЗаписи = "Уже существует контрагент с таким ИНН" + ?(ЭтоФизлицо, "", " И КПП") + " (" + ВыборкаКонтрагентов.Ссылка.Код + " " + ВыборкаКонтрагентов.ПредставлениеКонтрагента + ") !!!" ;
       
ОбщегоНазначения.СообщитьОбОшибке(СообщениеОНевозможностиЗаписи);
       
Отказ = Истина;
        Возврат;
    КонецЕсли;

КонецПроцедуры
//финиш - 11/05/2010 (проверка на корректность и уникальность ИНН и КПП)

См. также

Математика и алгоритмы Программист Платформа 1C v8.2 Конфигурации 1cv8 Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    3733    stopa85    12    

38

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    8339    user1959478    52    

36

Математика и алгоритмы Разное Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

Расширение (+ обработка) представляют собою математический тренажер. Ваш ребенок сможет проверить свои знание на математические вычисление до 100.

2 стартмани

29.09.2023    3659    maksa2005    8    

26

Математика и алгоритмы Инструментарий разработчика Программист Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

Что ж... лучше поздно, чем никогда. Подсистема 1С для работы с регулярными выражениями: разбор выражения, проверка на соответствие шаблону, поиск вхождений в тексте.

1 стартмани

09.06.2023    11425    8    SpaceOfMyHead    19    

61

Математика и алгоритмы Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Три задачи - три идеи - три решения. Мало кода, много смысла. Мини-статья.

03.04.2023    4899    RustIG    9    

25

Механизмы платформы 1С Математика и алгоритмы Программист Платформа 1С v8.3 Россия Бесплатно (free)

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

23.11.2022    4055    gzharkoj    14    

25

Математика и алгоритмы Программист Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    9144    7    kalyaka    11    

44
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. ms200999 30.01.12 13:44 Сейчас в теме
Напрашивается проверка по контрольному числу. :)
2. DSerg74 41 30.01.12 15:48 Сейчас в теме
(1) не спорю, можно добавить и такой контроль, например из http://infostart.ru/public/70687/
мне такая проверка не нужна, т.к. часто при создании контрагента-физлица отсутствует информация об ИНН, тогда пользователи используют в качестве ИНН СерияНомерПаспорта+"00"
3. DSerg74 41 30.01.12 21:58 Сейчас в теме
(1) в типовой конфе БП оказывается уже есть функция проверки на контрольное число, добавил сюда эту проверку, спасибо за полезное замечание
4. DDos76 206 11.02.12 09:17 Сейчас в теме
Спасибо за готовый код! Иногда просто бывает некогда писать и думать - а тут скопировал вставил и работает!
5. artbear 1565 11.03.12 17:22 Сейчас в теме
Сабж пока слабо готов к реальной эксплуатации
1. Нет проверки на ОбменДанными.Загрузка
2. ИМХО в подобных обработчиках лучше сразу проверять Отказ. Если Истина, то ничего не делать, так будет производительнее для системы.
6. DSerg74 41 13.03.12 08:37 Сейчас в теме
(5) artbear - прав, спасибо за замечания, одна голова хорошо, а две лучше :)
в принципе этот алгоритм используется на практике уже 2 года, но для универсальности добавлю твои предложения
7. JLaikova 09.09.13 10:35 Сейчас в теме
Спасибо!!!! Пригодилось
8. kalaratra 13 14.08.14 09:07 Сейчас в теме
Спасибо огромное! Только сегодня пришла такая же задача) Не пришлось самой разбираться)))
9. bashirov.rs 31 04.12.14 14:02 Сейчас в теме
Проверка на значения типа "0000000000" или "1111111111" и т.д. будет? Возможно проверить по регионам ИНН (начинается ли ИНН с кода региона - 01, 02, ... 99) ?
10. improg 712 17.01.15 20:44 Сейчас в теме
Автору спасибо, благодаря статье сделал все быстро.
11. Nordkas 11 29.01.15 21:53 Сейчас в теме
Спасибо, я не много доработал и получилось очень достойно.
12. b-dm 174 19.02.15 18:14 Сейчас в теме
Молодец! Проверка при записи правильное дело.
13. wertyoz453 30.09.15 10:42 Сейчас в теме
Хороший вариант реализации, но для работы в нетиповых потребуется и сама функция:

// Проверяет соответствие ИНН требованиям
// Параметры:
//		ИНН - строка - проверяемый индивидуальный номер налогоплательщика,
//		ВладелецИНН - ПеречислениеСсылка.ЮрФизЛицо - тип владельца ИНН: физлицо или юрлицо
Функция ИННСоответствуетТребованиям(Знач ИНН, Знач ТипЛица) Экспорт

	ИНН = СокрЛП(ИНН);
	ДлинаИНН =  СтрДлина(ИНН);

	Если НЕ ОбщегоНазначения.ТолькоЦифрыВСтроке(ИНН) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если Метаданные.Перечисления.Найти("ЮрФизЛицо") = Неопределено Тогда
		ПроверяетсяИННФизЛица = ТипЛица;
	Иначе
		ПроверяетсяИННФизЛица = (ТипЛица = Истина ИЛИ ТипЛица = Перечисления.ЮрФизЛицо.ФизЛицо);
	КонецЕсли;
	
	Если ДлинаИНН = 10  И НЕ ПроверяетсяИННФизЛица Тогда

		КонтрольнаяСумма = 0;

		Для Н = 1 По 9 Цикл

			Если 	  Н = 1 Тогда
				Множитель = 2;
			ИначеЕсли Н = 2 Тогда
				Множитель = 4;
			ИначеЕсли Н = 3 Тогда
				Множитель = 10;
			ИначеЕсли Н = 4 Тогда
				Множитель = 3;
			ИначеЕсли Н = 5 Тогда
				Множитель = 5;
			ИначеЕсли Н = 6 Тогда
				Множитель = 9;
			ИначеЕсли Н = 7 Тогда
				Множитель = 4;
			ИначеЕсли Н = 8 Тогда
				Множитель = 6;
			ИначеЕсли Н = 9 Тогда
				Множитель = 8;
			КонецЕсли; 
			
			Цифра = Число(Сред(ИНН,Н,1));
			КонтрольнаяСумма = КонтрольнаяСумма + Цифра * Множитель;
			
		КонецЦикла; 
		
		КонтрольныйРазряд = (КонтрольнаяСумма %11) %10;
		
		Если КонтрольныйРазряд <> Число(Сред(ИНН,10,1)) Тогда
			Возврат Ложь;
		КонецЕсли; 
		
	ИначеЕсли ДлинаИНН =12 И ПроверяетсяИННФизЛица Тогда
		
		КонтрольнаяСумма11 = 0;
		КонтрольнаяСумма12 = 0;
		
		Для Н=1 По 11 Цикл
			
			// Расчет множителя для 11-го и 12-го разрядов
			Если Н = 1 Тогда
				Множитель11 = 7;
				Множитель12 = 3;
			ИначеЕсли Н = 2 Тогда
				Множитель11 = 2;
				Множитель12 = 7;
			ИначеЕсли Н = 3 Тогда
				Множитель11 = 4;
				Множитель12 = 2;
			ИначеЕсли Н = 4 Тогда
				Множитель11 = 10;
				Множитель12 = 4;
			ИначеЕсли Н = 5 Тогда
				Множитель11 = 3;
				Множитель12 = 10;
			ИначеЕсли Н = 6 Тогда
				Множитель11 = 5;
				Множитель12 = 3;
			ИначеЕсли Н = 7 Тогда
				Множитель11 = 9;
				Множитель12 = 5;
			ИначеЕсли Н = 8 Тогда
				Множитель11 = 4;
				Множитель12 = 9;
			ИначеЕсли Н = 9 Тогда
				Множитель11 = 6;
				Множитель12 = 4;
			ИначеЕсли Н = 10 Тогда
				Множитель11 = 8;
				Множитель12 = 6;
			ИначеЕсли Н = 11 Тогда
				Множитель11 = 0;
				Множитель12 = 8;
			КонецЕсли; 
			
			Цифра = Число(Сред(ИНН,Н,1));
			КонтрольнаяСумма11 = КонтрольнаяСумма11 + Цифра * Множитель11;
			КонтрольнаяСумма12 = КонтрольнаяСумма12 + Цифра * Множитель12;
			
		КонецЦикла; 
		
		КонтрольныйРазряд11 = (КонтрольнаяСумма11 %11) %10;
		КонтрольныйРазряд12 = (КонтрольнаяСумма12 %11) %10;
		
		Если КонтрольныйРазряд11 <> Число(Сред(ИНН,11,1))
			ИЛИ КонтрольныйРазряд12 <> Число(Сред(ИНН,12,1)) Тогда
			Возврат Ложь;
		КонецЕсли; 
		
	Иначе
		
		Возврат Ложь;
		
	КонецЕсли; 
	
	Возврат Истина;
	
КонецФункции
Показать





14. maksa2005 551 14.10.15 21:37 Сейчас в теме
Чтобы не вводили вместо чисел буквы и цифры в ИНН и КПП для счастья луше добавить маску в ИНН - 999999999999 и КПП 999999999
serg1974; +1 Ответить
15. maksa2005 551 14.10.15 21:38 Сейчас в теме
Не добавил проверку по ИП у которых стоит КПП.
Оставьте свое сообщение