go_import 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/bin/go-import +96 -0
  2. data/lib/go_import/csv_helper.rb +47 -0
  3. data/lib/go_import/email_helper.rb +10 -0
  4. data/lib/go_import/errors.rb +22 -0
  5. data/lib/go_import/excel_helper.rb +10 -0
  6. data/lib/go_import/global_phone.json +6571 -0
  7. data/lib/go_import/model/address.rb +61 -0
  8. data/lib/go_import/model/class_settings.rb +50 -0
  9. data/lib/go_import/model/coworker.rb +76 -0
  10. data/lib/go_import/model/coworker_reference.rb +33 -0
  11. data/lib/go_import/model/customfield.rb +87 -0
  12. data/lib/go_import/model/deal.rb +172 -0
  13. data/lib/go_import/model/deal_class_settings.rb +73 -0
  14. data/lib/go_import/model/deal_state.rb +15 -0
  15. data/lib/go_import/model/deal_status.rb +23 -0
  16. data/lib/go_import/model/deal_status_reference.rb +47 -0
  17. data/lib/go_import/model/deal_status_setting.rb +49 -0
  18. data/lib/go_import/model/documents.rb +51 -0
  19. data/lib/go_import/model/link.rb +70 -0
  20. data/lib/go_import/model/note.rb +97 -0
  21. data/lib/go_import/model/note_classification.rb +25 -0
  22. data/lib/go_import/model/organization.rb +219 -0
  23. data/lib/go_import/model/person.rb +151 -0
  24. data/lib/go_import/model/referencetosource.rb +46 -0
  25. data/lib/go_import/model/relation.rb +23 -0
  26. data/lib/go_import/model/rootmodel.rb +359 -0
  27. data/lib/go_import/model/settings.rb +61 -0
  28. data/lib/go_import/model/tag.rb +35 -0
  29. data/lib/go_import/model_helpers.rb +54 -0
  30. data/lib/go_import/phone_helper.rb +74 -0
  31. data/lib/go_import/roo_helper.rb +80 -0
  32. data/lib/go_import/serialize_helper.rb +186 -0
  33. data/lib/go_import/source.rb +87 -0
  34. data/lib/go_import/templating.rb +52 -0
  35. data/lib/go_import.rb +19 -0
  36. data/sources/csv/.gitignore +14 -0
  37. data/sources/csv/.go_import/runner.rb +62 -0
  38. data/sources/csv/Gemfile +5 -0
  39. data/sources/csv/Rakefile.rb +7 -0
  40. data/sources/csv/converter.rb +179 -0
  41. data/sources/csv/data/coworkers.csv +2 -0
  42. data/sources/csv/data/deals.csv +2 -0
  43. data/sources/csv/data/organizations.csv +2 -0
  44. data/sources/csv/data/persons.csv +2 -0
  45. data/sources/csv/spec/exporter_spec.rb +17 -0
  46. data/sources/csv/spec/sample_data/coworkers.csv +2 -0
  47. data/sources/csv/spec/sample_data/deals.csv +2 -0
  48. data/sources/csv/spec/sample_data/organizations.csv +2 -0
  49. data/sources/csv/spec/sample_data/persons.csv +2 -0
  50. data/sources/csv/spec/spec_helper.rb +30 -0
  51. data/sources/easy/.gitignore +14 -0
  52. data/sources/easy/.go_import/runner.rb +115 -0
  53. data/sources/easy/Export/readme.txt +6 -0
  54. data/sources/easy/Gemfile +5 -0
  55. data/sources/easy/Rakefile.rb +7 -0
  56. data/sources/easy/converter.rb +435 -0
  57. data/sources/easy/spec/exporter_spec.rb +10 -0
  58. data/sources/easy/spec/sample_data/Company.txt +649 -0
  59. data/sources/easy/spec/spec_helper.rb +30 -0
  60. data/sources/excel/.gitignore +14 -0
  61. data/sources/excel/.go_import/runner.rb +116 -0
  62. data/sources/excel/Gemfile +6 -0
  63. data/sources/excel/Rakefile.rb +7 -0
  64. data/sources/excel/converter.rb +130 -0
  65. data/sources/excel/spec/sample_data/sample.xlsx +0 -0
  66. data/sources/excel/spec/spec_helper.rb +26 -0
  67. data/sources/excel/spec/tomodel_spec.rb +18 -0
  68. data/sources/excel/template.xlsx +0 -0
  69. data/spec/address_spec.rb +49 -0
  70. data/spec/class_settings_spec.rb +37 -0
  71. data/spec/coworker_spec.rb +94 -0
  72. data/spec/custom_field_spec.rb +22 -0
  73. data/spec/deal_class_settings_spec.rb +104 -0
  74. data/spec/deal_spec.rb +182 -0
  75. data/spec/deal_status_reference_spec.rb +17 -0
  76. data/spec/documents_spec.rb +37 -0
  77. data/spec/helpers/csv_helper_spec.rb +29 -0
  78. data/spec/helpers/email_helper_spec.rb +32 -0
  79. data/spec/helpers/phone_helper_spec.rb +97 -0
  80. data/spec/helpers/roo_helper_spec.rb +10 -0
  81. data/spec/helpers/serialize_helper_spec.rb +249 -0
  82. data/spec/helpers/xsd_validate_spec.rb +55 -0
  83. data/spec/link_spec.rb +106 -0
  84. data/spec/note_spec.rb +110 -0
  85. data/spec/organization_spec.rb +151 -0
  86. data/spec/person_spec.rb +132 -0
  87. data/spec/rootmodel_spec.rb +371 -0
  88. data/spec/spec_helper.rb +30 -0
  89. data/spec/templating_spec.rb +12 -0
  90. metadata +306 -0
