Организации, ИНН и DaData в быту...

15 7

Для чего это вообще может быть нужно? Ну, как один из знаменитых сервисов, неоднократно отмеченный Хабром, он в принципе привлекателен тем, что у него в сутки дается 10 000 запросов, плюс на нем вполне актуальная информация. Адреса, Организации, координаты, почтовые отделения и иные мелочи. Да - не секретная информация, но для простого заполнения Организации по ИНН - вполне себе отличная. 

Итак, приступим!

1. Первое, что нам надо сделать - зарегистрироваться на сайте https://dadata.ru так как только так вы получите свой уникальный KEY для запросов. Это не сложно.

2. Далее - выбираем сервис который нам интересен:

3. На моем примере выбран раздел "Организация по ИНН или ОГРН" - запросы по API. Там же есть все необходимое для создания запроса и получения информации:

4. Теперь осталось это обличить в IS-Builder и проверить! Приступим по готовому:

HTTP   = CreateObject("MSXML2.XMLHTTP.6.0")
HTTP.Open("POST"                        ; "https://suggestions.dadata.ru/suggestions/api/4_1/rs/findById/party"; false)
HTTP.setRequestHeader("Content-Type"    ; "application/json")
HTTP.setRequestHeader("Accept"          ; "application/json")
HTTP.setRequestHeader("Authorization"   ; "Token ХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХ")
HTTP.Send('{ "query": "' & INN & '" }')

Итак - у нас появился запрос (с указанной переменной "INN") и вероятно какой-то ответ, который легко проверяется через "if HTTP.status". Теперь нам надо размотать полученный JSON и взять все что нам из него нужно:

if HTTP.status
  JSON = http.responseText  
  scriptControl = CreateObject("ScriptControl")
  scriptControl.Language = "JScript"
  
  NameOrg   = scriptControl.Eval('(' & JSON & ').suggestions[0].value')                         // Краткое Наименование компании
  PNameOrg  = scriptControl.Eval('(' & JSON & ').suggestions[0].data.name.full_with_opf')       // Полное Наименование компании
  AddresOrg = scriptControl.Eval('(' & JSON & ').suggestions[0].data.address.value')            // Адрес
  GolOrg    = scriptControl.Eval('(' & JSON & ').suggestions[0].data.branch_type')              // Филиал или Головная
  INNOrg    = scriptControl.Eval('(' & JSON & ').suggestions[0].data.inn')                      // ИНН
  KPPOrg    = scriptControl.Eval('(' & JSON & ').suggestions[0].data.kpp')                      // КПП
  OGRNOrg   = scriptControl.Eval('(' & JSON & ').suggestions[0].data.ogrn')                     // ОГРН
  RukOrg    = scriptControl.Eval('(' & JSON & ').suggestions[0].data.management.name')          // ФИО руководителя
  DRukOrg   = scriptControl.Eval('(' & JSON & ').suggestions[0].data.management.post')          // должность руководителя
  StateOrg  = scriptControl.Eval('(' & JSON & ').suggestions[0].data.state.status')             /* Статус:
                                                                                                ACTIVE       — действующая
                                                                                                LIQUIDATING  — ликвидируется
                                                                                                LIQUIDATED   — ликвидирована
                                                                                                REORGANIZING — в процессе присоединения к другому юрлицу, 
                                                                                                с последующей ликвидацией */
  TypeOrg   = scriptControl.Eval('(' & JSON & ').suggestions[0].data.type')                     // Тип организации: LEGAL  — юридическое лицо               
  Actual    = scriptControl.Eval('(' & JSON & ').suggestions[0].data.state.actuality_date')     // Дата актуальности сведений
  DateAct   = SQL("Select DATEADD(Second," & Actual/1000 & ",'19700101')")                      // Преобразование полученного числа секунд в нормальную Дату
  // Более подробная инфоррмация на сайте DaData = https://dadata.ru/api/find-party/
  Статус    = ifThen(StateOrg == 'ACTIVE'       ;'Действующая';
              ifThen(StateOrg == 'LIQUIDATING'  ;'Ликвидируется';
              ifThen(StateOrg == 'LIQUIDATED'   ;'Ликвидирована';
              ifThen(StateOrg == 'REORGANIZING' ;'В процессе присоединения к другому юрлицу, с последующей ликвидацией';'Не вычислено'))))
  ГолФил    = IfThen(GolOrg   == 'MAIN'         ;'Головная';'Филиал')               
  Тип       = IfThen(TypeOrg  == 'LEGAL'        ;'Юридическое лицо';'Индивидуальный предприниматель')
  Resultat = 'Краткое наименование: ' & NameOrg   & CR &                                                            
  'Полное наименование: '             & PNameOrg  & CR & 
  'Тип: '                             & Тип       & CR &
  'Адрес: '                           & AddresOrg & CR & 
  'Выбранная организация: '           & ГолФил    & CR & 
  'КПП: '                             & KPPOrg    & CR & 
  'ИНН: '                             & INNOrg    & CR & 
  'ОГРН: '                            & OGRNOrg   & CR & 
  'ФИО руководителя: '                & RukOrg    & CR & 
  'Должность руководителя: '          & DRukOrg   & CR & 
  'Статус организации: '              & Статус    & CR & 
  '---------------------------------------------------' & CR & 
  'Дата актуальности сведений: '      & DateAct  
  EditText(Resultat)
endif

Ну, понятно, что в конце можно не выводить информацию, а передать ее в любом удобном для вас виде, начиная от простого статуса, до Функционального RESULT - это уже на ваш выбор. 

Собственно это все - дешево и сердито, минимально, но тем не менее. Вдруг и это кому-то пригодится.

Удачного дня!

Антон Волков

Тарас, просто к сведению, практически аналогичная функциональность по загрузке данных из ЕГРЮЛ и ЕГРИП появилась в коробке версии 5.8: https://club.directum.ru/webhelp/directum/5.8/index.html?rp_organizacii_zakladaka_organizacii.htm

Тарас Асачёв

Антон, Спасибо за дополнительную информацию 

Но я предложил решение вообще для всей линейки 5 как минимум))))

Руслан Бапин

Тарас, большое спасибо за описание удобного и простого в реализации решения важной задачи!

Бегло и поверхностно ознакомившись с сайтом https://dadata.ru/, я не нашел информацию о том, можно ли запрашивать данные, изменившиеся с заданного момента времени. Это вопрос об актуализации данных, как Вы, наверное, уже догадались :)

Решение в лоб (пробегаться по всему справочнику "Организации" и по каждому контрагенту делать запрос, чтобы проверить, не изменилось ли чего) будет слишком накладным, если актуализировать надо более-менее регулярно. Можно актуализировать информацию об организации только в тот момент, когда пользователю понадобилась данная организация (при выборе контрагента в карточке договора, к примеру), но тут свои минусы. В общем, есть над чем подумать, мне кажется. Уже размышляли над этим?

Антон Максунов

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

Алексей Семакин

Руслан, можно попробовать ориентироваться на значение state.actuality_date. Если поле обновилось с момента прошлого запроса, то анализировать остальные данные. Только запрашивать все данные по организации придется все равно сразу, одним запросом, если планируется, что запросов будет много (сравнимо с суточным лимитом). Таким образом, на трафике не сэкономить тут.

А похоже, запросить только даты актуальности, чтобы потом актуализировать только неактуальных контрагентов, и не получится — насколько я понимаю, сервис всегда возвращает все данные по ИНН/ОГРН.

Алексей Семакин: обновлено 28.01.2020 в 11:07
Роман Деменков

 

Кстати дадата может возвращать данные и в родном для Директума XML

HTTP.setRequestHeader("Accept" ; "application/xml")

И можно получать данные:

 XML = CreateObject("Msxml2.DOMDocument")
 XML.loadXML(Data)   ShowMessage(XML.selectSingleNode("/SuggestResponse/suggestions/data/name/short").text)

 

Этим сервисом успешно закрыл основную свою головную боль: заведение контрагентов с филиалами. Так, действующий ранее сервис по автозаполнению данных из 1С умеет принимать на вход только ИНН, то есть заполнить данные, например, Сбербанка по УР №8616 не удастся-всегда получишь данные "головы" из Мск.
DaData принимает на вход ИНН+КПП или признак "Голова\Филиал", что стало решающим преимуществом.
На очереди следующий шаг-избавление от многочисленных дублей и полная синхронизация контрагентов с 1С.

Авторизуйтесь, чтобы написать комментарий