Загрузка контрагентов по ИНН в древнюю отраслевую базу

Клиент поставил задачу — заполнять контрагентов по ИНН. У клиентов есть только юридические лица, что упрощает задачу.

В форме дописал код, чтобы показывалась кнопка заполнения по ИНН:

&НаСервере
Процедура дор_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	ИмяКоманды = "дор_ЗаполнитьПоИНН";
	КомандаФормы = ЭтаФорма.Команды.Добавить(ИмяКоманды);
	КомандаФормы.Действие = "дор_ЗаполнитьПоИНН";
	КомандаФормы.Заголовок = "Заполнить";
	КомандаФормы.ИзменяетСохраняемыеДанные = истина;
	КомандаФормы.Отображение = ОтображениеКнопки.Текст;
	
	ПередЭлемент = Элементы.КПП;
	НовыйЭлемент = ЭтаФорма.Элементы.Вставить("Заполнить", Тип("КнопкаФормы"), ПередЭлемент.Родитель, ПередЭлемент);
	НовыйЭлемент.Вид = ВидКнопкиФормы.ОбычнаяКнопка;
	НовыйЭлемент.ИмяКоманды = ИмяКоманды;
	
КонецПроцедуры


&НаКлиенте
Процедура дор_ЗаполнитьПоИНН(Команда)
	ПоказатьПредупреждение(, "Не реализовано!");
КонецПроцедуры

Добавляю в базу две строковые константы для доступа к ИТС:

За основу взял обработку с ИТС для БП 2.0. Но потом почитал, что с 1 января 2017 года поддержка старого сервиса отменяется.

Поэтому код у меня, разумеется, не заработал:

Ошибка получения файла описания web-сервиса:soap:Server      

Возникла мысль заполнить контрагентов через DaData. Но я отмёл ее, все-таки у клиента есть ИТС-Проф, зачем ему еще раз покупать другой сервис — бесплатный там ограничен по некоторым полям.

Ладно, возьмем заполнение по ИНН из актуальной БП3. Сначала я хотел копировать только нужные функции, добавляя то, чего не хватает:

Но этот способ оказался слишком долгим, поэтому я его бросили и скопировал модуль РаботаСКонтрагентами целиком.

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

Добавил в них только нужные функции, благо в некоторых модулях используется только одна функция.

Модуль ИнтернетПоддержкаПользователей тоже взял целиком, убрал некоторые ненужные функции.

Пришлось также дописать несколько функций в имеющиеся модули ОбщегоНазначения, ОбщегоНазначенияКлиентСервер, ПолучениеФайловИзИнтернета.

Далее я поставил вот такую остановку и ловил ошибки отсутствия метода и добавлял нужные методы:

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

Через несколько протяжек код заработал, например, по фирме 1С (ИНН 7709860400) выдал такие данные:

Статус (структура):

Регистрирующий орган (структура):

Руководители:

Регистрация в налоговом органе (структура):

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

Работы до этого этапа съели 3 часа.

После этого я создал контрагента 1С с ИНН и начал тестировать его заполнение. Посмотрел, как происходит заполнение в типовой БП3:

Я упростил структуру кода, все совершая на сервере, на клиент выдавая только результат заполнения:

&НаКлиенте
Процедура дор_ЗаполнитьПоИНН(Команда)
	
	ТекИНН = Объект.ИНН;
	Если НЕ ЗначениеЗаполнено(ТекИНН) Тогда
		ПоказатьПредупреждение(ТекИНН, НСтр("ru='Поле ""ИНН"" не заполнено'"));
		ЭтаФорма.ТекущийЭлемент = Элементы.ИНН; //Позиционируем на ИНН
		Возврат;
	КонецЕсли;
	
	Результат = ВыполнитьЗаполнениеРеквизитовПоИНН(ТекИНН);
	Если СокрЛП(Результат.ОписаниеОшибки) <> "" Тогда
		ПоказатьПредупреждение(, Результат.ОписаниеОшибки,,"Ошибка получения данных по ИНН!");
		Возврат;
	Иначе
		ПоказатьПредупреждение(, "Данные по ИНН успешно заполнены!");
		Возврат;
	КонецЕсли;
	
	
КонецПроцедуры

Функция ВыполнитьЗаполнениеРеквизитовПоИНН(ИННОбъекта)
	Результат = Новый Структура("ОписаниеОшибки", "");
	
	РеквизитыКонтрагента = ПолучитьРеквизитыКонтрагентаПоИНН(ИННОбъекта); //Это вызов сервиса 1с:Контрагенты
	Результат.ОписаниеОшибки = РеквизитыКонтрагента.ОписаниеОшибки;
	
	Если СокрЛП(РеквизитыКонтрагента.ОписаниеОшибки) <> "" Тогда
		Возврат Результат;
	КонецЕсли;
	
	ЗаполнитьКонтрагентаПоРеквизитам(РеквизитыКонтрагента); //Это код по заполнению
	
	Возврат Результат;