@@ -0,0 +1,30 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ #require File.expand_path("../../config/environment", __FILE__)
3
+ #require 'rspec/rails'
4
+ #require 'rspec/autorun'
5
+
6
+ # Requires supporting ruby files with custom matchers and macros, etc,
7
+ # in spec/support/ and its subdirectories.
8
+ #Dir[File.join(File.dirname(File.absolute_path(__FILE__)),"support/**/*.rb")].each { |f| require f }
9
+
10
+ RSpec.configure do |config|
11
+ # ## Mock Framework
12
+ #
13
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
14
+ #
15
+ # config.mock_with :mocha
16
+ # config.mock_with :flexmock
17
+ # config.mock_with :rr
18
+
19
+ # Run specs in random order to surface order dependencies. If you find an
20
+ # order dependency and want to debug it, you can fix the order by providing
21
+ # the seed, which is printed after each run.
22
+ # --seed 1234
23
+ config.order = "random"
24
+
25
+ # Allow both should and expect syntax
26
+ # http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
27
+ config.expect_with :rspec do |c|
28
+ c.syntax = [:should, :expect]
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+ # Ignore built gems
10
+ /*.gem
11
+ # Ignore all logfiles and tempfiles.
12
+ /tmp
13
+ /spec/tmp
14
+ pkg
@@ -0,0 +1,115 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'go_import'
4
+ require_relative("../converter")
5
+
6
+ def convert_source
7
+ puts "Trying to convert LIME Easy source to LIME Go..."
8
+
9
+ converter = Converter.new
10
+
11
+ # *** TODO:
12
+ #
13
+ # Modify the name of the sheets. Or add/remove sheets based on
14
+ # your Excel file.
15
+
16
+ # First we read each sheet from the excel file into separate
17
+ # variables
18
+ excel_workbook = GoImport::ExcelHelper.Open(EXCEL_FILE)
19
+
20
+ if defined?(COWORKER_SHEET)
21
+ if excel_workbook.has_sheet?(COWORKER_SHEET)
22
+ coworker_rows = excel_workbook.rows_for_sheet COWORKER_SHEET
23
+ else
24
+ puts "Warning: can't find sheet '#{COWORKER_SHEET}'"
25
+ end
26
+ end
27
+
28
+ if defined?(ORGANIZATION_SHEET)
29
+ if excel_workbook.has_sheet?(ORGANIZATION_SHEET)
30
+ organization_rows = excel_workbook.rows_for_sheet ORGANIZATION_SHEET
31
+ else
32
+ puts "Warning: can't find sheet '#{ORGANIZATION_SHEET}'"
33
+ end
34
+ end
35
+
36
+ if defined?(PERSON_SHEET)
37
+ if excel_workbook.has_sheet?(PERSON_SHEET)
38
+ person_rows = excel_workbook.rows_for_sheet PERSON_SHEET
39
+ else
40
+ puts "Warning: can't find sheet '#{PERSON_SHEET}'"
41
+ end
42
+ end
43
+
44
+ if defined?(DEAL_SHEET)
45
+ if excel_workbook.has_sheet?(DEAL_SHEET)
46
+ deal_rows = excel_workbook.rows_for_sheet DEAL_SHEET
47
+ else
48
+ puts "Warning: can't find sheet '#{DEAL_SHEET}'"
49
+ end
50
+ end
51
+
52
+ if defined?(NOTE_SHEET)
53
+ if excel_workbook.has_sheet?(NOTE_SHEET)
54
+ note_rows = excel_workbook.rows_for_sheet NOTE_SHEET
55
+ else
56
+ puts "Warning: can't find sheet '#{NOTE_SHEET}'"
57
+ end
58
+ end
59
+
60
+ # Then we create a rootmodel that will contain all data that
61
+ # should be exported to LIME Go.
62
+ rootmodel = GoImport::RootModel.new
63
+
64
+ # And configure the model if we have any custom fields
65
+ converter.configure rootmodel
66
+
67
+ # Now start to read data from the excel file and add to the
68
+ # rootmodel. We begin with coworkers since they are referenced
69
+ # from everywhere (orgs, deals, notes)
70
+ if defined?(coworker_rows) && !coworker_rows.nil?
71
+ puts "Trying to convert coworkers..."
72
+ coworker_rows.each do |row|
73
+ rootmodel.add_coworker(converter.to_coworker(row))
74
+ end
75
+ end
76
+
77
+ # Then create organizations, they are only referenced by
78
+ # coworkers.
79
+ if defined?(organization_rows) && !organization_rows.nil?
80
+ puts "Trying to convert organizations..."
81
+ organization_rows.each do |row|
82
+ rootmodel.add_organization(converter.to_organization(row, rootmodel))
83
+ end
84
+ end
85
+
86
+ # Add people and link them to their organizations
87
+ if defined?(person_rows) && !person_rows.nil?
88
+ puts "Trying to convert persons..."
89
+ person_rows.each do |row|
90
+ # People are special since they are not added directly to
91
+ # the root model
92
+ converter.import_person_to_organization(row, rootmodel)
93
+ end
94
+ end
95
+
96
+ # Deals can connected to coworkers, organizations and people.
97
+ if defined?(deal_rows) && !deal_rows.nil?
98
+ puts "Trying to convert deals..."
99
+ deal_rows.each do |row|
100
+ rootmodel.add_deal(converter.to_deal(row, rootmodel))
101
+ end
102
+ end
103
+
104
+ # Notes must be owned by a coworker and the be added to
105
+ # organizations and notes and might refernce a person
106
+ if defined?(note_rows) && !note_rows.nil?
107
+ puts "Trying to convert notes..."
108
+ note_rows.each do |row|
109
+ rootmodel.add_note(converter.to_note(row, rootmodel))
110
+ end
111
+ end
112
+
113
+ return rootmodel
114
+ end
115
+
@@ -0,0 +1,6 @@
1
+ Export all data from KONTAKT.mdb to this folder.
2
+
3
+ Export data using the magical tool called PowerSellMigrationExport.exe
4
+ that can be found in K:\Lundalogik\LIME Easy\Tillbeh�r\Migrationsexport.
5
+
6
+ Yay!
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'thor'
4
+ #gem 'go_import'
5
+ gem 'rspec'
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,435 @@
1
+ # encoding: UTF-8
2
+ require 'go_import'
3
+
4
+ # Customize this file to suit your input files.
5
+ #
6
+ # Documentation go_import can be found at
7
+ # http://rubygems.org/gems/go_import
8
+ #
9
+ # go_import contains all objects in LIME Go such as organization,
10
+ # people, deals, etc. What properties each object has is described in
11
+ # the documentation.
12
+
13
+ # *** TODO:
14
+ #
15
+ # You must customize this template so it works with your LIME Easy
16
+ # database. Modify each to_* method and set properties on the LIME Go
17
+ # objects.
18
+ #
19
+ # Follow these steps:
20
+ #
21
+ # 1) Export all data from KONTAKT.mdb to a folder named Export located
22
+ # in the folder created by go_import unpack_template. Export data
23
+ # using the magical tool called PowerSellMigrationExport.exe that can
24
+ # be found in K:\Lundalogik\LIME Easy\Tillbeh�r\Migrationsexport.
25
+ #
26
+ # 2) Modify this file (the to_* methods) according to your customer's
27
+ # KONTAKT.mdb and wishes.
28
+ #
29
+ # 3) Run easy-to-go.bat in a command prompt.
30
+ #
31
+ # 4) Upload go.xml to LIME Go. First test your import on staging and
32
+ # when your customer has approved the import, run it on production.
33
+ class Exporter
34
+ # Turns a user from the User.txt Easy Export file into
35
+ # a go_import coworker.
36
+ def to_coworker(row)
37
+ coworker = GoImport::Coworker.new
38
+ # integration_id is typically the userId in Easy
39
+ # Must be set to be able to import the same file more
40
+ # than once without creating duplicates
41
+
42
+ # NOTE: You shouldn't have to modify this method
43
+
44
+ coworker.integration_id = row['PowerSellUserID']
45
+ coworker.parse_name_to_firstname_lastname_se(row['Name'])
46
+
47
+ return coworker
48
+ end
49
+
50
+ # Turns a row from the Easy exported Company.txt file into a
51
+ # go_import organization.
52
+ def to_organization(row, coworkers)
53
+ organization = GoImport::Organization.new
54
+ # integration_id is typically the company Id in Easy
55
+ # Must be set to be able to import the same file more
56
+ # than once without creating duplicates
57
+
58
+ # Easy standard fields
59
+ organization.integration_id = row['PowerSellCompanyID']
60
+ organization.name = row['Company name']
61
+ organization.central_phone_number = row['Telephone']
62
+
63
+ # *** TODO: Customize below this line (address, superfield,
64
+ # relation, etc)
65
+
66
+ # NOTE!! if a bisnode-id is present maybe you want to consider
67
+ # not setting this (because if you set the address LIME Go
68
+ # will NOT automagically update the address from PAR)
69
+ # Addresses consists of several parts in Go. Lots of other
70
+ # systems have the address all in one line, to be able to
71
+ # match when importing it is way better to split the addresses
72
+ organization.with_postal_address do |address|
73
+ address.street = row['street']
74
+ address.zip_code = row['zip']
75
+ address.city = row['city']
76
+ address.location = row['location']
77
+ end
78
+
79
+ # Easy superfields
80
+
81
+ # Same as postal address
82
+ organization.with_visit_address do |addr|
83
+ addr.street = row['visit street']
84
+ addr.zip_code = row['visit zip']
85
+ addr.city = row['visit city']
86
+ end
87
+
88
+ organization.email = row['e-mail']
89
+ organization.organization_number = row['orgnr']
90
+
91
+ # Set Bisnode Id if present
92
+ bisnode_id = row['Bisnode-id']
93
+
94
+ if bisnode_id && !bisnode_id.empty?
95
+ organization.with_source do |source|
96
+ source.par_se(bisnode_id)
97
+ end
98
+ end
99
+
100
+ # Only set other Bisnode fields if the Bisnode Id is empty
101
+ if bisnode_id.empty?
102
+ organization.web_site = row['website']
103
+ end
104
+
105
+ # Responsible coworker for the organization.
106
+ # For instance responsible sales rep.
107
+ coworker_id = coworkers[row['idUser-Responsible']]
108
+ organization.responsible_coworker = @rootmodel.find_coworker_by_integration_id(coworker_id)
109
+
110
+ # Tags are set and defined at the same place
111
+ # Setting a tag: Imported is useful for the user
112
+ organization.set_tag("Imported")
113
+
114
+ # Option fields are normally translated into tags
115
+ # The option field customer category for instance,
116
+ # has the options "A-customer", "B-customer", and "C-customer"
117
+ organization.set_tag(row['customer category'])
118
+
119
+ # Relation
120
+ # let's say that there is a option field in Easy called 'Customer relation'
121
+ # with the options '1.Customer', '2.Prospect' '3.Partner' and '4.Lost customer'
122
+ if row['Customer relation'] == '1.Customer'
123
+ # We have made a deal with this organization.
124
+ organization.relation = GoImport::Relation::IsACustomer
125
+ elsif row['Customer relation'] == '3.Partner'
126
+ # We have made a deal with this organization.
127
+ organization.relation = GoImport::Relation::IsACustomer
128
+ elsif row['Customer relation'] == '2.Prospect'
129
+ # Something is happening with this organization, we might have
130
+ # booked a meeting with them or created a deal, etc.
131
+ organization.relation = GoImport::Relation::WorkingOnIt
132
+ elsif row['Customer relation'] == '4.Lost customer'
133
+ # We had something going with this organization but we
134
+ # couldn't close the deal and we don't think they will be a
135
+ # customer to us in the foreseeable future.
136
+ organization.relation = GoImport::Relation::BeenInTouch
137
+ else
138
+ organization.relation = GoImport::Relation::NoRelation
139
+ end
140
+
141
+ return organization
142
+ end
143
+
144
+ # Turns a row from the Easy exported Company-Person.txt file into
145
+ # a go_import model that is used to generate xml
146
+ def to_person(row)
147
+ person = GoImport::Person.new
148
+
149
+ # Easy standard fields created in configure method Easy
150
+ # persons don't have a globally unique Id, they are only
151
+ # unique within the scope of the company, so we combine the
152
+ # referenceId and the companyId to make a globally unique
153
+ # integration_id
154
+ person.integration_id = "#{row['PowerSellReferenceID']}-#{row['PowerSellCompanyID']}"
155
+ person.first_name = row['First name']
156
+ person.last_name = row['Last name']
157
+
158
+ # set employer connection
159
+ employer = @rootmodel.find_organization_by_integration_id(row['PowerSellCompanyID'])
160
+ if employer
161
+ employer.add_employee person
162
+ end
163
+
164
+ # *** TODO: Customize below this line (superfields, tags, etc)
165
+
166
+ # Easy superfields
167
+ person.direct_phone_number = row['Direktnummer']
168
+ person.mobile_phone_number = row['Mobil']
169
+ person.email = row['e-mail']
170
+ person.position = row['position']
171
+
172
+ # Populate a Go custom field
173
+ person.set_custom_value("shoe_size", row['shoe size'])
174
+
175
+ # Tags
176
+ person.set_tag("Imported")
177
+
178
+ # Checkbox fields
179
+ # Xmas card field is a checkbox in Easy
180
+ if row['Xmas card'] == "1"
181
+ person.set_tag("Xmas card")
182
+ end
183
+
184
+ # Multioption fields or "Set"- fields
185
+ if row['intrests']
186
+ intrests = row['intrests'].split(';')
187
+ intrests.each do |intrest|
188
+ person.set_tag(intrest)
189
+ end
190
+ end
191
+ end
192
+
193
+ # Turns a row from the Easy exported Project.txt file into
194
+ # a go_import model that is used to generate xml.
195
+ # Uses includes hash to lookup organizations to connect
196
+ # Uses coworkers hash to lookup coworkers to connect
197
+ def to_deal(row, includes, coworkers)
198
+ deal = GoImport::Deal.new
199
+ # Easy standard fields
200
+ deal.integration_id = row['PowerSellProjectID']
201
+ deal.name = row['Name']
202
+ deal.description = row['Description']
203
+
204
+ # Easy superfields
205
+ deal.order_date = row['order date']
206
+
207
+ coworker_id = coworkers[row['isUser-Ansvarig']]
208
+ deal.responsible_coworker = @rootmodel.find_coworker_by_integration_id(coworker_id)
209
+
210
+ # Should be integer
211
+ # The currency used in Easy should match the one used in Go
212
+ deal.value = row['value']
213
+
214
+ # should be between 0 - 100
215
+ # remove everything that is not an intiger
216
+ deal.probability = row['probability'].gsub(/[^\d]/,"").to_i unless row['probability'].nil?
217
+
218
+ # Sets the deal's status to the value of the Easy field. This
219
+ # assumes that the status is already created in LIME Go. To
220
+ # create statuses during import add them to the settings
221
+ # during configure.
222
+ if !row['Status'].empty?
223
+ deal.status = row['Status']
224
+ end
225
+
226
+ # Tags
227
+ deal.set_tag("Imported")
228
+
229
+ # Make the deal - organization connection
230
+ if includes
231
+ organization_id = includes[row['PowerSellProjectID']]
232
+ organization = @rootmodel.find_organization_by_integration_id(organization_id)
233
+ if organization
234
+ deal.customer = organization
235
+ end
236
+ end
237
+
238
+ return deal
239
+ end
240
+
241
+ # Turns a row from the Easy exported Company-History.txt file into
242
+ # a go_import model that is used to generate xml.
243
+ # Uses coworkers hash to lookup coworkers to connect
244
+ # Uses people hash to lookup persons to connect
245
+ def to_organization_note(row, coworkers, people)
246
+ organization = @rootmodel.find_organization_by_integration_id(row['PowerSellCompanyID'])
247
+
248
+ coworker_id = coworkers[row['idUser']]
249
+ coworker = @rootmodel.find_coworker_by_integration_id(coworker_id)
250
+
251
+ if organization && coworker
252
+ note = GoImport::Note.new()
253
+ note.organization = organization
254
+ note.created_by = coworker
255
+ note.person = organization.find_employee_by_integration_id(people[row['idPerson']])
256
+ note.date = row['Date']
257
+ note.text = "#{row['Category']}: #{row['History']}"
258
+
259
+ return note.text.empty? ? nil : note
260
+ end
261
+
262
+ return nil
263
+ end
264
+
265
+ # Turns a row from the Easy exported Project-History.txt file into
266
+ # a go_import model that is used to generate xml
267
+ # Uses coworkers hash to lookup coworkers to connect
268
+ def to_deal_note(row, coworkers)
269
+ # TODO: This could be improved to read a person from an
270
+ # organization connected to this deal if any, but since it is
271
+ # a many to many connection between organizations and deals
272
+ # it's not a straight forward task
273
+ deal = @rootmodel.find_deal_by_integration_id(row['PowerSellProjectID'])
274
+
275
+ coworker_id = coworkers[row['idUser']]
276
+ coworker = @rootmodel.find_coworker_by_integration_id(coworker_id)
277
+
278
+ if deal && coworker
279
+ note = GoImport::Note.new()
280
+ note.deal = deal
281
+ note.created_by = coworker
282
+ note.date = row['Date']
283
+ # Raw history looks like this <category>: <person>: <text>
284
+ note.text = row['RawHistory']
285
+
286
+ return note.text.empty? ? nil : note
287
+ end
288
+
289
+ return nil
290
+ end
291
+
292
+ def configure(model)
293
+ # add custom field to your model here. Custom fields can be
294
+ # added to organization, deal and person. Valid types are
295
+ # :String and :Link. If no type is specified :String is used
296
+ # as default.
297
+ model.settings.with_person do |person|
298
+ person.set_custom_field( { :integration_id => 'shoe_size', :title => 'Shoe size', :type => :String} )
299
+ end
300
+
301
+ model.settings.with_deal do |deal|
302
+ # assessment is default DealState::NoEndState
303
+ deal.add_status( {:label => '1. Kvalificering' })
304
+ deal.add_status( {:label => '2. Deal closed', :assessment => GoImport::DealState::PositiveEndState })
305
+ deal.add_status( {:label => '4. Deal lost', :assessment => GoImport::DealState::NegativeEndState })
306
+ end
307
+ end
308
+
309
+ def process_rows(file_name)
310
+ data = File.open(file_name, 'r').read.encode('UTF-8',"ISO-8859-1").strip().gsub('"', '')
311
+ data = '"' + data.gsub("\t", "\"\t\"") + '"'
312
+ data = data.gsub("\n", "\"\n\"")
313
+
314
+ rows = GoImport::CsvHelper::text_to_hashes(data, "\t", "\n", '"')
315
+ rows.each do |row|
316
+ yield row
317
+ end
318
+ end
319
+
320
+ def to_model(coworkers_filename, organization_filename, persons_filename, orgnotes_filename, includes_filename, deals_filename, dealnotes_filename)
321
+ # A rootmodel is used to represent all entitite/models
322
+ # that is exported
323
+ @rootmodel = GoImport::RootModel.new
324
+ coworkers = Hash.new
325
+ includes = Hash.new
326
+ people = Hash.new
327
+
328
+ configure @rootmodel
329
+
330
+ # coworkers
331
+ # start with these since they are referenced
332
+ # from everywhere....
333
+ if coworkers_filename && !coworkers_filename.empty?
334
+ process_rows coworkers_filename do |row|
335
+ coworkers[row['userIndex']] = row['userId']
336
+ @rootmodel.add_coworker(to_coworker(row))
337
+ end
338
+ end
339
+
340
+ # organizations
341
+ if organization_filename && !organization_filename.empty?
342
+ process_rows organization_filename do |row|
343
+ @rootmodel.add_organization(to_organization(row, coworkers))
344
+ end
345
+ end
346
+
347
+ # persons
348
+ # depends on organizations
349
+ if persons_filename && !persons_filename.empty?
350
+ process_rows persons_filename do |row|
351
+ people[row['personIndex']] = "#{row['PowerSellReferenceID']}-#{row['PowerSellCompanyID']}"
352
+ # adds it self to the employer
353
+ to_person(row)
354
+ end
355
+ end
356
+
357
+ # organization notes
358
+ if orgnotes_filename && !orgnotes_filename.empty?
359
+ process_rows orgnotes_filename do |row|
360
+ # adds itself if applicable
361
+ @rootmodel.add_note(to_organization_note(row, coworkers, people))
362
+ end
363
+ end
364
+
365
+ # Organization - Deal connection
366
+ # Reads the includes.txt and creats a hash
367
+ # that connect organizations to deals
368
+ if includes_filename && !includes_filename.empty?
369
+ process_rows includes_filename do |row|
370
+ includes[row['PowerSellProjectID']] = row['PowerSellCompanyID']
371
+ end
372
+ end
373
+
374
+ # deals
375
+ # deals can reference coworkers (responsible), organizations
376
+ # and persons (contact)
377
+ if deals_filename && !deals_filename.empty?
378
+ process_rows deals_filename do |row|
379
+ @rootmodel.add_deal(to_deal(row, includes, coworkers))
380
+ end
381
+ end
382
+
383
+ # deal notes
384
+ if dealnotes_filename && !dealnotes_filename.empty?
385
+ process_rows dealnotes_filename do |row|
386
+ # adds itself if applicable
387
+ @rootmodel.add_note(to_deal_note(row, coworkers))
388
+ end
389
+ end
390
+
391
+ return @rootmodel
392
+ end
393
+
394
+ def save_xml(file)
395
+ File.open(file,'w') do |f|
396
+ f.write(GoImport::SerializeHelper::serialize(to_xml_model))
397
+ end
398
+ end
399
+ end
400
+
401
+ require "thor"
402
+ require "fileutils"
403
+ require 'pathname'
404
+
405
+ class Cli < Thor
406
+ desc "to_go", "Generates a Go XML file"
407
+ method_option :output, :desc => "Path to file where xml will be output", :default => "export.xml", :type => :string, :required => true
408
+ method_option :coworkers, :desc => "Path to coworkers csv file", :type => :string, :required => true
409
+ method_option :organizations, :desc => "Path to organization csv file", :type => :string, :required => true
410
+ method_option :persons, :desc => "Path to persons csv file", :type => :string, :required => true
411
+ method_option :orgnotes, :desc => "Path to organization notes file", :type => :string, :required => true
412
+ method_option :includes, :desc => "Path to include file", :type => :string, :required => true
413
+ method_option :deals, :desc => "Path to deals csv file", :type => :string, :required => true
414
+ method_option :dealnotes, :desc => "Path to deal notes file", :type => :string, :required => true
415
+ def to_go
416
+ output = options.output
417
+ exporter = Exporter.new()
418
+ model = exporter.to_model(options.coworkers, options.organizations, options.persons, options.orgnotes, options.includes, options.deals, options.dealnotes)
419
+ error = model.sanity_check
420
+ if error.empty?
421
+ validation_errors = model.validate
422
+
423
+ if validation_errors.empty?
424
+ model.serialize_to_file(output)
425
+ puts "Generated Go XML file: '#{output}'."
426
+ else
427
+ puts "Could not generate file due to"
428
+ puts validation_errors
429
+ end
430
+ else
431
+ puts "Could not generate file due to"
432
+ puts error
433
+ end
434
+ end
435
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'tomodel'
3
+
4
+ describe 'Exporter' do
5
+ before(:all) do
6
+ exporter = Exporter.new
7
+ organizations_file = File.join(File.dirname(__FILE__), 'sample_data', 'company.txt')
8
+ @model = exporter.to_model(nil, organizations_file, nil, nil, nil, nil, nil)
9
+ end
10
+ end