go_import 3.0.19 → 3.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/bin/go-import +1 -1
- data/lib/go_import/email_helper.rb +5 -1
- data/lib/go_import/model/rootmodel.rb +3 -2
- data/sources/salesforce/.go_import/runner.rb +167 -30
- data/sources/salesforce/converter.rb +46 -24
- data/spec/helpers/csv_helper_spec.rb +16 -0
- data/spec/helpers/email_helper_spec.rb +5 -0
- data/spec/rootmodel_spec.rb +15 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NWU4ODY3ZjBlYWZjYTExMzE2NjExMmIxODYzZjZkOWJkODk5MDg3ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWNlYzA4NjJmYmIzNDU1OTZlNzFiZGU1YWExNjYxNTM2MGQyMjUxMg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzJlNjIxOTViMDhhN2Q0ZGVlMDc2YjA0YThkOGUyNjUyY2I2NmVlMDBjNjZj
|
10
|
+
Y2E2NTkzMDQwZjJjNWZkYjUzZmVhMTc5OTBiZDZlZTBjOTA0ZjM4ZWU3MmRh
|
11
|
+
ZDZiMzU0ZDkzZTI4YWQ1NDhkNmY3YTJhOWM2ZmI0YmZlN2U4ZTQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODU4M2I5NmNlOWM5MTM1M2MwMmFhZjYzNDVhMTRlMWIzOTkwNjFmYmNhNjgz
|
14
|
+
YmFjYmQ0NDRkYTkzYTI1ZGQ0ZmM5MTI0YTY4NmEyYTZjYjEwMWYwNDJhMjcx
|
15
|
+
ZDg3Y2UyMDUwMTQ0YTkyZjFhNDI2NGQxZTA1MTM4ZDYwOTQ5MjU=
|
data/bin/go-import
CHANGED
@@ -23,7 +23,7 @@ class GoImportCommandLine < Thor
|
|
23
23
|
puts "\t#{s}"
|
24
24
|
end
|
25
25
|
|
26
|
-
puts "\nCreate a new project with 'go-import new' with one of these sources."
|
26
|
+
puts "\nCreate a new project with 'go-import new <PROJECT> <SOURCE>' with one of these sources."
|
27
27
|
puts "Use 'go-import about <SOURCE>' for more information about a specific source."
|
28
28
|
end
|
29
29
|
|
@@ -4,7 +4,11 @@ module GoImport
|
|
4
4
|
# The EmailHelper helps you validate email addresses.
|
5
5
|
class EmailHelper
|
6
6
|
def self.is_valid?(email)
|
7
|
-
|
7
|
+
begin
|
8
|
+
return (email =~ EmailAddressValidation::Pattern) ? true : false
|
9
|
+
rescue
|
10
|
+
return false
|
11
|
+
end
|
8
12
|
end
|
9
13
|
end
|
10
14
|
end
|
@@ -158,10 +158,11 @@ module GoImport
|
|
158
158
|
|
159
159
|
deal = Deal.new(deal) if !deal.is_a?(Deal)
|
160
160
|
|
161
|
-
if
|
161
|
+
if (!deal.integration_id.nil? && deal.integration_id.length > 0) &&
|
162
|
+
find_deal_by_integration_id(deal.integration_id) != nil
|
162
163
|
raise AlreadyAddedError, "Already added a deal with integration_id #{deal.integration_id}"
|
163
164
|
end
|
164
|
-
|
165
|
+
|
165
166
|
if deal.responsible_coworker.nil?
|
166
167
|
deal.responsible_coworker = @import_coworker
|
167
168
|
end
|
@@ -7,7 +7,8 @@ require_relative("../converter")
|
|
7
7
|
# EXPORT_FOLDER and other constants should be defined ../converter.rb
|
8
8
|
|
9
9
|
USER_FILE = "User.csv"
|
10
|
-
|
10
|
+
ORGANIZATION_ACCOUNT_FILE = "Account.csv"
|
11
|
+
ORGANIZATION_LEAD_FILE = "Lead.csv"
|
11
12
|
PERSON_FILE = "Contact.csv"
|
12
13
|
DEAL_FILE = "Opportunity.csv"
|
13
14
|
NOTE_FILE = "Note.csv"
|
@@ -17,10 +18,10 @@ def process_rows(filename)
|
|
17
18
|
puts "Error: Cant find the file '#{filename}'."
|
18
19
|
raise
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
f = File.open(filename, 'r')
|
22
23
|
data = f.read.encode("UTF-8", "ISO-8859-1")
|
23
|
-
rows = GoImport::CsvHelper::text_to_hashes(data)
|
24
|
+
rows = GoImport::CsvHelper::text_to_hashes(data, ',')
|
24
25
|
rows.each do |row|
|
25
26
|
yield row
|
26
27
|
end
|
@@ -70,7 +71,7 @@ def to_coworker(row)
|
|
70
71
|
if row['IsActive'] == '1' && row['UserType'] == 'Standard'
|
71
72
|
coworker = GoImport::Coworker.new
|
72
73
|
|
73
|
-
coworker.
|
74
|
+
coworker.email = row['Email']
|
74
75
|
coworker.integration_id = row['Id']
|
75
76
|
coworker.first_name = row['FirstName']
|
76
77
|
coworker.last_name = row['LastName']
|
@@ -81,13 +82,14 @@ def to_coworker(row)
|
|
81
82
|
return coworker
|
82
83
|
end
|
83
84
|
|
84
|
-
def
|
85
|
+
def account_to_organization(row, rootmodel)
|
85
86
|
if row['IsDeleted'] != '0'
|
86
87
|
return nil
|
87
88
|
end
|
88
89
|
|
89
90
|
organization = GoImport::Organization.new
|
90
91
|
|
92
|
+
organization.relation = GoImport::Relation::IsACustomer
|
91
93
|
organization.integration_id = row['Id']
|
92
94
|
organization.name = row['Name']
|
93
95
|
organization.set_tag(row['Type'])
|
@@ -99,42 +101,134 @@ def to_organization(row, rootmodel)
|
|
99
101
|
address.street = row['BillingStreet']
|
100
102
|
address.zip_code = row['BillingPostalCode']
|
101
103
|
address.city = row['BillingCity']
|
102
|
-
address.country_code = row['BillingCountry']
|
104
|
+
address.country_code = get_country_code(row['BillingCountry'])
|
103
105
|
end
|
104
106
|
|
105
107
|
organization.with_visit_address do |address|
|
106
108
|
address.street = row['ShippingStreet']
|
107
109
|
address.zip_code = row['ShippingPostalCode']
|
108
110
|
address.city = row['ShippingCity']
|
109
|
-
address.country_code = row['ShippingCountry']
|
111
|
+
address.country_code = get_country_code(row['ShippingCountry'])
|
110
112
|
end
|
111
113
|
|
114
|
+
organization.set_tag row['Industry']
|
115
|
+
|
112
116
|
organization.responsible_coworker =
|
113
117
|
rootmodel.find_coworker_by_integration_id(row['OwnerId'])
|
114
118
|
|
115
119
|
return organization
|
116
120
|
end
|
117
121
|
|
118
|
-
def
|
119
|
-
if row['IsDeleted']
|
120
|
-
|
122
|
+
def lead_to_organization(row, rootmodel, converter)
|
123
|
+
if row['IsDeleted'] != '0'
|
124
|
+
return nil
|
125
|
+
end
|
126
|
+
|
127
|
+
if row['IsConverted'] == '1'
|
128
|
+
return nil
|
129
|
+
end
|
130
|
+
|
131
|
+
organization = GoImport::Organization.new
|
132
|
+
|
133
|
+
if converter.respond_to?(:get_relation_for_lead)
|
134
|
+
relation = converter.get_relation_for_lead
|
135
|
+
|
136
|
+
if !relation.nil?
|
137
|
+
organization.relation = relation
|
138
|
+
else
|
139
|
+
organization.relation = GoImport::Relation::WorkingOnIt
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
use_default_lead_tag = true
|
144
|
+
if converter.respond_to?(:get_tags_for_lead)
|
145
|
+
tags = converter.get_tags_for_lead(row['Status'])
|
121
146
|
|
122
|
-
if !
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
person.mobile_phone_number = row['MobilePhone']
|
133
|
-
person.home_phone_number = row['HomePhone']
|
134
|
-
person.position = row['Title']
|
135
|
-
person.email = row['Email']
|
147
|
+
if !tags.nil?
|
148
|
+
if tags.is_a?(String)
|
149
|
+
organization.set_tag tags
|
150
|
+
use_default_lead_tag = false
|
151
|
+
elsif tags.is_a?(Array)
|
152
|
+
tags.each do |tag|
|
153
|
+
organization.set_tag tag
|
154
|
+
end
|
155
|
+
use_default_lead_tag = false
|
156
|
+
end
|
136
157
|
end
|
137
158
|
end
|
159
|
+
if use_default_lead_tag == true
|
160
|
+
organization.set_tag 'lead'
|
161
|
+
organization.set_tag row['Status']
|
162
|
+
end
|
163
|
+
|
164
|
+
organization.responsible_coworker =
|
165
|
+
rootmodel.find_coworker_by_integration_id(row['OwnerId'])
|
166
|
+
|
167
|
+
organization.name = row['Company']
|
168
|
+
organization.with_postal_address do |address|
|
169
|
+
address.street = row['Street']
|
170
|
+
address.zip_code = row['PostalCode']
|
171
|
+
address.city = row['City']
|
172
|
+
address.country_code = get_country_code(row['Country'])
|
173
|
+
end
|
174
|
+
organization.web_site = row['WebSite']
|
175
|
+
|
176
|
+
organization.set_tag row['Industry']
|
177
|
+
|
178
|
+
person = GoImport::Person.new
|
179
|
+
organization.add_employee(person)
|
180
|
+
person.first_name = row['FirstName']
|
181
|
+
person.last_name = row['LastName']
|
182
|
+
person.position = row['Title']
|
183
|
+
person.direct_phone_number = row['Phone']
|
184
|
+
person.mobile_phone_number = row['MobilePhone']
|
185
|
+
person.email = row['Email']
|
186
|
+
|
187
|
+
return organization
|
188
|
+
end
|
189
|
+
|
190
|
+
def get_country_code(country)
|
191
|
+
country_code = ''
|
192
|
+
|
193
|
+
case country.downcase
|
194
|
+
when 'sverige'
|
195
|
+
country_code = 'se'
|
196
|
+
when 'sweden'
|
197
|
+
country_code = 'se'
|
198
|
+
when 'norge'
|
199
|
+
country_code = 'no'
|
200
|
+
when 'norway'
|
201
|
+
country_code = 'no'
|
202
|
+
when 'danmark'
|
203
|
+
country_code = 'dk'
|
204
|
+
when 'denmark'
|
205
|
+
country_code = 'dk'
|
206
|
+
end
|
207
|
+
|
208
|
+
return country_code
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_person_to_organization(row, rootmodel)
|
212
|
+
if row['IsDeleted'] != '0'
|
213
|
+
return
|
214
|
+
end
|
215
|
+
|
216
|
+
org = rootmodel.find_organization_by_integration_id(row['AccountId'])
|
217
|
+
if !org.nil?
|
218
|
+
person = GoImport::Person.new
|
219
|
+
org.add_employee(person)
|
220
|
+
|
221
|
+
person.integration_id = row['Id']
|
222
|
+
person.first_name = row['FirstName']
|
223
|
+
person.last_name = row['LastName']
|
224
|
+
|
225
|
+
person.direct_phone_number = row['Phone']
|
226
|
+
person.fax_phone_number = row['Fax']
|
227
|
+
person.mobile_phone_number = row['MobilePhone']
|
228
|
+
person.home_phone_number = row['HomePhone']
|
229
|
+
person.position = row['Title']
|
230
|
+
person.email = row['Email']
|
231
|
+
end
|
138
232
|
end
|
139
233
|
|
140
234
|
def to_deal(row, rootmodel, converter)
|
@@ -161,7 +255,11 @@ def to_deal(row, rootmodel, converter)
|
|
161
255
|
|
162
256
|
if !status.nil?
|
163
257
|
deal.status = status
|
258
|
+
else
|
259
|
+
deal.status = row['StageName']
|
164
260
|
end
|
261
|
+
else
|
262
|
+
deal.status = row['StageName']
|
165
263
|
end
|
166
264
|
|
167
265
|
return deal
|
@@ -188,8 +286,34 @@ def to_note(row, rootmodel)
|
|
188
286
|
return note
|
189
287
|
end
|
190
288
|
|
289
|
+
def get_deal_statuses_from_opportunites()
|
290
|
+
puts "Trying to get deal statuses..."
|
291
|
+
statuses = []
|
292
|
+
|
293
|
+
process_rows(DEAL_FILE) do |row|
|
294
|
+
status = {
|
295
|
+
:label => row['StageName'],
|
296
|
+
:integration_id => row['StageName'],
|
297
|
+
}
|
298
|
+
|
299
|
+
if row['IsClosed'] == '1'
|
300
|
+
if row['IsWon'] == '1'
|
301
|
+
status[:assessment] = GoImport::DealState::PositiveEndState
|
302
|
+
else
|
303
|
+
status[:assessment] = GoImport::DealState::NegativeEndState
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
if !statuses.any? {|s| s[:label] == status[:label]}
|
308
|
+
statuses.push status
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
return statuses
|
313
|
+
end
|
314
|
+
|
191
315
|
def convert_source
|
192
|
-
puts "Trying to convert
|
316
|
+
puts "Trying to convert Salesforce to LIME Go..."
|
193
317
|
|
194
318
|
converter = Converter.new
|
195
319
|
|
@@ -201,7 +325,9 @@ def convert_source
|
|
201
325
|
end
|
202
326
|
|
203
327
|
rootmodel = GoImport::RootModel.new
|
204
|
-
converter.configure
|
328
|
+
if converter.respond_to?(:configure)
|
329
|
+
converter.configure(rootmodel)
|
330
|
+
end
|
205
331
|
|
206
332
|
# We know have the Salesforce export zip file in
|
207
333
|
# export_zip_files[0]. We should unzip the file to a temp folder
|
@@ -218,10 +344,18 @@ def convert_source
|
|
218
344
|
entry.extract
|
219
345
|
end
|
220
346
|
end
|
347
|
+
end
|
348
|
+
|
349
|
+
deal_statuses = get_deal_statuses_from_opportunites()
|
350
|
+
rootmodel.settings.with_deal do |deal|
|
351
|
+
deal_statuses.each do |status|
|
352
|
+
deal.add_status({ :label => status[:label],
|
353
|
+
:integration_id => status[:integration_id],
|
354
|
+
:assessment => status[:assessment]
|
355
|
+
})
|
356
|
+
end
|
221
357
|
end
|
222
358
|
|
223
|
-
#puts 'sleep a while'
|
224
|
-
#sleep 5
|
225
359
|
|
226
360
|
puts "Trying to import users..."
|
227
361
|
process_rows(USER_FILE) do |row|
|
@@ -229,8 +363,11 @@ def convert_source
|
|
229
363
|
end
|
230
364
|
|
231
365
|
puts "Trying to import organizations..."
|
232
|
-
process_rows(
|
233
|
-
rootmodel.add_organization(
|
366
|
+
process_rows(ORGANIZATION_ACCOUNT_FILE) do |row|
|
367
|
+
rootmodel.add_organization(account_to_organization(row, rootmodel))
|
368
|
+
end
|
369
|
+
process_rows(ORGANIZATION_LEAD_FILE) do |row|
|
370
|
+
rootmodel.add_organization(lead_to_organization(row, rootmodel, converter))
|
234
371
|
end
|
235
372
|
|
236
373
|
puts "Trying to import persons..."
|
@@ -37,39 +37,61 @@ FILES_FOLDER_AT_CUSTOMER = "m:\\documents\\"
|
|
37
37
|
class Converter
|
38
38
|
# Configure your root model, add custom fields and deal statuses.
|
39
39
|
def configure(rootmodel)
|
40
|
-
# add custom field to your model
|
41
|
-
# added to organization, deal and
|
42
|
-
# :String and :Link. If no type is
|
43
|
-
# as default.
|
40
|
+
# add custom field and deal statuses to your model
|
41
|
+
# here. Custom fields can be added to organization, deal and
|
42
|
+
# person. Valid types are :String and :Link. If no type is
|
43
|
+
# specified :String is used as default.
|
44
|
+
|
45
|
+
# You dont have to add the Stages for Opportunities here since
|
46
|
+
# they are automagically added.
|
47
|
+
|
48
|
+
|
44
49
|
# rootmodel.settings.with_organization do |organization|
|
45
50
|
# organization.set_custom_field( { :integrationid => 'external_url', :title => 'Link to external system', :type => :Link } )
|
46
51
|
# end
|
47
|
-
|
48
|
-
rootmodel.settings.with_deal do |deal|
|
49
|
-
deal.add_status({:label => "1. Kvalificering", :integration_id => "qualification"})
|
50
|
-
deal.add_status({:label => "Vunnen", :integration_id => "won",
|
51
|
-
:assessment => GoImport::DealState::PositiveEndState })
|
52
|
-
deal.add_status({:label => "Lost", :integration_id => "Lost",
|
53
|
-
:assessment => GoImport::DealState::NegativeEndState })
|
54
|
-
end
|
55
52
|
end
|
56
53
|
|
57
54
|
def get_deal_status_from_salesforce_stage(salesforce_deal_stage)
|
58
55
|
# When deals are added to LIME Go this method is called for
|
59
56
|
# each deal. The deal's stage from Salesforce is supplied as
|
60
57
|
# an argument and this method should return a status for the
|
61
|
-
# deal in LIME Go. The returned value is probably
|
62
|
-
#
|
63
|
-
#
|
64
|
-
|
58
|
+
# deal in LIME Go. The returned value is probably a label of a
|
59
|
+
# deal status that has been added in the configure(rootmodel)
|
60
|
+
# method. If nil is returned, the default status will be the
|
61
|
+
# same as in Salesforce (ie salesforce_deal_stage)
|
62
|
+
|
63
|
+
# deal_status = nil
|
64
|
+
|
65
|
+
# case salesforce_deal_stage
|
66
|
+
# when 'Prospecting'
|
67
|
+
# deal_status = '1. Kvalificering'
|
68
|
+
# when 'Closed Won'
|
69
|
+
# deal_status = 'Vunnen'
|
70
|
+
# end
|
71
|
+
|
72
|
+
# return deal_status
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_relation_for_lead()
|
76
|
+
# Returns the relation that converted leads should have. By
|
77
|
+
# default leads will get the relation WorkingOnIt.
|
78
|
+
|
79
|
+
return GoImport::Relation::WorkingOnIt
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_tags_for_lead(lead_status)
|
83
|
+
# Returns the tag or tags that converted leads should
|
84
|
+
# have. Return either a string or an array of
|
85
|
+
# strings. lead_status is the status value from Salesforce.
|
86
|
+
|
87
|
+
# If no tag is returned, the default is 'lead' and the status.
|
88
|
+
|
89
|
+
# if lead_status == 'Qualified'
|
90
|
+
# return ['lead', 'qualified']
|
91
|
+
# else
|
92
|
+
# return 'lead'
|
93
|
+
# end
|
65
94
|
|
66
|
-
|
67
|
-
when 'Prospecting'
|
68
|
-
deal_status = '1. Kvalificering'
|
69
|
-
when 'Closed Won'
|
70
|
-
deal_status = 'Vunnen'
|
71
|
-
end
|
72
|
-
|
73
|
-
return deal_status
|
95
|
+
# return nil
|
74
96
|
end
|
75
97
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: iso-8859-1
|
1
2
|
require 'spec_helper'
|
2
3
|
require 'go_import'
|
3
4
|
|
@@ -26,4 +27,19 @@ And a new line\"")
|
|
26
27
|
v.should include({"id"=>"1","navn"=>"Bj\u{00F6}rk
|
27
28
|
And a new line"})
|
28
29
|
end
|
30
|
+
|
31
|
+
it "should handled values with ," do
|
32
|
+
# given
|
33
|
+
str = "id,name,text
|
34
|
+
1,lundalogik,\"hej, hopp\""
|
35
|
+
|
36
|
+
# when
|
37
|
+
v = GoImport::CsvHelper.text_to_hashes(str)
|
38
|
+
|
39
|
+
# then
|
40
|
+
v.should include({
|
41
|
+
"id" => "1",
|
42
|
+
"name" => "lundalogik",
|
43
|
+
"text" => "hej, hopp"})
|
44
|
+
end
|
29
45
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: iso-8859-1
|
1
2
|
require 'spec_helper'
|
2
3
|
require 'go_import'
|
3
4
|
|
@@ -29,4 +30,8 @@ describe GoImport::EmailHelper do
|
|
29
30
|
it "should not validate an invalid address" do
|
30
31
|
GoImport::EmailHelper.is_valid?("hubbabubba").should eq false
|
31
32
|
end
|
33
|
+
|
34
|
+
it "should not validate an address with swedish chars" do
|
35
|
+
GoImport::EmailHelper.is_valid?("info.bor�s@example.se").should eq false
|
36
|
+
end
|
32
37
|
end
|
data/spec/rootmodel_spec.rb
CHANGED
@@ -183,6 +183,21 @@ describe "RootModel" do
|
|
183
183
|
rootmodel.deals.length.should eq 1
|
184
184
|
end
|
185
185
|
|
186
|
+
it "will add two deal without integration id" do
|
187
|
+
# given
|
188
|
+
deal1 = GoImport::Deal.new
|
189
|
+
deal1.name = "The big deal"
|
190
|
+
deal2 = GoImport::Deal.new
|
191
|
+
deal2.name = "The even bigger deal"
|
192
|
+
|
193
|
+
# when
|
194
|
+
rootmodel.add_deal(deal1)
|
195
|
+
rootmodel.add_deal(deal2)
|
196
|
+
|
197
|
+
# then
|
198
|
+
rootmodel.deals.length.should eq 2
|
199
|
+
end
|
200
|
+
|
186
201
|
it "can add a note from hash" do
|
187
202
|
rootmodel.add_note({
|
188
203
|
:integration_id => "123key",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: go_import
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oskar Gewalli
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2014-12-
|
14
|
+
date: 2014-12-16 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: iso_country_codes
|