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

16 8

Для чего это вообще может быть нужно? Ну, как один из знаменитых сервисов, неоднократно отмеченный Хабром, он в принципе привлекателен тем, что у него в сутки дается 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С.

Тарас Асачёв

Если кто искал, то вот Финальная версия:

INN = Object.Params.FindItem('INN')
AppCT           = MimeDecodeString("YXBwbGljYXRpb24vanNvbg==")
Authorization   = MimeDecodeString("VG9rZW4gNzZkZGQ3ODA0ZjBhOTJkODczYTZlYjM4MDM2MDU5NWNlODQzMGMzMA==")
URL             = MimeDecodeString("aHR0cHM6Ly9zdWdnZXN0aХХХW9BpLzRfMS9ycy9maW5kQnlJZC9wYXJ0eQ==")
AcceptEncoding  = MimeDecodeString("Z3ppХХХХХХХХХХХХ0ZQ==")
HTTP   = CreateObject("MSXML2.XMLHTTP.6.0")
HTTP.Open("POST"                        ; URL; false)
HTTP.setRequestHeader("Content-Type"    ; AppCT)
HTTP.setRequestHeader("Accept-Encoding" ; AcceptEncoding)
HTTP.setRequestHeader("Accept"          ; AppCT)
HTTP.setRequestHeader("Authorization"   ; Authorization)
HTTP.Send('{ "query": "' & INN & '" }')
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')                     // ОГРН
  try
    RukOrg    = scriptControl.Eval('(' & JSON & ').suggestions[0].data.management.name')          // ФИО руководителя
  except
    RukOrg    = NameOrg
  endexcept
  try
    DRukOrg   = scriptControl.Eval('(' & JSON & ').suggestions[0].data.management.post')          // должность руководителя
  except
    DRukOrg   = 'ИП'
  endexcept  
  
  
  
  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
  Reference =  References.ОРГ.GetComponent
    AddWhere = Reference.AddWhere(Format("%0:s.%1:s like char(37) + '%2:g' + char(37)"; ArrayOf(Reference.TableName; Reference.Requisites('ИНН').FieldName; INN)))
    Reference.Open 
      if Reference.RecordCount > 0     
          Code = Reference.Requisites('Код').AsString
          CodeOrg = ИзмененияСпрОрганизации(Code; NameOrg; PNameOrg; INNOrg; KPPOrg; null; '' ; ''; null; AddresOrg) // Функция по Созданию/Генерации Организации
          ORGD = References.ОРГ.GetObjectByCode(CodeOrg)
          ORGD.ОГРН = OGRNOrg
          ORGD.Save
          Result = 'Обновлена информация в справочнике Организаций: ' & CR & Resultat 
      else
          CodeOrg = ИзмененияСпрОрганизации(null; NameOrg; PNameOrg; INNOrg; KPPOrg; null; '' ; ''; null; AddresOrg) // Функция по Созданию/Генерации Организации
          ORGD = References.ОРГ.GetObjectByCode(CodeOrg)
          ORGD.ОГРН = OGRNOrg
          ORGD.Save
          Result = 'Создана новая запись в справочнике Организаций: ' & CR & Resultat 
      endif   
  //EditText(Resultat)
endif

Ну и функция:

if Assigned(Контрагент)
  try
   SprOrg = References.ОРГ.GetObjectByCode(Trim(Контрагент))
  except
   SprOrg = References.ОРГ.CreateNew
  endexcept 
else
   SprOrg = References.ОРГ.CreateNew
endif
   SprOrg.Requisites(SYSREQ_NAME).AsString = Наименование          
   SprOrg.Requisites("LongString5").AsString = ЮрНаименование
   SprOrg.Requisites("ИНН").AsString = ИНН
   if Assigned(КПП)
        SprOrg.Requisites("Ед_Изм").AsString = КПП
   endif
   if Assigned(Город)
      try
        SprOrg.Requisites("Город").Value = Город
      except
        RefCity = References.ГРД.GetComponent
        AddWhere = RefCity.AddWhere(Format("%0:s.%1:s like char(37) + '%2:s' + char(37)"; ArrayOf(RefCity.TableName; RefCity.Requisites(SYSREQ_NAME).SQLFieldName; Город)))
        RefCity.Open
        if RefCity.RecordCount > 0
          SprOrg.Requisites("Город").Value = RefCity.Requisites(SYSREQ_CODE).Value
        else
          SprOrg.Requisites("Город").Value = null
        endif
      endexcept          
   endif
   //SprOrg.Requisites("Отрасль").Value = ВидДеятельности
   //SprOrg.Requisites("Партнерство").Value = Партнер
   if Assigned(Email)
      SprOrg.Requisites("Email").AsString = Email
   endif
   if Assigned(Телефон)
      SprOrg.Requisites("Дополнение4").AsString = Телефон
   endif
   if Assigned(Ответственный)
        SprOrg.Requisites("Employee").Value = Ответственный
   endif
   if Assigned(Адрес)
        SprOrg.Requisites("Содержание2").AsString = Адрес
   endif
   SprOrg.Save 
   Rez = SprOrg.SYSREQ_CODE
   SprOrg.Close
   
   Result = Rez

 

Тарас Асачёв: обновлено 04.05.2021 в 15:13

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