КонецФункции

Заполнение основных полей вылилось в одну строку кода:

ЗаполнитьЗначенияСвойств(Объект, РеквизитыКонтрагента);

Заполненный контрагент выглядел так:

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

Если РеквизитыКонтрагента.Руководитель <> Неопределено Тогда 
	
	Если ЗаписатьОбъектЕслиНужно("Генеральный директор не будет установлен") Тогда
		ДанныеКонтактногоЛица = РеквизитыКонтрагента.Руководитель;
		Объект.ГенеральныйДиректор = ДатьКонтактноеЛицо(Объект.Ссылка, ДанныеКонтактногоЛица);
	КонецЕсли;
	
КонецЕсли;

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

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

Реквизиты контактной информации не создавались, пока не был переход на закладку «Адреса», поэтому при нажатии кнопки «Заполнить» создаю эти поля:

Если НЕ ПараметрыКонтактнойИнформации.ГруппаКонтактнаяИнформация.ВыполненаОтложеннаяИнициализация Тогда
	КонтактнаяИнформацияПриСменеСтраницы();
КонецЕсли;

С самой контактной информацией тоже пришлось повозиться.

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

Я сделал несколько неверных движений:

Забил в адрес в свободной форме свое тестовое значение и посмотрел, как это хранится в 1с:

В итоге у меня получилось:

Код по заполнению контактной информации:

//Заполнение адресов
ЗаполнитьЭлементКонтактнойИнформации(Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента, РеквизитыКонтрагента.ЮридическийАдрес, "Адрес");
ЗаполнитьЭлементКонтактнойИнформации(Справочники.ВидыКонтактнойИнформации.ФактАдресКонтрагента, РеквизитыКонтрагента.ЮридическийАдрес, "Адрес");
ЗаполнитьЭлементКонтактнойИнформации(Справочники.ВидыКонтактнойИнформации.ПочтовыйАдресКонтрагента, РеквизитыКонтрагента.ЮридическийАдрес, "Адрес");
	
// Заполнение телефона
ЗаполнитьЭлементКонтактнойИнформации(Справочники.ВидыКонтактнойИнформации.ТелефонКонтрагента, РеквизитыКонтрагента.Телефон, "Телефон");

Процедура ЗаполнитьЭлементКонтактнойИнформации(ВидКонтактнойИнформации, СтруктураДанных, ТипКИ)
	
	Если СтруктураДанных = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Отбор  = Новый Структура("Вид", ВидКонтактнойИнформации);
	Строки = ЭтотОбъект.КонтактнаяИнформацияОписаниеДополнительныхРеквизитов.НайтиСтроки(Отбор);
	ДанныеСтроки = ?(Строки.Количество() = 0, Неопределено, Строки[0]);
	Если ДанныеСтроки = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ИмяРеквизита = ДанныеСтроки.ИмяРеквизита;
	
	ЗаполнитьЗначенияСвойств(ДанныеСтроки, СтруктураДанных);
	
	Если  ТипКИ = "Адрес" Тогда
		ДанныеСтроки.ЗначенияПолей = АдресВСвободнойФорме(СтруктураДанных.Представление);//СтруктураДанных.КонтактнаяИнформация;
	Иначе
		ДанныеСтроки.ЗначенияПолей = СтруктураДанных.Представление;//СтруктураДанных.КонтактнаяИнформация;
	КонецЕсли;
	
	ЭтаФорма[ИмяРеквизита] = СтруктураДанных.Представление;
	
КонецПроцедуры

Функция АдресВСвободнойФорме(Представление)
	
	мУправлениеКонтактнойИнформациейСлужебный = Вычислить("УправлениеКонтактнойИнформациейСлужебный");
	мУправлениеКонтактнойИнформациейКлиентСервер = Вычислить("УправлениеКонтактнойИнформациейКлиентСервер");
	
	ПространствоИмен = мУправлениеКонтактнойИнформациейКлиентСервер.ПространствоИмен();
	
	XDTOИнформация = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен, "КонтактнаяИнформация"));
	XDTOИнформация.Представление = Представление;
	
	Адрес = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен, "Адрес"));
	Адрес.Страна = "РОССИЯ"; //Справочники.СтраныМира.Россия;
	XDTOИнформация.Состав = Адрес;
	
	АдресРФ = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен, "АдресРФ"));
	АдресРФ.Адрес_по_документу = Представление;
	//мУправлениеКонтактнойИнформациейСлужебный.ДобавитьДополнительныеЭлементыАдреса(АдресРФ, "10100000", 90);
	Адрес.Состав = АдресРФ;
	
	XML = мУправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(XDTOИнформация);
	Возврат XML;
	
КонецФункции


Заполнение полей контрагента заняло еще 2 час.

Объем: 5 час.

fixin

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

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *