go_import 3.0.19 → 3.0.21
Sign up to get free protection for your applications and to get access to all the features.
- 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
|