go_import 3.0.0
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.
- data/bin/go-import +96 -0
- data/lib/go_import/csv_helper.rb +47 -0
- data/lib/go_import/email_helper.rb +10 -0
- data/lib/go_import/errors.rb +22 -0
- data/lib/go_import/excel_helper.rb +10 -0
- data/lib/go_import/global_phone.json +6571 -0
- data/lib/go_import/model/address.rb +61 -0
- data/lib/go_import/model/class_settings.rb +50 -0
- data/lib/go_import/model/coworker.rb +76 -0
- data/lib/go_import/model/coworker_reference.rb +33 -0
- data/lib/go_import/model/customfield.rb +87 -0
- data/lib/go_import/model/deal.rb +172 -0
- data/lib/go_import/model/deal_class_settings.rb +73 -0
- data/lib/go_import/model/deal_state.rb +15 -0
- data/lib/go_import/model/deal_status.rb +23 -0
- data/lib/go_import/model/deal_status_reference.rb +47 -0
- data/lib/go_import/model/deal_status_setting.rb +49 -0
- data/lib/go_import/model/documents.rb +51 -0
- data/lib/go_import/model/link.rb +70 -0
- data/lib/go_import/model/note.rb +97 -0
- data/lib/go_import/model/note_classification.rb +25 -0
- data/lib/go_import/model/organization.rb +219 -0
- data/lib/go_import/model/person.rb +151 -0
- data/lib/go_import/model/referencetosource.rb +46 -0
- data/lib/go_import/model/relation.rb +23 -0
- data/lib/go_import/model/rootmodel.rb +359 -0
- data/lib/go_import/model/settings.rb +61 -0
- data/lib/go_import/model/tag.rb +35 -0
- data/lib/go_import/model_helpers.rb +54 -0
- data/lib/go_import/phone_helper.rb +74 -0
- data/lib/go_import/roo_helper.rb +80 -0
- data/lib/go_import/serialize_helper.rb +186 -0
- data/lib/go_import/source.rb +87 -0
- data/lib/go_import/templating.rb +52 -0
- data/lib/go_import.rb +19 -0
- data/sources/csv/.gitignore +14 -0
- data/sources/csv/.go_import/runner.rb +62 -0
- data/sources/csv/Gemfile +5 -0
- data/sources/csv/Rakefile.rb +7 -0
- data/sources/csv/converter.rb +179 -0
- data/sources/csv/data/coworkers.csv +2 -0
- data/sources/csv/data/deals.csv +2 -0
- data/sources/csv/data/organizations.csv +2 -0
- data/sources/csv/data/persons.csv +2 -0
- data/sources/csv/spec/exporter_spec.rb +17 -0
- data/sources/csv/spec/sample_data/coworkers.csv +2 -0
- data/sources/csv/spec/sample_data/deals.csv +2 -0
- data/sources/csv/spec/sample_data/organizations.csv +2 -0
- data/sources/csv/spec/sample_data/persons.csv +2 -0
- data/sources/csv/spec/spec_helper.rb +30 -0
- data/sources/easy/.gitignore +14 -0
- data/sources/easy/.go_import/runner.rb +115 -0
- data/sources/easy/Export/readme.txt +6 -0
- data/sources/easy/Gemfile +5 -0
- data/sources/easy/Rakefile.rb +7 -0
- data/sources/easy/converter.rb +435 -0
- data/sources/easy/spec/exporter_spec.rb +10 -0
- data/sources/easy/spec/sample_data/Company.txt +649 -0
- data/sources/easy/spec/spec_helper.rb +30 -0
- data/sources/excel/.gitignore +14 -0
- data/sources/excel/.go_import/runner.rb +116 -0
- data/sources/excel/Gemfile +6 -0
- data/sources/excel/Rakefile.rb +7 -0
- data/sources/excel/converter.rb +130 -0
- data/sources/excel/spec/sample_data/sample.xlsx +0 -0
- data/sources/excel/spec/spec_helper.rb +26 -0
- data/sources/excel/spec/tomodel_spec.rb +18 -0
- data/sources/excel/template.xlsx +0 -0
- data/spec/address_spec.rb +49 -0
- data/spec/class_settings_spec.rb +37 -0
- data/spec/coworker_spec.rb +94 -0
- data/spec/custom_field_spec.rb +22 -0
- data/spec/deal_class_settings_spec.rb +104 -0
- data/spec/deal_spec.rb +182 -0
- data/spec/deal_status_reference_spec.rb +17 -0
- data/spec/documents_spec.rb +37 -0
- data/spec/helpers/csv_helper_spec.rb +29 -0
- data/spec/helpers/email_helper_spec.rb +32 -0
- data/spec/helpers/phone_helper_spec.rb +97 -0
- data/spec/helpers/roo_helper_spec.rb +10 -0
- data/spec/helpers/serialize_helper_spec.rb +249 -0
- data/spec/helpers/xsd_validate_spec.rb +55 -0
- data/spec/link_spec.rb +106 -0
- data/spec/note_spec.rb +110 -0
- data/spec/organization_spec.rb +151 -0
- data/spec/person_spec.rb +132 -0
- data/spec/rootmodel_spec.rb +371 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/templating_spec.rb +12 -0
- 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,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
|