Added init version of clearbit integration.
This commit is contained in:
parent
62d35d2a0e
commit
e06f4ee7fe
22 changed files with 1865 additions and 99 deletions
|
@ -156,6 +156,17 @@ job_integration_slack:
|
||||||
- ruby -I test test/integration/slack_test.rb
|
- ruby -I test test/integration/slack_test.rb
|
||||||
- rake db:drop
|
- rake db:drop
|
||||||
|
|
||||||
|
job_integration_clearbit:
|
||||||
|
stage: test
|
||||||
|
tags:
|
||||||
|
- core
|
||||||
|
script:
|
||||||
|
- export RAILS_ENV=test
|
||||||
|
- rake db:create
|
||||||
|
- rake db:migrate
|
||||||
|
- ruby -I test test/integration/clearbit_test.rb
|
||||||
|
- rake db:drop
|
||||||
|
|
||||||
job_integration_es_mysql:
|
job_integration_es_mysql:
|
||||||
stage: test
|
stage: test
|
||||||
tags:
|
tags:
|
||||||
|
|
4
Gemfile
4
Gemfile
|
@ -32,8 +32,6 @@ gem 'omniauth-facebook'
|
||||||
gem 'omniauth-linkedin'
|
gem 'omniauth-linkedin'
|
||||||
gem 'omniauth-google-oauth2'
|
gem 'omniauth-google-oauth2'
|
||||||
|
|
||||||
gem 'zendesk_api'
|
|
||||||
|
|
||||||
gem 'twitter'
|
gem 'twitter'
|
||||||
gem 'koala'
|
gem 'koala'
|
||||||
gem 'mail'
|
gem 'mail'
|
||||||
|
@ -90,6 +88,8 @@ gem 'browser'
|
||||||
|
|
||||||
# integrations
|
# integrations
|
||||||
gem 'slack-notifier'
|
gem 'slack-notifier'
|
||||||
|
gem 'clearbit'
|
||||||
|
gem 'zendesk_api'
|
||||||
|
|
||||||
# event machine
|
# event machine
|
||||||
gem 'eventmachine'
|
gem 'eventmachine'
|
||||||
|
|
|
@ -54,6 +54,8 @@ GEM
|
||||||
childprocess (0.5.9)
|
childprocess (0.5.9)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
clavius (1.0.2)
|
clavius (1.0.2)
|
||||||
|
clearbit (0.2.3)
|
||||||
|
nestful (~> 1.1.0)
|
||||||
coderay (1.1.1)
|
coderay (1.1.1)
|
||||||
coffee-rails (4.1.1)
|
coffee-rails (4.1.1)
|
||||||
coffee-script (>= 2.2.0)
|
coffee-script (>= 2.2.0)
|
||||||
|
@ -134,7 +136,7 @@ GEM
|
||||||
faraday
|
faraday
|
||||||
multi_json
|
multi_json
|
||||||
libv8 (3.16.14.13)
|
libv8 (3.16.14.13)
|
||||||
listen (3.0.6)
|
listen (3.1.1)
|
||||||
rb-fsevent (>= 0.9.3)
|
rb-fsevent (>= 0.9.3)
|
||||||
rb-inotify (>= 0.9.7)
|
rb-inotify (>= 0.9.7)
|
||||||
loofah (2.0.3)
|
loofah (2.0.3)
|
||||||
|
@ -154,6 +156,7 @@ GEM
|
||||||
mysql2 (0.3.20)
|
mysql2 (0.3.20)
|
||||||
naught (1.1.0)
|
naught (1.1.0)
|
||||||
nenv (0.3.0)
|
nenv (0.3.0)
|
||||||
|
nestful (1.1.1)
|
||||||
net-ldap (0.14.0)
|
net-ldap (0.14.0)
|
||||||
nokogiri (1.6.7.2)
|
nokogiri (1.6.7.2)
|
||||||
mini_portile2 (~> 2.0.0.rc2)
|
mini_portile2 (~> 2.0.0.rc2)
|
||||||
|
@ -323,6 +326,7 @@ DEPENDENCIES
|
||||||
autoprefixer-rails (>= 5.2)
|
autoprefixer-rails (>= 5.2)
|
||||||
biz
|
biz
|
||||||
browser
|
browser
|
||||||
|
clearbit
|
||||||
coffee-rails
|
coffee-rails
|
||||||
coffee-script-source
|
coffee-script-source
|
||||||
coffeelint
|
coffeelint
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
class Index extends App.ControllerIntegrationBase
|
||||||
|
featureIntegration: 'clearbit_integration'
|
||||||
|
featureName: 'Clearbit'
|
||||||
|
featureConfig: 'clearbit_config'
|
||||||
|
description: [
|
||||||
|
['Automatically enrich your customers and organizations with fresh, up-to-date intel. Map data directly to object fields.
|
||||||
|
']
|
||||||
|
]
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
super
|
||||||
|
new Form(
|
||||||
|
el: @$('.js-form')
|
||||||
|
)
|
||||||
|
|
||||||
|
new App.HttpLog(
|
||||||
|
el: @$('.js-log')
|
||||||
|
facility: 'clearbit'
|
||||||
|
)
|
||||||
|
|
||||||
|
class Form extends App.Controller
|
||||||
|
events:
|
||||||
|
'submit form': 'update'
|
||||||
|
'click .js-userSync .js-add': 'addUserSync'
|
||||||
|
'click .js-organizationSync .js-add': 'addOrganizationSync'
|
||||||
|
'click .js-userSync .js-remove': 'removeRow'
|
||||||
|
'click .js-organizationSync .js-remove': 'removeRow'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# check authentication
|
||||||
|
return if !@authenticate()
|
||||||
|
|
||||||
|
@subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false)
|
||||||
|
|
||||||
|
currentConfig: ->
|
||||||
|
config = App.Setting.get('clearbit_config')
|
||||||
|
if !config
|
||||||
|
config = {}
|
||||||
|
if config.organization_autocreate is undefined
|
||||||
|
config.organization_autocreate = true
|
||||||
|
if config.organization_shared is undefined
|
||||||
|
config.organization_shared = false
|
||||||
|
if !config.user_sync
|
||||||
|
config.user_sync =
|
||||||
|
'person.name.givenName': 'user.firstname'
|
||||||
|
'person.name.familyName': 'user.lastname'
|
||||||
|
'person.email': 'user.email'
|
||||||
|
'person.bio': 'user.note'
|
||||||
|
'company.url': 'user.web'
|
||||||
|
'person.site': 'user.web'
|
||||||
|
'company.location': 'user.address'
|
||||||
|
'person.location': 'user.address'
|
||||||
|
if !config.organization_sync
|
||||||
|
config.organization_sync =
|
||||||
|
'company.legalName': 'organization.name'
|
||||||
|
'company.name': 'organization.name'
|
||||||
|
'company.description': 'organization.note'
|
||||||
|
config
|
||||||
|
|
||||||
|
setConfig: (value) ->
|
||||||
|
App.Setting.set('clearbit_config', value)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
@config = @currentConfig()
|
||||||
|
|
||||||
|
settings = [
|
||||||
|
{ name: 'api_key', display: 'API Key', tag: 'input', type: 'text', limit: 100, null: false, placeholder: '...', note: 'Your api key.' },
|
||||||
|
{ name: 'organization_autocreate', display: 'Auto create', tag: 'boolean', type: 'boolean', null: false, note: 'Create organizations automatically if record has one.' },
|
||||||
|
{ name: 'organization_shared', display: 'Shared', tag: 'boolean', type: 'boolean', null: false, note: 'New organizations are shared.' },
|
||||||
|
]
|
||||||
|
|
||||||
|
@html App.view('integration/clearbit')(
|
||||||
|
config: @config
|
||||||
|
settings: settings
|
||||||
|
)
|
||||||
|
|
||||||
|
for setting in settings
|
||||||
|
setting.display = ''
|
||||||
|
new App.ControllerForm(
|
||||||
|
el: @$("[data-name=#{setting.name}]")
|
||||||
|
model: { configure_attributes: [setting] }
|
||||||
|
params: @config
|
||||||
|
)
|
||||||
|
|
||||||
|
updateCurrentConfig: =>
|
||||||
|
config = @config
|
||||||
|
cleanupInput = @cleanupInput
|
||||||
|
|
||||||
|
params = @formParam(@$('form'))
|
||||||
|
config.api_key = params['api_key']
|
||||||
|
config.organization_autocreate = params['organization_autocreate']
|
||||||
|
config.organization_shared = params['organization_shared']
|
||||||
|
|
||||||
|
# user sync
|
||||||
|
config.user_sync = {}
|
||||||
|
@$('.js-userSync .js-row').each(->
|
||||||
|
element = $(@)
|
||||||
|
source = cleanupInput(element.find('input[name="source"]').val())
|
||||||
|
destination = cleanupInput(element.find('input[name="destination"]').val())
|
||||||
|
config.user_sync[source] = destination
|
||||||
|
)
|
||||||
|
|
||||||
|
# organization sync
|
||||||
|
config.organization_sync = {}
|
||||||
|
@$('.js-organizationSync .js-row').each(->
|
||||||
|
element = $(@)
|
||||||
|
source = cleanupInput(element.find('input[name="source"]').val())
|
||||||
|
destination = cleanupInput(element.find('input[name="destination"]').val())
|
||||||
|
config.organization_sync[source] = destination
|
||||||
|
)
|
||||||
|
|
||||||
|
@config = config
|
||||||
|
|
||||||
|
update: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@updateCurrentConfig()
|
||||||
|
@setConfig(@config)
|
||||||
|
|
||||||
|
cleanupInput: (value) ->
|
||||||
|
return value if !value
|
||||||
|
value.replace(/\s/g, '').trim()
|
||||||
|
|
||||||
|
addUserSync: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@updateCurrentConfig()
|
||||||
|
element = $(e.currentTarget).closest('tr')
|
||||||
|
source = @cleanupInput(element.find('input[name="source"]').val())
|
||||||
|
destination = @cleanupInput(element.find('input[name="destination"]').val())
|
||||||
|
@config.user_sync[source] = destination
|
||||||
|
@setConfig(@config)
|
||||||
|
@render()
|
||||||
|
|
||||||
|
addOrganizationSync: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@updateCurrentConfig()
|
||||||
|
element = $(e.currentTarget).closest('tr')
|
||||||
|
source = @cleanupInput(element.find('input[name="source"]').val())
|
||||||
|
destination = @cleanupInput(element.find('input[name="destination"]').val())
|
||||||
|
@config.organization_sync[source] = destination
|
||||||
|
@setConfig(@config)
|
||||||
|
@render()
|
||||||
|
|
||||||
|
removeRow: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@updateCurrentConfig()
|
||||||
|
element = $(e.currentTarget).closest('tr')
|
||||||
|
element.remove()
|
||||||
|
|
||||||
|
class State
|
||||||
|
@current: ->
|
||||||
|
App.Setting.get('clearbit_integration')
|
||||||
|
|
||||||
|
App.Config.set(
|
||||||
|
'IntegrationClearbit'
|
||||||
|
{
|
||||||
|
name: 'Clearbit'
|
||||||
|
target: '#system/integration/clearbit'
|
||||||
|
description: 'A powerfull service to get more information about your customers.'
|
||||||
|
controller: Index
|
||||||
|
state: State
|
||||||
|
}
|
||||||
|
'NavBarIntegrations'
|
||||||
|
)
|
|
@ -148,7 +148,7 @@ App.Config.set(
|
||||||
{
|
{
|
||||||
name: 'sipgate.io'
|
name: 'sipgate.io'
|
||||||
target: '#system/integration/sipgate'
|
target: '#system/integration/sipgate'
|
||||||
description: 'VoIP services provide.'
|
description: 'VoIP service provider with realtime push.'
|
||||||
controller: Index
|
controller: Index
|
||||||
state: State
|
state: State
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,93 +1,3 @@
|
||||||
class App.SettingsForm extends App.Controller
|
|
||||||
events:
|
|
||||||
'submit form': 'update'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
|
|
||||||
# check authentication
|
|
||||||
return if !@authenticate()
|
|
||||||
|
|
||||||
@subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false)
|
|
||||||
|
|
||||||
render: =>
|
|
||||||
|
|
||||||
# serach area settings
|
|
||||||
settings = App.Setting.search(
|
|
||||||
filter:
|
|
||||||
area: @area
|
|
||||||
)
|
|
||||||
|
|
||||||
# filter online service settings
|
|
||||||
if App.Config.get('system_online_service')
|
|
||||||
settings = _.filter(settings, (setting) ->
|
|
||||||
return if setting.online_service
|
|
||||||
return if setting.preferences && setting.preferences.online_service_disable
|
|
||||||
setting
|
|
||||||
)
|
|
||||||
return if _.isEmpty(settings)
|
|
||||||
|
|
||||||
# sort by prio
|
|
||||||
settings = _.sortBy( settings, (setting) ->
|
|
||||||
return if !setting.preferences
|
|
||||||
setting.preferences.prio
|
|
||||||
)
|
|
||||||
|
|
||||||
localEl = $( App.view('settings/form')(
|
|
||||||
settings: settings
|
|
||||||
))
|
|
||||||
|
|
||||||
for setting in settings
|
|
||||||
configure_attributes = setting.options['form']
|
|
||||||
value = App.Setting.get(setting.name)
|
|
||||||
params = {}
|
|
||||||
params[setting.name] = value
|
|
||||||
new App.ControllerForm(
|
|
||||||
el: localEl.find("[data-name=#{setting.name}]")
|
|
||||||
model: { configure_attributes: configure_attributes, className: '' }
|
|
||||||
params: params
|
|
||||||
)
|
|
||||||
@html localEl
|
|
||||||
|
|
||||||
update: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
@formDisable(e)
|
|
||||||
params = @formParam(e.target)
|
|
||||||
|
|
||||||
ui = @
|
|
||||||
count = 0
|
|
||||||
for name, value of params
|
|
||||||
if App.Setting.findByAttribute('name', name)
|
|
||||||
count += 1
|
|
||||||
App.Setting.set(
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
done: ->
|
|
||||||
ui.formEnable(e)
|
|
||||||
count -= 1
|
|
||||||
if count == 0
|
|
||||||
App.Event.trigger 'notify', {
|
|
||||||
type: 'success'
|
|
||||||
msg: App.i18n.translateContent('Update successful!')
|
|
||||||
timeout: 2000
|
|
||||||
}
|
|
||||||
|
|
||||||
# rerender ui || get new collections and session data
|
|
||||||
if @preferences
|
|
||||||
if @preferences.render
|
|
||||||
App.Event.trigger( 'ui:rerender' )
|
|
||||||
|
|
||||||
if @preferences.session_check
|
|
||||||
App.Auth.loginCheck()
|
|
||||||
|
|
||||||
fail: (settings, details) ->
|
|
||||||
App.Event.trigger 'notify', {
|
|
||||||
type: 'error'
|
|
||||||
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
|
|
||||||
timeout: 2000
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
class App.SettingsArea extends App.Controller
|
class App.SettingsArea extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
89
app/assets/javascripts/app/controllers/_settings/form.coffee
Normal file
89
app/assets/javascripts/app/controllers/_settings/form.coffee
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
class App.SettingsForm extends App.Controller
|
||||||
|
events:
|
||||||
|
'submit form': 'update'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
# check authentication
|
||||||
|
return if !@authenticate()
|
||||||
|
|
||||||
|
@subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
|
||||||
|
# serach area settings
|
||||||
|
settings = App.Setting.search(
|
||||||
|
filter:
|
||||||
|
area: @area
|
||||||
|
)
|
||||||
|
|
||||||
|
# filter online service settings
|
||||||
|
if App.Config.get('system_online_service')
|
||||||
|
settings = _.filter(settings, (setting) ->
|
||||||
|
return if setting.online_service
|
||||||
|
return if setting.preferences && setting.preferences.online_service_disable
|
||||||
|
setting
|
||||||
|
)
|
||||||
|
return if _.isEmpty(settings)
|
||||||
|
|
||||||
|
# sort by prio
|
||||||
|
settings = _.sortBy( settings, (setting) ->
|
||||||
|
return if !setting.preferences
|
||||||
|
setting.preferences.prio
|
||||||
|
)
|
||||||
|
|
||||||
|
localEl = $( App.view('settings/form')(
|
||||||
|
settings: settings
|
||||||
|
))
|
||||||
|
|
||||||
|
for setting in settings
|
||||||
|
configure_attributes = setting.options['form']
|
||||||
|
value = App.Setting.get(setting.name)
|
||||||
|
params = {}
|
||||||
|
params[setting.name] = value
|
||||||
|
new App.ControllerForm(
|
||||||
|
el: localEl.find("[data-name=#{setting.name}]")
|
||||||
|
model: { configure_attributes: configure_attributes }
|
||||||
|
params: params
|
||||||
|
)
|
||||||
|
@html localEl
|
||||||
|
|
||||||
|
update: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@formDisable(e)
|
||||||
|
params = @formParam(e.target)
|
||||||
|
|
||||||
|
ui = @
|
||||||
|
count = 0
|
||||||
|
for name, value of params
|
||||||
|
if App.Setting.findByAttribute('name', name)
|
||||||
|
count += 1
|
||||||
|
App.Setting.set(
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
done: ->
|
||||||
|
ui.formEnable(e)
|
||||||
|
count -= 1
|
||||||
|
if count == 0
|
||||||
|
App.Event.trigger 'notify', {
|
||||||
|
type: 'success'
|
||||||
|
msg: App.i18n.translateContent('Update successful!')
|
||||||
|
timeout: 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
# rerender ui || get new collections and session data
|
||||||
|
if @preferences
|
||||||
|
if @preferences.render
|
||||||
|
App.Event.trigger( 'ui:rerender' )
|
||||||
|
|
||||||
|
if @preferences.session_check
|
||||||
|
App.Auth.loginCheck()
|
||||||
|
|
||||||
|
fail: (settings, details) ->
|
||||||
|
App.Event.trigger 'notify', {
|
||||||
|
type: 'error'
|
||||||
|
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to update object!')
|
||||||
|
timeout: 2000
|
||||||
|
}
|
||||||
|
)
|
|
@ -220,6 +220,7 @@ class App extends Spine.Controller
|
||||||
|
|
||||||
# define richtext helper
|
# define richtext helper
|
||||||
params.RichText = (string) ->
|
params.RichText = (string) ->
|
||||||
|
return string if !string
|
||||||
if string.match(/@T\('/)
|
if string.match(/@T\('/)
|
||||||
string = string.replace(/@T\('(.+?)'\)/g, (match, capture) ->
|
string = string.replace(/@T\('(.+?)'\)/g, (match, capture) ->
|
||||||
App.i18n.translateContent(capture)
|
App.i18n.translateContent(capture)
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<form>
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<table class="settings-list" style="width: 100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="15%"><%- @T('Title') %>
|
||||||
|
<th width="50%"><%- @T('Value') %>
|
||||||
|
<th width="35%"><%- @T('Description') %>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% for setting in @settings: %>
|
||||||
|
<tr>
|
||||||
|
<td><%- @T(setting.display) %>
|
||||||
|
<td data-name="<%- setting.name %>">
|
||||||
|
<td><p class="help-text"><%- @RichText(setting.note) %></p>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2><%- @T('Mapping') %></h2>
|
||||||
|
|
||||||
|
<p><%- @T('What values of %s should be synced to users.', 'Clearbit') %></p>
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<table class="settings-list js-userSync" style="width: 100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="45%"><%- @T('Clearbit') %>
|
||||||
|
<th width="45%"><%- @T('Zammad') %>
|
||||||
|
<th width="10%"><%- @T('Action') %>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% for source, destination of @config.user_sync: %>
|
||||||
|
<tr class="js-row">
|
||||||
|
<td class="settings-list-control-cell"><input name="source" value="<%= source %>" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-control-cell"><input name="destination" value="<%= destination %>" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-row-control"><div class="btn btn--text js-remove"><%- @Icon('trash') %> <%- @T('Remove') %></div>
|
||||||
|
<% end %>
|
||||||
|
<tr>
|
||||||
|
<td class="settings-list-control-cell"><input name="source" value="" placeholder="person.attribute" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-control-cell"><input name="destination" value="" placeholder="user.attribute" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-row-control"><div class="btn btn--text btn--create js-add"><%- @Icon('plus-small') %> <%- @T('Add') %></div>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><%- @T('What values of %s should be synced to organization.', 'Clearbit') %></p>
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<table class="settings-list js-organizationSync" style="width: 100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="45%"><%- @T('Clearbit') %>
|
||||||
|
<th width="45%"><%- @T('Zammad') %>
|
||||||
|
<th width="10%"><%- @T('Action') %>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% for source, destination of @config.organization_sync: %>
|
||||||
|
<tr class="js-row">
|
||||||
|
<td class="settings-list-control-cell"><input name="source" value="<%= source %>" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-control-cell"><input name="destination" value="<%= destination %>" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-row-control"><div class="btn btn--text js-remove"><%- @Icon('trash') %> <%- @T('Remove') %></div>
|
||||||
|
<% end %>
|
||||||
|
<tr>
|
||||||
|
<td class="settings-list-control-cell"><input name="source" value="" placeholder="company.attribute" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-control-cell"><input name="destination" value="" placeholder="organization.attribute" class="form-control form-control--small js-summary">
|
||||||
|
<td class="settings-list-row-control"><div class="btn btn--text btn--create js-add"><%- @Icon('plus-small') %> <%- @T('Add') %></div>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn--primary"><%- @T('Save') %></button>
|
||||||
|
</form>
|
|
@ -6,7 +6,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 30px;"></th>
|
<th style="width: 30px;"></th>
|
||||||
<th style="width: 40%;"><%- @T('Service') %></th>
|
<th style="width: 30%;"><%- @T('Service') %></th>
|
||||||
<th><%- @T('Description') %></th>
|
<th><%- @T('Description') %></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
5
app/models/external_sync.rb
Normal file
5
app/models/external_sync.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class ExternalSync < ApplicationModel
|
||||||
|
store :last_payload
|
||||||
|
end
|
|
@ -23,8 +23,13 @@ class Transaction::BackgroundJob
|
||||||
def perform
|
def perform
|
||||||
Setting.where(area: 'Transaction::Backend').order(:name).each {|setting|
|
Setting.where(area: 'Transaction::Backend').order(:name).each {|setting|
|
||||||
backend = Setting.get(setting.name)
|
backend = Setting.get(setting.name)
|
||||||
|
begin
|
||||||
integration = Kernel.const_get(backend).new(@item, @params)
|
integration = Kernel.const_get(backend).new(@item, @params)
|
||||||
integration.perform
|
integration.perform
|
||||||
|
rescue => e
|
||||||
|
logger.error 'ERROR: ' + setting.inspect
|
||||||
|
logger.error 'ERROR: ' + e.inspect
|
||||||
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
321
app/models/transaction/clearbit_enrichment.rb
Normal file
321
app/models/transaction/clearbit_enrichment.rb
Normal file
|
@ -0,0 +1,321 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class Transaction::ClearbitEnrichment
|
||||||
|
|
||||||
|
=begin
|
||||||
|
{
|
||||||
|
object: 'User',
|
||||||
|
type: 'create',
|
||||||
|
object_id: 123,
|
||||||
|
changes: {
|
||||||
|
'attribute1' => [before, now],
|
||||||
|
'attribute2' => [before, now],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
=end
|
||||||
|
|
||||||
|
def initialize(item, params = {})
|
||||||
|
@item = item
|
||||||
|
@params = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
|
||||||
|
# return if we run import mode
|
||||||
|
return if Setting.get('import_mode')
|
||||||
|
|
||||||
|
return if @item[:object] != 'User'
|
||||||
|
return if @item[:type] != 'create'
|
||||||
|
|
||||||
|
return if !Setting.get('clearbit_integration')
|
||||||
|
|
||||||
|
config = Setting.get('clearbit_config')
|
||||||
|
return if !config
|
||||||
|
return if config['api_key'].empty?
|
||||||
|
|
||||||
|
user = User.lookup(id: @item[:object_id])
|
||||||
|
return if !user
|
||||||
|
|
||||||
|
Transaction::ClearbitEnrichment.sync_user(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.sync
|
||||||
|
users = User.of_role('Customer')
|
||||||
|
users.each {|user|
|
||||||
|
sync_user(user)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.sync_user(user)
|
||||||
|
|
||||||
|
return if !user.email
|
||||||
|
data = fetch(user.email)
|
||||||
|
#p 'OO: ' + data.inspect
|
||||||
|
|
||||||
|
config = Setting.get('clearbit_config')
|
||||||
|
return if !config
|
||||||
|
|
||||||
|
# get new user sync attributes
|
||||||
|
user_sync = config['user_sync']
|
||||||
|
user_sync_values = {}
|
||||||
|
if user_sync
|
||||||
|
user_sync.each {|callback, destination|
|
||||||
|
next if !user_sync_values[destination].empty?
|
||||||
|
value = _replace(callback, data)
|
||||||
|
next if !value
|
||||||
|
user_sync_values[destination] = value
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# get new organization sync attributes
|
||||||
|
organization_sync = config['organization_sync']
|
||||||
|
organization_sync_values = {}
|
||||||
|
if organization_sync
|
||||||
|
organization_sync.each {|callback, destination|
|
||||||
|
next if !organization_sync_values[destination].empty?
|
||||||
|
value = _replace(callback, data)
|
||||||
|
next if !value
|
||||||
|
organization_sync_values[destination] = value
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# get latest user synced attributes
|
||||||
|
external_syn_user = nil
|
||||||
|
user_sync_values_last_time = {}
|
||||||
|
if data && data['person'] && data['person']['id']
|
||||||
|
external_syn_user = ExternalSync.find_by(
|
||||||
|
source: 'clearbit',
|
||||||
|
source_id: data['person']['id'],
|
||||||
|
object: 'User',
|
||||||
|
o_id: user.id,
|
||||||
|
)
|
||||||
|
if external_syn_user && external_syn_user.last_payload
|
||||||
|
user_sync.each {|callback, destination|
|
||||||
|
next if !user_sync_values_last_time[destination].empty?
|
||||||
|
value = _replace(callback, external_syn_user.last_payload)
|
||||||
|
next if !value
|
||||||
|
user_sync_values_last_time[destination] = value
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# if person record exists
|
||||||
|
user_has_changed = false
|
||||||
|
user_sync_values.each {|destination, value|
|
||||||
|
attribute = destination.sub(/^user\./, '')
|
||||||
|
next if user[attribute] == value
|
||||||
|
next if !user[attribute].empty? && user_sync_values_last_time[destination] != user[attribute]
|
||||||
|
begin
|
||||||
|
user[attribute] = value
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.error "ERROR: Unable to assign user.#{attribute}: #{e.inspect}"
|
||||||
|
end
|
||||||
|
user_has_changed = true
|
||||||
|
}
|
||||||
|
if user_has_changed
|
||||||
|
user.updated_by_id = 1
|
||||||
|
if data['person'] && data['person']['id']
|
||||||
|
if external_syn_user
|
||||||
|
external_syn_user.last_payload = data
|
||||||
|
external_syn_user.save
|
||||||
|
else
|
||||||
|
external_syn_user = ExternalSync.create(
|
||||||
|
source: 'clearbit',
|
||||||
|
source_id: data['person']['id'],
|
||||||
|
object: 'User',
|
||||||
|
o_id: user.id,
|
||||||
|
last_payload: data,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# if no company record exists
|
||||||
|
if !data['company']
|
||||||
|
if user_has_changed
|
||||||
|
user.save
|
||||||
|
end
|
||||||
|
Observer::Transaction.commit
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# if company record exists
|
||||||
|
external_syn_organization = ExternalSync.find_by(
|
||||||
|
source: 'clearbit',
|
||||||
|
source_id: data['company']['id'],
|
||||||
|
)
|
||||||
|
|
||||||
|
# create new organization
|
||||||
|
if !external_syn_organization
|
||||||
|
|
||||||
|
# can't create organization without name
|
||||||
|
if organization_sync_values['organization.name'].empty?
|
||||||
|
Observer::Transaction.commit
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# find by name
|
||||||
|
organization = Organization.find_by(name: organization_sync_values['organization.name'])
|
||||||
|
|
||||||
|
# create new organization
|
||||||
|
if !organization
|
||||||
|
organization = Organization.new(
|
||||||
|
shared: config['organization_shared'],
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
organization_sync_values.each {|destination, value|
|
||||||
|
attribute = destination.sub(/^organization\./, '')
|
||||||
|
next if !organization[attribute].empty?
|
||||||
|
begin
|
||||||
|
organization[attribute] = value
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.error "ERROR: Unable to assign organization.#{attribute}: #{e.inspect}"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
organization.save
|
||||||
|
end
|
||||||
|
ExternalSync.create(
|
||||||
|
source: 'clearbit',
|
||||||
|
source_id: data['company']['id'],
|
||||||
|
object: 'Organization',
|
||||||
|
o_id: organization.id,
|
||||||
|
last_payload: data,
|
||||||
|
)
|
||||||
|
|
||||||
|
# assign new organization to user
|
||||||
|
if !user.organization_id
|
||||||
|
user.organization_id = organization.id
|
||||||
|
user.save
|
||||||
|
end
|
||||||
|
Observer::Transaction.commit
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# get latest organization synced attributes
|
||||||
|
organization_sync_values_last_time = {}
|
||||||
|
if external_syn_organization && external_syn_organization.last_payload
|
||||||
|
organization_sync.each {|callback, destination|
|
||||||
|
next if !organization_sync_values_last_time[destination].empty?
|
||||||
|
value = _replace(callback, external_syn_organization.last_payload)
|
||||||
|
next if !value
|
||||||
|
organization_sync_values_last_time[destination] = value
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# update existing organization
|
||||||
|
organization = Organization.find(external_syn_organization[:o_id])
|
||||||
|
organization_has_changed = false
|
||||||
|
organization_sync_values.each {|destination, value|
|
||||||
|
attribute = destination.sub(/^organization\./, '')
|
||||||
|
next if organization[attribute] == value
|
||||||
|
next if !organization[attribute].empty? && organization_sync_values_last_time[destination] != organization[attribute]
|
||||||
|
begin
|
||||||
|
organization[attribute] = value
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.error "ERROR: Unable to assign organization.#{attribute}: #{e.inspect}"
|
||||||
|
end
|
||||||
|
organization_has_changed = true
|
||||||
|
}
|
||||||
|
if organization_has_changed
|
||||||
|
organization.updated_by_id = 1
|
||||||
|
organization.save
|
||||||
|
external_syn_organization.last_payload = data
|
||||||
|
external_syn_organization.save
|
||||||
|
end
|
||||||
|
|
||||||
|
# assign new organization to user
|
||||||
|
if !user.organization_id
|
||||||
|
user_has_changed = true
|
||||||
|
user.organization_id = organization.id
|
||||||
|
end
|
||||||
|
|
||||||
|
if user_has_changed
|
||||||
|
user.save
|
||||||
|
end
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def self._replace(callback, data)
|
||||||
|
object_name = nil
|
||||||
|
object_method = nil
|
||||||
|
placeholder = nil
|
||||||
|
|
||||||
|
if callback =~ /\A ( [\w]+ )\.( [\w\.]+ ) \z/x
|
||||||
|
object_name = $1
|
||||||
|
object_method = $2
|
||||||
|
end
|
||||||
|
|
||||||
|
return if !data
|
||||||
|
return if !data[object_name]
|
||||||
|
|
||||||
|
# do validaton, ignore some methodes
|
||||||
|
if callback =~ /(`|\.(|\s*)(save|destroy|delete|remove|drop|update\(|update_att|create\(|new|all|where|find))/i
|
||||||
|
placeholder = "#{callback} (not allowed)"
|
||||||
|
|
||||||
|
# get value based on object_name and object_method
|
||||||
|
elsif object_name && object_method
|
||||||
|
object_refs = data[object_name]
|
||||||
|
object_methods = object_method.split('.')
|
||||||
|
object_methods_s = ''
|
||||||
|
object_methods.each {|method|
|
||||||
|
if object_methods_s != ''
|
||||||
|
object_methods_s += '.'
|
||||||
|
end
|
||||||
|
object_methods_s += method
|
||||||
|
|
||||||
|
# if method exists
|
||||||
|
break if !object_refs.respond_to?(method.to_sym) && !object_refs[method]
|
||||||
|
|
||||||
|
object_refs = if object_refs.respond_to?(method.to_sym)
|
||||||
|
object_refs.send(method.to_sym)
|
||||||
|
else
|
||||||
|
object_refs[method]
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if object_refs.class == String
|
||||||
|
placeholder = object_refs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
placeholder
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.fetch(email)
|
||||||
|
if !Rails.env.production?
|
||||||
|
filename = "#{Rails.root}/test/fixtures/clearbit/#{email}.json"
|
||||||
|
if File.exist?(filename)
|
||||||
|
data = IO.binread(filename)
|
||||||
|
return JSON.parse(data) if data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
config = Setting.get('clearbit_config')
|
||||||
|
return if !config
|
||||||
|
return if config['api_key'].empty?
|
||||||
|
|
||||||
|
record = {
|
||||||
|
direction: 'out',
|
||||||
|
facility: 'clearbit',
|
||||||
|
url: "clearbit -> #{email}",
|
||||||
|
status: 200,
|
||||||
|
ip: nil,
|
||||||
|
request: { content: email },
|
||||||
|
response: {},
|
||||||
|
method: 'GET',
|
||||||
|
}
|
||||||
|
|
||||||
|
begin
|
||||||
|
Clearbit.key = config['api_key']
|
||||||
|
result = Clearbit::Enrichment.find(email: email, stream: true)
|
||||||
|
record[:response] = { code: 200, content: result.to_s }
|
||||||
|
rescue => e
|
||||||
|
record[:status] = 500
|
||||||
|
record[:response] = { code: 500, content: e.inspect }
|
||||||
|
end
|
||||||
|
HttpLog.create(record)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
15
db/migrate/20160424000002_create_external_sync.rb
Normal file
15
db/migrate/20160424000002_create_external_sync.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class CreateExternalSync < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
create_table :external_syncs do |t|
|
||||||
|
t.string :source, limit: 100, null: false
|
||||||
|
t.string :source_id, limit: 200, null: false
|
||||||
|
t.string :object, limit: 100, null: false
|
||||||
|
t.integer :o_id, null: false
|
||||||
|
t.text :last_payload, limit: 500.kilobytes + 1, null: true
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
add_index :external_syncs, [:source, :source_id], unique: true
|
||||||
|
add_index :external_syncs, [:source, :source_id, :object, :o_id]
|
||||||
|
add_index :external_syncs, [:object, :o_id]
|
||||||
|
end
|
||||||
|
end
|
46
db/migrate/20160425000001_add_clearbit_integration.rb
Normal file
46
db/migrate/20160425000001_add_clearbit_integration.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
class AddClearbitIntegration < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Clearbit integration',
|
||||||
|
name: 'clearbit_integration',
|
||||||
|
area: 'Integration::Switch',
|
||||||
|
description: 'Define if Clearbit (http://www.clearbit.com) is enabled or not.',
|
||||||
|
options: {
|
||||||
|
form: [
|
||||||
|
{
|
||||||
|
display: '',
|
||||||
|
null: true,
|
||||||
|
name: 'clearbit_integration',
|
||||||
|
tag: 'boolean',
|
||||||
|
options: {
|
||||||
|
true => 'yes',
|
||||||
|
false => 'no',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
state: false,
|
||||||
|
preferences: { prio: 1 },
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Clearbit config',
|
||||||
|
name: 'clearbit_config',
|
||||||
|
area: 'Integration::Clearbit',
|
||||||
|
description: 'Define the Clearbit config.',
|
||||||
|
options: {},
|
||||||
|
state: {},
|
||||||
|
frontend: false,
|
||||||
|
preferences: { prio: 2 },
|
||||||
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define transaction backend.',
|
||||||
|
name: '9000_clearbit_enrichment',
|
||||||
|
area: 'Transaction::Backend',
|
||||||
|
description: 'Define the transaction backend which will enrich customer and organization informations from (http://www.clearbit.com).',
|
||||||
|
options: {},
|
||||||
|
state: 'Transaction::ClearbitEnrichment',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
42
db/seeds.rb
42
db/seeds.rb
|
@ -1864,6 +1864,48 @@ Setting.create_if_not_exists(
|
||||||
frontend: false,
|
frontend: false,
|
||||||
preferences: { prio: 2 },
|
preferences: { prio: 2 },
|
||||||
)
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Clearbit integration',
|
||||||
|
name: 'clearbit_integration',
|
||||||
|
area: 'Integration::Switch',
|
||||||
|
description: 'Define if Clearbit (http://www.clearbit.com) is enabled or not.',
|
||||||
|
options: {
|
||||||
|
form: [
|
||||||
|
{
|
||||||
|
display: '',
|
||||||
|
null: true,
|
||||||
|
name: 'clearbit_integration',
|
||||||
|
tag: 'boolean',
|
||||||
|
options: {
|
||||||
|
true => 'yes',
|
||||||
|
false => 'no',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
state: false,
|
||||||
|
preferences: { prio: 1 },
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Clearbit config',
|
||||||
|
name: 'clearbit_config',
|
||||||
|
area: 'Integration::Clearbit',
|
||||||
|
description: 'Define the Clearbit config.',
|
||||||
|
options: {},
|
||||||
|
state: {},
|
||||||
|
frontend: false,
|
||||||
|
preferences: { prio: 2 },
|
||||||
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Define transaction backend.',
|
||||||
|
name: '9000_clearbit_enrichment',
|
||||||
|
area: 'Transaction::Backend',
|
||||||
|
description: 'Define the transaction backend which will enrich customer and organization informations from (http://www.clearbit.com).',
|
||||||
|
options: {},
|
||||||
|
state: 'Transaction::ClearbitEnrichment',
|
||||||
|
frontend: false
|
||||||
|
)
|
||||||
|
|
||||||
signature = Signature.create_if_not_exists(
|
signature = Signature.create_if_not_exists(
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|
188
test/fixtures/clearbit/alex@alexmaccaw.com.json
vendored
Normal file
188
test/fixtures/clearbit/alex@alexmaccaw.com.json
vendored
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
{
|
||||||
|
"person": {
|
||||||
|
"id": "d54c54ad-40be-4305-8a34-0ab44710b90d",
|
||||||
|
"name": {
|
||||||
|
"fullName": "Alex MacCaw",
|
||||||
|
"givenName": "Alex",
|
||||||
|
"familyName": "MacCaw"
|
||||||
|
},
|
||||||
|
"email": "alex@alexmaccaw.com",
|
||||||
|
"gender": "male",
|
||||||
|
"location": "San Francisco, CA, US",
|
||||||
|
"timeZone": "America/Los_Angeles",
|
||||||
|
"utcOffset": -8,
|
||||||
|
"geo": {
|
||||||
|
"city": "San Francisco",
|
||||||
|
"state": "California",
|
||||||
|
"stateCode": "CA",
|
||||||
|
"country": "United States",
|
||||||
|
"countryCode": "US",
|
||||||
|
"lat": 37.7749295,
|
||||||
|
"lng": -122.4194155
|
||||||
|
},
|
||||||
|
"bio": "O'Reilly author, software engineer & traveller. Founder of https://clearbit.com",
|
||||||
|
"site": "http://alexmaccaw.com",
|
||||||
|
"avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/d54c54ad-40be-4305-8a34-0ab44710b90d",
|
||||||
|
"employment": {
|
||||||
|
"domain": "clearbit.com",
|
||||||
|
"name": "Clearbit",
|
||||||
|
"title": "Founder and CEO",
|
||||||
|
"role": "ceo",
|
||||||
|
"seniority": "executive"
|
||||||
|
},
|
||||||
|
"facebook": {
|
||||||
|
"handle": "amaccaw"
|
||||||
|
},
|
||||||
|
"github": {
|
||||||
|
"handle": "maccman",
|
||||||
|
"avatar": "https://avatars.githubusercontent.com/u/2142?v=2",
|
||||||
|
"company": "Clearbit",
|
||||||
|
"blog": "http://alexmaccaw.com",
|
||||||
|
"followers": 2932,
|
||||||
|
"following": 94
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "maccaw",
|
||||||
|
"id": "2006261",
|
||||||
|
"bio": "O'Reilly author, software engineer & traveller. Founder of https://clearbit.com",
|
||||||
|
"followers": 15248,
|
||||||
|
"following": 1711,
|
||||||
|
"location": "San Francisco",
|
||||||
|
"site": "http://alexmaccaw.com",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/1826201101/297606_10150904890650705_570400704_21211347_1883468370_n.jpeg"
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "pub/alex-maccaw/78/929/ab5"
|
||||||
|
},
|
||||||
|
"googleplus": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"angellist": {
|
||||||
|
"handle": "maccaw",
|
||||||
|
"bio": "O'Reilly author, engineer & traveller. Mostly harmless.",
|
||||||
|
"blog": "http://blog.alexmaccaw.com",
|
||||||
|
"site": "http://alexmaccaw.com",
|
||||||
|
"followers": 532,
|
||||||
|
"avatar": "https://d1qb2nb5cznatu.cloudfront.net/users/403357-medium_jpg?1405661263"
|
||||||
|
},
|
||||||
|
"aboutme": {
|
||||||
|
"handle": "maccaw",
|
||||||
|
"bio": "Software engineer & traveller. Walker, skier, reader, tennis player, breather, ginger beer drinker, scooterer & generally enjoying things :)",
|
||||||
|
"avatar": "http://o.aolcdn.com/dims-global/dims/ABOUTME/5/803/408/80/http://d3mod6n032mdiz.cloudfront.net/thumb2/m/a/c/maccaw/maccaw-840x560.jpg"
|
||||||
|
},
|
||||||
|
"gravatar": {
|
||||||
|
"handle": "maccman",
|
||||||
|
"urls": [
|
||||||
|
{
|
||||||
|
"value": "http://alexmaccaw.com",
|
||||||
|
"title": "Personal Website"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"avatar": "http://2.gravatar.com/avatar/994909da96d3afaf4daaf54973914b64",
|
||||||
|
"avatars": [
|
||||||
|
{
|
||||||
|
"url": "http://2.gravatar.com/avatar/994909da96d3afaf4daaf54973914b64",
|
||||||
|
"type": "thumbnail"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fuzzy": false
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"id": "027b0d40-016c-40ea-8925-a076fa640992",
|
||||||
|
"name": "Uber",
|
||||||
|
"legalName": "Uber, Inc.",
|
||||||
|
"domain": "uber.com",
|
||||||
|
"domainAliases": [],
|
||||||
|
"url": "http://uber.com",
|
||||||
|
"site": {
|
||||||
|
"url": "http://uber.com",
|
||||||
|
"title": null,
|
||||||
|
"h1": null,
|
||||||
|
"metaDescription": null,
|
||||||
|
"metaAuthor": null,
|
||||||
|
"phoneNumbers": [
|
||||||
|
"+1 877-223-8023"
|
||||||
|
],
|
||||||
|
"emailAddresses": [
|
||||||
|
"team@uber.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Transportation",
|
||||||
|
"Design",
|
||||||
|
"SEO",
|
||||||
|
"Automotive",
|
||||||
|
"Real Time",
|
||||||
|
"Limousines",
|
||||||
|
"Public Transportation",
|
||||||
|
"Transport"
|
||||||
|
],
|
||||||
|
"description": "Uber is a mobile app connecting passengers with drivers for hire.",
|
||||||
|
"foundedDate": "2009-03-01",
|
||||||
|
"location": "1455 Market Street, San Francisco, CA 94103, USA",
|
||||||
|
"timeZone": "America/Los_Angeles",
|
||||||
|
"utcOffset": -8,
|
||||||
|
"geo": {
|
||||||
|
"streetNumber": "1455",
|
||||||
|
"streetName": "Market Street",
|
||||||
|
"subPremise": null,
|
||||||
|
"city": "San Francisco",
|
||||||
|
"state": "California",
|
||||||
|
"stateCode": "CA",
|
||||||
|
"postalCode": "94103",
|
||||||
|
"country": "United States",
|
||||||
|
"countryCode": "US",
|
||||||
|
"lat": 37.7752315,
|
||||||
|
"lng": -122.4175567
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"raised": 5900000000,
|
||||||
|
"employees": 3250,
|
||||||
|
"googleRank": 7,
|
||||||
|
"alexaUsRank": 649,
|
||||||
|
"alexaGlobalRank": 1071,
|
||||||
|
"marketCap": null,
|
||||||
|
"annualRevenue": null
|
||||||
|
},
|
||||||
|
"logo": "https://dqus23xyrtg1i.cloudfront.net/v1/logos/027b0d40-016c-40ea-8925-a076fa640992",
|
||||||
|
"facebook": {
|
||||||
|
"handle": "uber.IND"
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "company/uber.com"
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "uber",
|
||||||
|
"id": 19103481,
|
||||||
|
"bio": "Everyone's Private Driver. Question, concern or praise? Tweet at your local community manager here: https://t.co/EUiTjLk0xj",
|
||||||
|
"followers": 176582,
|
||||||
|
"following": 330,
|
||||||
|
"location": "Global",
|
||||||
|
"site": "http://t.co/PtMbwFTeQA",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/378800000762572812/91ea09a6535666e18ca3c56f731f67ef_normal.jpeg"
|
||||||
|
},
|
||||||
|
"angellist": {
|
||||||
|
"id": 19163,
|
||||||
|
"handle": "uber",
|
||||||
|
"description": "Request a car from any mobile phone via text message, iPhone and Android apps. Within minutes, a professional driver in a sleek black car will arrive curbside. Automatically charged to your credit card on file, tip included.",
|
||||||
|
"followers": 2650,
|
||||||
|
"blogUrl": "http://blog.uber.com/"
|
||||||
|
},
|
||||||
|
"crunchbase": {
|
||||||
|
"handle": "uber"
|
||||||
|
},
|
||||||
|
"phone": "+1 877-223-8023",
|
||||||
|
"emailProvider": false,
|
||||||
|
"type": "private",
|
||||||
|
"tech": [
|
||||||
|
"google_analytics",
|
||||||
|
"double_click",
|
||||||
|
"mixpanel",
|
||||||
|
"optimizely",
|
||||||
|
"typekit_by_adobe",
|
||||||
|
"nginx",
|
||||||
|
"google_apps"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
196
test/fixtures/clearbit/me2@example.com.json
vendored
Normal file
196
test/fixtures/clearbit/me2@example.com.json
vendored
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
{
|
||||||
|
"person": {
|
||||||
|
"id": "4db7cfeb-8017-4aac-b4b9-debb6d3142c0",
|
||||||
|
"name": {
|
||||||
|
"fullName": "Martini Edenhofer",
|
||||||
|
"givenName": "Martini",
|
||||||
|
"familyName": "Edenhofer"
|
||||||
|
},
|
||||||
|
"email": "me2@otrs.org",
|
||||||
|
"gender": null,
|
||||||
|
"location": "Berlin, Berlin, DE",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"city": "Berlin",
|
||||||
|
"state": "Berlin",
|
||||||
|
"stateCode": "Berlin",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 52.52000659999999,
|
||||||
|
"lng": 13.404954
|
||||||
|
},
|
||||||
|
"bio": "Open Source professional and geek. Also known as OTRS inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
|
||||||
|
"site": "http://edenhofer.de/",
|
||||||
|
"avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/4db7cfeb-8017-4aac-b4b9-debb6d3142c0",
|
||||||
|
"employment": {
|
||||||
|
"domain": "otrs.org",
|
||||||
|
"name": "OTRS",
|
||||||
|
"title": "CEO",
|
||||||
|
"role": null,
|
||||||
|
"seniority": "executive"
|
||||||
|
},
|
||||||
|
"facebook": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"github": {
|
||||||
|
"handle": null,
|
||||||
|
"id": null,
|
||||||
|
"avatar": null,
|
||||||
|
"company": null,
|
||||||
|
"blog": null,
|
||||||
|
"followers": null,
|
||||||
|
"following": null
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "medenhofer",
|
||||||
|
"id": 219826253,
|
||||||
|
"bio": "Open Source professional and geek. Also known as OTRS inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
|
||||||
|
"followers": 215,
|
||||||
|
"following": 260,
|
||||||
|
"statuses": 114,
|
||||||
|
"favorites": 8,
|
||||||
|
"location": "",
|
||||||
|
"site": "http://edenhofer.de/",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/1216362658/DSC_0084-p.jpg"
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "in/enjoyme"
|
||||||
|
},
|
||||||
|
"googleplus": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"aboutme": {
|
||||||
|
"handle": null,
|
||||||
|
"bio": null,
|
||||||
|
"avatar": null
|
||||||
|
},
|
||||||
|
"gravatar": {
|
||||||
|
"handle": "bazzi",
|
||||||
|
"urls": [
|
||||||
|
{
|
||||||
|
"value": "http://edenhofer.de",
|
||||||
|
"title": "Blog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "http://znuny.com",
|
||||||
|
"title": "Znuny - OTRS related services"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"avatar": "http://2.gravatar.com/avatar/0e321a416c45d214d1040a7667cb0b54",
|
||||||
|
"avatars": [
|
||||||
|
{
|
||||||
|
"url": "http://2.gravatar.com/avatar/0e321a416c45d214d1040a7667cb0b54",
|
||||||
|
"type": "thumbnail"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fuzzy": false
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"id": "2b30663f-f1a4-47a9-b2a9-0817b8d3ae7b",
|
||||||
|
"name": "OTRS",
|
||||||
|
"legalName": "OTRS AG",
|
||||||
|
"domain": "otrs.com",
|
||||||
|
"domainAliases": [
|
||||||
|
"otrs.org"
|
||||||
|
],
|
||||||
|
"url": "http://otrs.com",
|
||||||
|
"site": {
|
||||||
|
"url": "http://otrs.com",
|
||||||
|
"title": "OTRS Simple Service Management",
|
||||||
|
"h1": "What is OTRS?",
|
||||||
|
"metaDescription": "OTRS is an Open Source helpdesk software and an IT Service Management software free of licence costs. Improve your Customer Service Management with OTRS.",
|
||||||
|
"metaAuthor": null,
|
||||||
|
"phoneNumbers": [
|
||||||
|
"+49 6172 681988",
|
||||||
|
"+1 408-549-1717",
|
||||||
|
"+49 5255 11689664",
|
||||||
|
"+49 6032 0355578",
|
||||||
|
"+49 9421 568181",
|
||||||
|
"+1 408-512-1748",
|
||||||
|
"+49 8523 6901503",
|
||||||
|
"+49 6032 7258038",
|
||||||
|
"+49 6032 0355568",
|
||||||
|
"+49 551 141308205"
|
||||||
|
],
|
||||||
|
"emailAddresses": [
|
||||||
|
"sales@otrs.com",
|
||||||
|
"otrs-demo@otrs.org",
|
||||||
|
"itsm-demo@otrs.org",
|
||||||
|
"security@otrs.org",
|
||||||
|
"investor-relations@otrs.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"sector": "Information Technology",
|
||||||
|
"industryGroup": "Software & Services",
|
||||||
|
"industry": "Internet Software & Services",
|
||||||
|
"subIndustry": "Internet Software & Services"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Information Technology & Services",
|
||||||
|
"Technology",
|
||||||
|
"Software"
|
||||||
|
],
|
||||||
|
"description": "OTRS is an Open Source helpdesk software and an IT Service Management software free of licence costs. Improve your Customer Service Management with OTRS.",
|
||||||
|
"foundedDate": null,
|
||||||
|
"location": "Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"streetNumber": "1",
|
||||||
|
"streetName": "Norsk-Data-Straße",
|
||||||
|
"subPremise": null,
|
||||||
|
"city": "Bad Homburg vor der Höhe",
|
||||||
|
"postalCode": "61352",
|
||||||
|
"state": "Hessen",
|
||||||
|
"stateCode": "HE",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 50.21093,
|
||||||
|
"lng": 8.652809999999999
|
||||||
|
},
|
||||||
|
"logo": "https://logo.clearbit.com/otrs.com",
|
||||||
|
"facebook": {
|
||||||
|
"handle": "otrsgroup"
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "company/otrs-ag"
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "OTRSGroup",
|
||||||
|
"id": "126673991",
|
||||||
|
"bio": "OTRS is the leading open source service management software including Help Desk and ITIL V3-certified IT service management (ITSM).",
|
||||||
|
"followers": 2988,
|
||||||
|
"following": 2484,
|
||||||
|
"location": "Cupertino, CA, Bad Homburg",
|
||||||
|
"site": "http://t.co/F09dcTEScJ",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/575314188848889856/F4KWmvVX_normal.png"
|
||||||
|
},
|
||||||
|
"crunchbase": {
|
||||||
|
"handle": "organization/otrs"
|
||||||
|
},
|
||||||
|
"emailProvider": false,
|
||||||
|
"type": "private",
|
||||||
|
"ticker": null,
|
||||||
|
"phone": null,
|
||||||
|
"metrics": {
|
||||||
|
"alexaUsRank": null,
|
||||||
|
"alexaGlobalRank": 116381,
|
||||||
|
"googleRank": 0,
|
||||||
|
"employees": 15,
|
||||||
|
"marketCap": null,
|
||||||
|
"raised": null,
|
||||||
|
"annualRevenue": null
|
||||||
|
},
|
||||||
|
"tech": [
|
||||||
|
"google_analytics",
|
||||||
|
"double_click",
|
||||||
|
"google_adwords",
|
||||||
|
"optimizely",
|
||||||
|
"wordpress",
|
||||||
|
"pardot"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
196
test/fixtures/clearbit/me@example.com.json
vendored
Normal file
196
test/fixtures/clearbit/me@example.com.json
vendored
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
{
|
||||||
|
"person": {
|
||||||
|
"id": "4db7cfeb-8017-4aac-b4b9-debb6d3142c0",
|
||||||
|
"name": {
|
||||||
|
"fullName": "Martin Edenhofer",
|
||||||
|
"givenName": "Martin",
|
||||||
|
"familyName": "Edenhofer"
|
||||||
|
},
|
||||||
|
"email": "me@otrs.org",
|
||||||
|
"gender": null,
|
||||||
|
"location": "Berlin, Berlin, DE",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"city": "Berlin",
|
||||||
|
"state": "Berlin",
|
||||||
|
"stateCode": "Berlin",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 52.52000659999999,
|
||||||
|
"lng": 13.404954
|
||||||
|
},
|
||||||
|
"bio": "Open Source professional and geek. Also known as OTRS inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
|
||||||
|
"site": "http://edenhofer.de/",
|
||||||
|
"avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/4db7cfeb-8017-4aac-b4b9-debb6d3142c0",
|
||||||
|
"employment": {
|
||||||
|
"domain": "otrs.org",
|
||||||
|
"name": "OTRS",
|
||||||
|
"title": "CEO",
|
||||||
|
"role": null,
|
||||||
|
"seniority": "executive"
|
||||||
|
},
|
||||||
|
"facebook": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"github": {
|
||||||
|
"handle": null,
|
||||||
|
"id": null,
|
||||||
|
"avatar": null,
|
||||||
|
"company": null,
|
||||||
|
"blog": null,
|
||||||
|
"followers": null,
|
||||||
|
"following": null
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "medenhofer",
|
||||||
|
"id": 219826253,
|
||||||
|
"bio": "Open Source professional and geek. Also known as OTRS inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
|
||||||
|
"followers": 215,
|
||||||
|
"following": 260,
|
||||||
|
"statuses": 114,
|
||||||
|
"favorites": 8,
|
||||||
|
"location": "",
|
||||||
|
"site": "http://edenhofer.de/",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/1216362658/DSC_0084-p.jpg"
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "in/enjoyme"
|
||||||
|
},
|
||||||
|
"googleplus": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"aboutme": {
|
||||||
|
"handle": null,
|
||||||
|
"bio": null,
|
||||||
|
"avatar": null
|
||||||
|
},
|
||||||
|
"gravatar": {
|
||||||
|
"handle": "bazzi",
|
||||||
|
"urls": [
|
||||||
|
{
|
||||||
|
"value": "http://edenhofer.de",
|
||||||
|
"title": "Blog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "http://znuny.com",
|
||||||
|
"title": "Znuny - OTRS related services"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"avatar": "http://2.gravatar.com/avatar/0e321a416c45d214d1040a7667cb0b54",
|
||||||
|
"avatars": [
|
||||||
|
{
|
||||||
|
"url": "http://2.gravatar.com/avatar/0e321a416c45d214d1040a7667cb0b54",
|
||||||
|
"type": "thumbnail"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fuzzy": false
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"id": "2b30663f-f1a4-47a9-b2a9-0817b8d3ae7b",
|
||||||
|
"name": "OTRS",
|
||||||
|
"legalName": null,
|
||||||
|
"domain": "otrs.com",
|
||||||
|
"domainAliases": [
|
||||||
|
"otrs.org"
|
||||||
|
],
|
||||||
|
"url": "http://otrs.com",
|
||||||
|
"site": {
|
||||||
|
"url": "http://otrs.com",
|
||||||
|
"title": "OTRS Simple Service Management",
|
||||||
|
"h1": "What is OTRS?",
|
||||||
|
"metaDescription": "OTRS is an Open Source helpdesk software and an IT Service Management software free of licence costs. Improve your Customer Service Management with OTRS.",
|
||||||
|
"metaAuthor": null,
|
||||||
|
"phoneNumbers": [
|
||||||
|
"+49 6172 681988",
|
||||||
|
"+1 408-549-1717",
|
||||||
|
"+49 5255 11689664",
|
||||||
|
"+49 6032 0355578",
|
||||||
|
"+49 9421 568181",
|
||||||
|
"+1 408-512-1748",
|
||||||
|
"+49 8523 6901503",
|
||||||
|
"+49 6032 7258038",
|
||||||
|
"+49 6032 0355568",
|
||||||
|
"+49 551 141308205"
|
||||||
|
],
|
||||||
|
"emailAddresses": [
|
||||||
|
"sales@otrs.com",
|
||||||
|
"otrs-demo@otrs.org",
|
||||||
|
"itsm-demo@otrs.org",
|
||||||
|
"security@otrs.org",
|
||||||
|
"investor-relations@otrs.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"sector": "Information Technology",
|
||||||
|
"industryGroup": "Software & Services",
|
||||||
|
"industry": "Internet Software & Services",
|
||||||
|
"subIndustry": "Internet Software & Services"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Information Technology & Services",
|
||||||
|
"Technology",
|
||||||
|
"Software"
|
||||||
|
],
|
||||||
|
"description": "OTRS is an Open Source helpdesk software and an IT Service Management software free of licence costs. Improve your Customer Service Management with OTRS.",
|
||||||
|
"foundedDate": null,
|
||||||
|
"location": "Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"streetNumber": "1",
|
||||||
|
"streetName": "Norsk-Data-Straße",
|
||||||
|
"subPremise": null,
|
||||||
|
"city": "Bad Homburg vor der Höhe",
|
||||||
|
"postalCode": "61352",
|
||||||
|
"state": "Hessen",
|
||||||
|
"stateCode": "HE",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 50.21093,
|
||||||
|
"lng": 8.652809999999999
|
||||||
|
},
|
||||||
|
"logo": "https://logo.clearbit.com/otrs.com",
|
||||||
|
"facebook": {
|
||||||
|
"handle": "otrsgroup"
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "company/otrs-ag"
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "OTRSGroup",
|
||||||
|
"id": "126673991",
|
||||||
|
"bio": "OTRS is the leading open source service management software including Help Desk and ITIL V3-certified IT service management (ITSM).",
|
||||||
|
"followers": 2988,
|
||||||
|
"following": 2484,
|
||||||
|
"location": "Cupertino, CA, Bad Homburg",
|
||||||
|
"site": "http://t.co/F09dcTEScJ",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/575314188848889856/F4KWmvVX_normal.png"
|
||||||
|
},
|
||||||
|
"crunchbase": {
|
||||||
|
"handle": "organization/otrs"
|
||||||
|
},
|
||||||
|
"emailProvider": false,
|
||||||
|
"type": "private",
|
||||||
|
"ticker": null,
|
||||||
|
"phone": null,
|
||||||
|
"metrics": {
|
||||||
|
"alexaUsRank": null,
|
||||||
|
"alexaGlobalRank": 116381,
|
||||||
|
"googleRank": 0,
|
||||||
|
"employees": 15,
|
||||||
|
"marketCap": null,
|
||||||
|
"raised": null,
|
||||||
|
"annualRevenue": null
|
||||||
|
},
|
||||||
|
"tech": [
|
||||||
|
"google_analytics",
|
||||||
|
"double_click",
|
||||||
|
"google_adwords",
|
||||||
|
"optimizely",
|
||||||
|
"wordpress",
|
||||||
|
"pardot"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
96
test/fixtures/clearbit/testing4@znuny.com.json
vendored
Normal file
96
test/fixtures/clearbit/testing4@znuny.com.json
vendored
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"person": null,
|
||||||
|
"company": {
|
||||||
|
"id": "273d8666-9d70-43dc-836b-a47a88293905",
|
||||||
|
"name": "Znuny / ES for OTRS",
|
||||||
|
"legalName": null,
|
||||||
|
"domain": "znuny.com",
|
||||||
|
"domainAliases": [
|
||||||
|
"znuny.de"
|
||||||
|
],
|
||||||
|
"url": "http://znuny.com",
|
||||||
|
"site": {
|
||||||
|
"url": "http://znuny.com",
|
||||||
|
"title": "Support, Consulting, Development and Training for OTRS - Znuny GmbH",
|
||||||
|
"h1": "We make OTRS support easy!",
|
||||||
|
"metaDescription": "OTRS Support, Consulting, Development, Training and Customizing - Znuny GmbH",
|
||||||
|
"metaAuthor": null,
|
||||||
|
"phoneNumbers": [
|
||||||
|
"+49 30 6098541",
|
||||||
|
"+49 4107 15880339",
|
||||||
|
"+49 8601 81017925",
|
||||||
|
"+49 4107 15880186",
|
||||||
|
"+49 8602 16139061"
|
||||||
|
],
|
||||||
|
"emailAddresses": [
|
||||||
|
"info@znuny.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"sector": "Industrials",
|
||||||
|
"industryGroup": "Commercial & Professional Services",
|
||||||
|
"industry": "Professional Services",
|
||||||
|
"subIndustry": "Consulting"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Consulting & Professional Services",
|
||||||
|
"Corporate & Business",
|
||||||
|
"Information Technology & Services"
|
||||||
|
],
|
||||||
|
"description": "OTRS Support, Consulting, Development, Training and Customizing - Znuny GmbH",
|
||||||
|
"foundedDate": null,
|
||||||
|
"location": "Marienstraße 11, 10117 Berlin, Germany",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"streetNumber": "11",
|
||||||
|
"streetName": "Marienstraße",
|
||||||
|
"subPremise": null,
|
||||||
|
"city": "Berlin",
|
||||||
|
"postalCode": "10117",
|
||||||
|
"state": "Berlin",
|
||||||
|
"stateCode": "Berlin",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 52.52182,
|
||||||
|
"lng": 13.38268
|
||||||
|
},
|
||||||
|
"logo": "https://logo.clearbit.com/znuny.com",
|
||||||
|
"facebook": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "company/znuny-gmbh"
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "znuny",
|
||||||
|
"id": "293437546",
|
||||||
|
"bio": "Enterprise Services for OTRS! We love to do what we can do!",
|
||||||
|
"followers": 85,
|
||||||
|
"following": 63,
|
||||||
|
"location": "Berlin",
|
||||||
|
"site": "http://t.co/miuzrhoHeG",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/2460325455/hix7so4b0h0miq9gwkw8_normal.png"
|
||||||
|
},
|
||||||
|
"crunchbase": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"emailProvider": false,
|
||||||
|
"type": "private",
|
||||||
|
"ticker": null,
|
||||||
|
"phone": null,
|
||||||
|
"metrics": {
|
||||||
|
"alexaUsRank": null,
|
||||||
|
"alexaGlobalRank": 10086408,
|
||||||
|
"googleRank": 3,
|
||||||
|
"employees": null,
|
||||||
|
"marketCap": null,
|
||||||
|
"raised": null,
|
||||||
|
"annualRevenue": null
|
||||||
|
},
|
||||||
|
"tech": [
|
||||||
|
"google_analytics",
|
||||||
|
"ruby_on_rails"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
120
test/fixtures/clearbit/testing5@znuny.com.json
vendored
Normal file
120
test/fixtures/clearbit/testing5@znuny.com.json
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
{
|
||||||
|
"person": {
|
||||||
|
"id": "4db7cfeb-8017-4aac-b4b9-debb6d3142c0-1",
|
||||||
|
"name": {
|
||||||
|
"fullName": "Bob Smith",
|
||||||
|
"givenName": "Bob",
|
||||||
|
"familyName": "Smith"
|
||||||
|
},
|
||||||
|
"email": "testing5@znuny.com",
|
||||||
|
"gender": null,
|
||||||
|
"location": "Berlin, Berlin, DE",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"city": "Berlin",
|
||||||
|
"state": "Berlin",
|
||||||
|
"stateCode": "Berlin",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 52.52000659999999,
|
||||||
|
"lng": 13.404954
|
||||||
|
},
|
||||||
|
"bio": "some_bio",
|
||||||
|
"site": "http://example.com/",
|
||||||
|
"avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/4db7cfeb-8017-4aac-b4b9-debb6d3142c0"
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"id": "273d8666-9d70-43dc-836b-a47a88293905",
|
||||||
|
"name": "Znuny2",
|
||||||
|
"legalName": null,
|
||||||
|
"domain": "znuny.com",
|
||||||
|
"domainAliases": [
|
||||||
|
"znuny.de"
|
||||||
|
],
|
||||||
|
"url": "http://znuny.com",
|
||||||
|
"site": {
|
||||||
|
"url": "http://znuny.com",
|
||||||
|
"title": "Support, Consulting, Development and Training for OTRS - Znuny GmbH",
|
||||||
|
"h1": "We make OTRS support easy!",
|
||||||
|
"metaDescription": "OTRS Support, Consulting, Development, Training and Customizing - Znuny GmbH",
|
||||||
|
"metaAuthor": null,
|
||||||
|
"phoneNumbers": [
|
||||||
|
"+49 30 6098541",
|
||||||
|
"+49 4107 15880339",
|
||||||
|
"+49 8601 81017925",
|
||||||
|
"+49 4107 15880186",
|
||||||
|
"+49 8602 16139061"
|
||||||
|
],
|
||||||
|
"emailAddresses": [
|
||||||
|
"info@znuny.com"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"sector": "Industrials",
|
||||||
|
"industryGroup": "Commercial & Professional Services",
|
||||||
|
"industry": "Professional Services",
|
||||||
|
"subIndustry": "Consulting"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Consulting & Professional Services",
|
||||||
|
"Corporate & Business",
|
||||||
|
"Information Technology & Services"
|
||||||
|
],
|
||||||
|
"description": "Znuny2 GmbH",
|
||||||
|
"foundedDate": null,
|
||||||
|
"location": "Marienstraße 11, 10117 Berlin, Germany",
|
||||||
|
"timeZone": "Europe/Berlin",
|
||||||
|
"utcOffset": 2,
|
||||||
|
"geo": {
|
||||||
|
"streetNumber": "11",
|
||||||
|
"streetName": "Marienstraße",
|
||||||
|
"subPremise": null,
|
||||||
|
"city": "Berlin",
|
||||||
|
"postalCode": "10117",
|
||||||
|
"state": "Berlin",
|
||||||
|
"stateCode": "Berlin",
|
||||||
|
"country": "Germany",
|
||||||
|
"countryCode": "DE",
|
||||||
|
"lat": 52.52182,
|
||||||
|
"lng": 13.38268
|
||||||
|
},
|
||||||
|
"logo": "https://logo.clearbit.com/znuny.com",
|
||||||
|
"facebook": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"linkedin": {
|
||||||
|
"handle": "company/znuny-gmbh"
|
||||||
|
},
|
||||||
|
"twitter": {
|
||||||
|
"handle": "znuny",
|
||||||
|
"id": "293437546",
|
||||||
|
"bio": "Enterprise Services for OTRS! We love to do what we can do!",
|
||||||
|
"followers": 85,
|
||||||
|
"following": 63,
|
||||||
|
"location": "Berlin",
|
||||||
|
"site": "http://t.co/miuzrhoHeG",
|
||||||
|
"avatar": "https://pbs.twimg.com/profile_images/2460325455/hix7so4b0h0miq9gwkw8_normal.png"
|
||||||
|
},
|
||||||
|
"crunchbase": {
|
||||||
|
"handle": null
|
||||||
|
},
|
||||||
|
"emailProvider": false,
|
||||||
|
"type": "private",
|
||||||
|
"ticker": null,
|
||||||
|
"phone": null,
|
||||||
|
"metrics": {
|
||||||
|
"alexaUsRank": null,
|
||||||
|
"alexaGlobalRank": 10086408,
|
||||||
|
"googleRank": 3,
|
||||||
|
"employees": null,
|
||||||
|
"marketCap": null,
|
||||||
|
"raised": null,
|
||||||
|
"annualRevenue": null
|
||||||
|
},
|
||||||
|
"tech": [
|
||||||
|
"google_analytics",
|
||||||
|
"ruby_on_rails"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
281
test/integration/clearbit_test.rb
Normal file
281
test/integration/clearbit_test.rb
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'integration_test_helper'
|
||||||
|
|
||||||
|
class ClearbitTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
|
# check
|
||||||
|
test 'base' do
|
||||||
|
if !ENV['CLEARBIT_CI_API_KEY']
|
||||||
|
raise "ERROR: Need CLEARBIT_CI_API_KEY - hint CLEARBIT_CI_API_KEY='abc...'"
|
||||||
|
end
|
||||||
|
|
||||||
|
# set system mode to done / to activate
|
||||||
|
Setting.set('system_init_done', true)
|
||||||
|
|
||||||
|
Setting.set('clearbit_integration', true)
|
||||||
|
Setting.set('clearbit_config', {
|
||||||
|
api_key: ENV['CLEARBIT_CI_API_KEY'],
|
||||||
|
organization_autocreate: true,
|
||||||
|
organization_shared: false,
|
||||||
|
user_sync: {
|
||||||
|
'person.name.givenName' => 'user.firstname',
|
||||||
|
'person.name.familyName' => 'user.lastname',
|
||||||
|
'person.email' => 'user.email',
|
||||||
|
'person.bio' => 'user.note',
|
||||||
|
'company.url' => 'user.web',
|
||||||
|
'person.site' => 'user.web',
|
||||||
|
'company.location' => 'user.address',
|
||||||
|
'person.location' => 'user.address',
|
||||||
|
#'person.timeZone' => 'user.preferences[:timezone]',
|
||||||
|
#'person.gender' => 'user.preferences[:gender]',
|
||||||
|
},
|
||||||
|
organization_sync: {
|
||||||
|
'company.legalName' => 'organization.name',
|
||||||
|
'company.name' => 'organization.name',
|
||||||
|
'company.description' => 'organization.note',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
# case 1 - person + company (demo data set)
|
||||||
|
customer1 = User.create(
|
||||||
|
firstname: '',
|
||||||
|
lastname: 'Should be still there',
|
||||||
|
email: 'alex@alexmaccaw.com',
|
||||||
|
note: '',
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(customer1)
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'User', o_id: customer1.id))
|
||||||
|
|
||||||
|
customer1_lookup = User.lookup(id: customer1.id)
|
||||||
|
|
||||||
|
assert_equal('Alex', customer1_lookup.firstname)
|
||||||
|
assert_equal('Should be still there', customer1_lookup.lastname)
|
||||||
|
assert_equal('O\'Reilly author, software engineer & traveller. Founder of https://clearbit.com', customer1_lookup.note)
|
||||||
|
assert_equal('1455 Market Street, San Francisco, CA 94103, USA', customer1_lookup.address)
|
||||||
|
|
||||||
|
organization1_lookup = Organization.find_by(name: 'Uber, Inc.')
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization1_lookup.id))
|
||||||
|
assert_equal(false, organization1_lookup.shared)
|
||||||
|
assert_equal('Uber is a mobile app connecting passengers with drivers for hire.', organization1_lookup.note)
|
||||||
|
|
||||||
|
# case 2 - person + company
|
||||||
|
customer2 = User.create(
|
||||||
|
firstname: '',
|
||||||
|
lastname: '',
|
||||||
|
email: 'me@example.com',
|
||||||
|
note: '',
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(customer2)
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'User', o_id: customer2.id))
|
||||||
|
|
||||||
|
customer2_lookup = User.lookup(id: customer2.id)
|
||||||
|
|
||||||
|
assert_equal('Martin', customer2_lookup.firstname)
|
||||||
|
assert_equal('Edenhofer', customer2_lookup.lastname)
|
||||||
|
assert_equal("Open Source professional and geek. Also known as OTRS inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.", customer2_lookup.note)
|
||||||
|
assert_equal('Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany', customer2_lookup.address)
|
||||||
|
|
||||||
|
organization2_lookup = Organization.find_by(name: 'OTRS')
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization2_lookup.id))
|
||||||
|
assert_equal(false, organization2_lookup.shared)
|
||||||
|
assert_equal('OTRS is an Open Source helpdesk software and an IT Service Management software free of licence costs. Improve your Customer Service Management with OTRS.', organization2_lookup.note)
|
||||||
|
|
||||||
|
# update with own values (do not overwrite)
|
||||||
|
customer2.update_attributes(
|
||||||
|
firstname: 'Martini',
|
||||||
|
note: 'changed by my self',
|
||||||
|
)
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'User', o_id: customer2.id))
|
||||||
|
|
||||||
|
customer2_lookup = User.lookup(id: customer2.id)
|
||||||
|
|
||||||
|
assert_equal('Martini', customer2_lookup.firstname)
|
||||||
|
assert_equal('Edenhofer', customer2_lookup.lastname)
|
||||||
|
assert_equal('changed by my self', customer2_lookup.note)
|
||||||
|
assert_equal('Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany', customer2_lookup.address)
|
||||||
|
|
||||||
|
Transaction::ClearbitEnrichment.sync_user(customer2)
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
customer2_lookup = User.lookup(id: customer2.id)
|
||||||
|
|
||||||
|
assert_equal('Martini', customer2_lookup.firstname)
|
||||||
|
assert_equal('Edenhofer', customer2_lookup.lastname)
|
||||||
|
assert_equal('changed by my self', customer2_lookup.note)
|
||||||
|
assert_equal('Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany', customer2_lookup.address)
|
||||||
|
|
||||||
|
# update with own values (do not overwrite)
|
||||||
|
customer2.update_attributes(
|
||||||
|
firstname: '',
|
||||||
|
note: 'changed by my self',
|
||||||
|
)
|
||||||
|
|
||||||
|
Transaction::ClearbitEnrichment.sync_user(customer2)
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
customer2_lookup = User.lookup(id: customer2.id)
|
||||||
|
|
||||||
|
assert_equal('Martin', customer2_lookup.firstname)
|
||||||
|
assert_equal('Edenhofer', customer2_lookup.lastname)
|
||||||
|
assert_equal('changed by my self', customer2_lookup.note)
|
||||||
|
assert_equal('Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany', customer2_lookup.address)
|
||||||
|
|
||||||
|
# update with changed values at clearbit site (do overwrite)
|
||||||
|
customer2.update_attributes(
|
||||||
|
email: 'me2@example.com',
|
||||||
|
)
|
||||||
|
|
||||||
|
Transaction::ClearbitEnrichment.sync_user(customer2)
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
customer2_lookup = User.lookup(id: customer2.id)
|
||||||
|
|
||||||
|
assert_equal('Martini', customer2_lookup.firstname)
|
||||||
|
assert_equal('Edenhofer', customer2_lookup.lastname)
|
||||||
|
assert_equal('changed by my self', customer2_lookup.note)
|
||||||
|
assert_equal('Norsk-Data-Straße 1, 61352 Bad Homburg vor der Höhe, Germany', customer2_lookup.address)
|
||||||
|
|
||||||
|
organization2_lookup = Organization.find_by(name: 'OTRS AG')
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization2_lookup.id))
|
||||||
|
assert_equal(false, organization2_lookup.shared)
|
||||||
|
assert_equal('OTRS is an Open Source helpdesk software and an IT Service Management software free of licence costs. Improve your Customer Service Management with OTRS.', organization2_lookup.note)
|
||||||
|
|
||||||
|
# case 3 - no person
|
||||||
|
customer3 = User.create(
|
||||||
|
firstname: '',
|
||||||
|
lastname: '',
|
||||||
|
email: 'testing4@znuny.com',
|
||||||
|
note: '',
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(customer3)
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
assert_not(ExternalSync.find_by(source: 'clearbit', object: 'User', o_id: customer3.id))
|
||||||
|
|
||||||
|
customer3_lookup = User.lookup(id: customer3.id)
|
||||||
|
assert_not_equal(customer3.updated_at, customer3_lookup.updated_at)
|
||||||
|
|
||||||
|
assert_equal('', customer3_lookup.firstname)
|
||||||
|
assert_equal('', customer3_lookup.lastname)
|
||||||
|
assert_equal('', customer3_lookup.note)
|
||||||
|
assert_equal('http://znuny.com', customer3_lookup.web)
|
||||||
|
assert_equal('Marienstraße 11, 10117 Berlin, Germany', customer3_lookup.address)
|
||||||
|
|
||||||
|
organization3_lookup = Organization.find_by(name: 'Znuny / ES for OTRS')
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization3_lookup.id))
|
||||||
|
assert_equal(false, organization3_lookup.shared)
|
||||||
|
assert_equal('OTRS Support, Consulting, Development, Training and Customizing - Znuny GmbH', organization3_lookup.note)
|
||||||
|
|
||||||
|
# case 4 - no person / real api call
|
||||||
|
customer4 = User.create(
|
||||||
|
firstname: '',
|
||||||
|
lastname: '',
|
||||||
|
email: 'testing5@clearbit.com',
|
||||||
|
note: '',
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(customer4)
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
assert_not(ExternalSync.find_by(source: 'clearbit', object: 'User', o_id: customer4.id))
|
||||||
|
|
||||||
|
customer4_lookup = User.lookup(id: customer4.id)
|
||||||
|
assert_not_equal(customer4.updated_at, customer4_lookup.updated_at)
|
||||||
|
|
||||||
|
assert_equal('', customer4_lookup.firstname)
|
||||||
|
assert_equal('', customer4_lookup.lastname)
|
||||||
|
assert_equal('', customer4_lookup.note)
|
||||||
|
assert_equal('http://clearbit.com', customer4_lookup.web)
|
||||||
|
assert_equal('', customer4_lookup.address)
|
||||||
|
|
||||||
|
organization4_lookup = Organization.find_by(name: 'Clearbit')
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization4_lookup.id))
|
||||||
|
assert_equal(false, organization4_lookup.shared)
|
||||||
|
assert_equal('Clearbit provides powerful products and data APIs to help your business grow. Contact enrichment, lead generation, financial compliance, and more...', organization4_lookup.note)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# check
|
||||||
|
test 'base with invalid input' do
|
||||||
|
if !ENV['CLEARBIT_CI_API_KEY']
|
||||||
|
raise "ERROR: Need CLEARBIT_CI_API_KEY - hint CLEARBIT_CI_API_KEY='abc...'"
|
||||||
|
end
|
||||||
|
|
||||||
|
# set system mode to done / to activate
|
||||||
|
Setting.set('system_init_done', true)
|
||||||
|
|
||||||
|
Setting.set('clearbit_integration', true)
|
||||||
|
Setting.set('clearbit_config', {
|
||||||
|
api_key: ENV['CLEARBIT_CI_API_KEY'],
|
||||||
|
organization_autocreate: true,
|
||||||
|
organization_shared: true,
|
||||||
|
user_sync: {
|
||||||
|
'person.name.givenName' => 'user.firstname',
|
||||||
|
'person.name.familyName' => 'user.lastname',
|
||||||
|
'person.email' => 'user.email',
|
||||||
|
'person.bio' => 'user.note_not_existing',
|
||||||
|
'company.url' => 'user.web',
|
||||||
|
'person.site' => 'user.web',
|
||||||
|
'company.location' => 'user.address',
|
||||||
|
'person.location' => 'user.address',
|
||||||
|
},
|
||||||
|
organization_sync: {
|
||||||
|
'company.legalName' => 'organization.name',
|
||||||
|
'company.name' => 'organization.name',
|
||||||
|
'company.description' => 'organization.note_not_existing',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
# case 1 - person + company (demo data set)
|
||||||
|
customer1 = User.create(
|
||||||
|
firstname: '',
|
||||||
|
lastname: 'Should be still there',
|
||||||
|
email: 'testing5@znuny.com',
|
||||||
|
note: '',
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert(customer1)
|
||||||
|
|
||||||
|
Observer::Transaction.commit
|
||||||
|
Delayed::Worker.new.work_off
|
||||||
|
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'User', o_id: customer1.id))
|
||||||
|
|
||||||
|
customer1_lookup = User.lookup(id: customer1.id)
|
||||||
|
|
||||||
|
assert_equal('Bob', customer1_lookup.firstname)
|
||||||
|
assert_equal('Should be still there', customer1_lookup.lastname)
|
||||||
|
assert_equal('', customer1_lookup.note)
|
||||||
|
assert_equal('Marienstraße 11, 10117 Berlin, Germany', customer1_lookup.address)
|
||||||
|
|
||||||
|
organization1_lookup = Organization.find_by(name: 'Znuny2')
|
||||||
|
assert(ExternalSync.find_by(source: 'clearbit', object: 'Organization', o_id: organization1_lookup.id))
|
||||||
|
assert_equal(true, organization1_lookup.shared)
|
||||||
|
assert_equal('', organization1_lookup.note)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue