Перенос популярного и удобного функционала автозаполнения реквизитов контрагента по ИНН из современных конфигураций (например, Бухгалтерия предприятия 3.0) в более старые решения (такие как Бухгалтерия предприятия 2.0, Управление торговлей 10.3 или Комплексная автоматизация 1.1) — частая задача для разработчиков 1С. Однако в процессе адаптации кода программисты регулярно сталкиваются с ошибкой выполнения, когда метод ФабрикаXDTO.Тип() возвращает Неопределено при попытке инициализировать структуры контактной информации.
В этой статье мы подробно разберем, почему возникает данная проблема, рассмотрим технические особенности работы с фабрикой XDTO в платформе «1С:Предприятие», пошагово выполним процесс переноса необходимых объектов конфигурации и изучим альтернативные, более простые архитектурные варианты решения этой задачи.
Метод ФабрикаXDTO.Тип() предназначен для получения типа данных XDTO по его пространству имен (URI) и локальному имени. Если этот метод возвращает Неопределено, это означает, что платформа не смогла сопоставить переданные параметры ни с одним из известных ей типов. Рассмотрим основные технические нюансы, которые приводят к такому поведению:
СервисДанныхЕдиныхГосРеестров, но забыли скопировать сам XDTO-пакет, в котором описаны типы адресов, глобальная фабрика конфигурации просто не будет знать о существовании таких типов, как АдресРФ.ФабрикаXDTO.Тип() работает исключительно с типами данных. Если разработчики сервиса объявили целевой объект как свойство, этот метод вернет пустой результат. В таком случае тип необходимо извлекать из самого свойства через пакет:
ТипИзСвойства = ФабрикаXDTO.Пакеты.Получить(ПространствоИменКИ).Свойства.Получить("АдресРФ").Тип;
ПространствоИменКИ должно посимвольно совпадать с аналогичным свойством пакета в конфигураторе.WSПрокси, его типы регистрируются во внутренней фабрике этого прокси-объекта, а не в глобальном объекте ФабрикаXDTO всей конфигурации. В таком случае обращаться к типам необходимо через прокси:
ТипАдреса = МойПараметрПрокси.ФабрикаXDTO.Тип(ПространствоИменКИ, "АдресРФ");
rphost может обновиться некорректно. На одном сервере вызов отработает штатно, а на другом — вернет ошибку. Для решения этой проблемы требуется полная очистка серверного кэша и перезапуск службы кластера.Для того чтобы перенести функционал заполнения реквизитов из БП 3.0 в старую базу, нам потребуется аккуратно перенести ключевые объекты метаданных и связать их между собой. Проанализируем этот процесс по шагам:
Откроем конфигуратор базы-источника (БП 3.0) и базы-приемника (например, БП 2.0). Найдем в ветке Общие -> XDTO-пакеты пакет с именем КонтактнаяИнформация. Перетащим его методом Drag-and-Drop или скопируем через буфер обмена в нашу целевую конфигурацию. Убедимся, что его URI пространства имен точно соответствует используемому в коде (как правило, это http://www.v8.1c.ru/ssl/contactinfo).
Нам потребуется скопировать модуль СервисДанныхЕдиныхГосРеестров. Обратите внимание, что этот модуль активно взаимодействует с подсистемой контактной информации БСП. Чтобы не переносить десятки связанных модулей БСП, мы можем точечно перенести или дописать несколько функций в модуль УправлениеКонтактнойИнформацией целевой конфигурации:
Функция ТипыОбъектовАдресацииАдресаРФ() — возвращает список типов адресных объектов.Функция СтрокаОбъектаАдресации(...) — формирует строку на основе переданных составляющих адреса.Функция СокращенияАдресныхОбъектов(...) — сопоставляет сокращения адресных классификаторов.Для получения данных от веб-сервиса 1С требуется авторизация под учетной записью Портала ИТС (у вас должна быть активна подписка на сервис «1С:Контрагент»). Данные авторизации (логин и пароль) обычно хранятся в константах или регистрах сведений (например, в регистре настроек интернет-поддержки). Нам необходимо убедиться, что эти данные корректно считываются в коде модуля СервисДанныхЕдиныхГосРеестров.
Важный совет по безопасности кода: при возникновении ошибок подключения (например, падение авторизации) платформа может вывести подробное описание исключения в Журнал регистрации, содержащее логин и пароль к ИТС в открытом виде! Рассмотрим, как можно обезопасить эти конфиденциальные данные с помощью простой функции маскирования в блоке перехвата исключений:
Попытка
WSОпределения = Новый WSОпределения(АдресWSDL, ИмяПользователя, Пароль);
Исключение
ОписаниеОшибки = ИнформацияОбОшибке().Описание;
// Маскируем учетные данные, чтобы они не попали в журнал регистрации в открытом виде
ОписаниеОшибки = СтрЗаменить(ОписаниеОшибки, ПараметрыАутентификации.login, "указан_логин");
ОписаниеОшибки = СтрЗаменить(ОписаниеОшибки, ПараметрыАутентификации.password, "указан_пароль");
ЗаписатьВЖурналРегистрации("ИнтеграцияСЕГРЮЛ",
УровеньЖурналаРегистрации.Ошибка,
, ,
"Ошибка инициализации веб-сервиса: " + ОписаниеОшибки);
ВызватьИсключение "Не удалось подключиться к сервису авторизации. Проверьте настройки ИТС.";
КонецПопытки;
Перенос подсистем БСП «в лоб» часто превращается в кошмар из-за лавинообразного роста зависимостей: один переносимый модуль требует функции второго, второй — третьего, и в итоге вам приходится менять структуру метаданных всей конфигурации. Посмотрим на альтернативные варианты реализации этой задачи, которые помогут сэкономить время.
Если вам не принципиально использовать именно встроенный сервис «1С:Контрагент», отличным решением будет интеграция со сторонними сервисами стандартизации данных, такими как DaData.ru. Этот подход имеет ряд весомых преимуществ:
ЧтениеJSON, позволяющий свернуть ответ сервера в обычную структуру 1С за одну строку кода.Рассмотрим очень красивое и простое решение, если на предприятии параллельно с вашей старой базой развернута и обновляется актуальная база Бухгалтерия предприятия 3.0. Вместо того чтобы дублировать сложный код парсинга XML и XDTO, мы можем использовать COM-соединение:
Проанализируем пример программной реализации такого COM-запроса:
&НаКлиенте
Процедура ЗаполнитьПоИННЧерезCOM(Команда)
ИНН = Объект.ИНН;
Если ПустаяСтрока(ИНН) Тогда
ПоказатьПредупреждение(, "Пожалуйста, заполните ИНН контрагента!");
Возврат;
КонецЕсли;
// Формируем строку подключения к базе БП 3.0
СтрокаПодключения = "Srvr=""MyServer"";Ref=""Accounting_Production"";Usr=""COM_Exchange"";Pwd=""SuperPassword"";";
Попытка
COMСоединитель = Новый COMОбъект("V83.COMConnector");
БазаБП3 = COMСоединитель.Connect(СтрокаПодключения);
Исключение
ВызватьИсключение "Не удалось установить связь с базой БП 3.0 для получения данных: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
// Вызываем функцию автозаполнения на стороне БП 3.0
// Предполагается, что в БП 3.0 есть функция, возвращающая простую структуру данных
ДанныеКонтрагента = БазаБП3.ОбщиеМодули.СервисДанныхЕдиныхГосРеестров.ПолучитьПлоскиеДанныеКонтрагента(ИНН);
Если ДанныеКонтрагента = Неопределено Тогда
ПоказатьПредупреждение(, "Контрагент с таким ИНН не найден в ЕГРЮЛ!");
Возврат;
КонецЕсли;
// Заполняем реквизиты на форме нашей старой конфигурации
Объект.НаименованиеПолное = ДанныеКонтрагента.НаименованиеПолное;
Объект.КПП = ДанныеКонтрагента.КПП;
Объект.ЮридическийАдрес = ДанныеКонтрагента.ЮридическийАдресТекст;
ПоказатьОповещениеПользователя("Успешно", , "Реквизиты заполнены из базы БП 3.0");
КонецПроцедуры
Преимущество этого метода очевидно: при любых изменениях в структуре веб-сервисов со стороны фирмы «1С» вам не придется переписывать код в вашей старой доработанной базе. Достаточно будет просто своевременно обновлять базу-донор БП 3.0 до актуальных релизов.
Мы выяснили, что ошибка получения типа XDTO чаще всего связана с отсутствием соответствующего пакета в конфигурации или неточным сопоставлением пространств имен. Мы рассмотрели варианты исправления этой ситуации как путем прямого переноса пакетов и доработки общих модулей, так и через создание обходных архитектурных решений, которые могут оказаться значительно более дешевыми в поддержке и внедрении.