go_import 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,186 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "rexml/document"
|
3
|
+
|
4
|
+
module GoImport
|
5
|
+
module SerializeHelper
|
6
|
+
def serialize()
|
7
|
+
SerializeHelper::serialize(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def serialize_to_file(file)
|
11
|
+
SerializeHelper::serialize_to_file(file, self)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!visibility private
|
15
|
+
def self.serialize_variables_rexml(elem, obj)
|
16
|
+
if (obj.respond_to?(:serialize_variables))
|
17
|
+
obj.serialize_variables.each do |serialize_variable|
|
18
|
+
element_name = serialize_variable[:id].to_s.gsub(/^\@/,'').split('_').map do |m|
|
19
|
+
m.capitalize
|
20
|
+
end.join('')
|
21
|
+
|
22
|
+
raw_var = obj.instance_variable_get("@#{serialize_variable[:id].to_s}")
|
23
|
+
if raw_var != nil
|
24
|
+
element = elem.add_element(element_name)
|
25
|
+
if (raw_var.respond_to?(:serialize_variables))
|
26
|
+
SerializeHelper::serialize_variables_rexml(element, raw_var)
|
27
|
+
elsif (raw_var.is_a?(Array))
|
28
|
+
raw_var.each do |raw_var_elem|
|
29
|
+
SerializeHelper::serialize_rexml(element, raw_var_elem)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
element.text = raw_var.to_s.encode('UTF-8')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
return
|
37
|
+
end
|
38
|
+
raise "Do not know how to handle #{obj.class} !!"
|
39
|
+
end
|
40
|
+
|
41
|
+
# @!visibility private
|
42
|
+
def self.serialize_rexml(elem, obj)
|
43
|
+
if obj.respond_to?(:to_rexml)
|
44
|
+
obj.to_rexml(elem)
|
45
|
+
elsif (obj.respond_to?(:serialize_variables))
|
46
|
+
element_name = obj.serialize_name
|
47
|
+
SerializeHelper::serialize_variables_rexml(elem.add_element(element_name), obj)
|
48
|
+
else
|
49
|
+
elem.text = obj.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @!visibility private
|
54
|
+
def self.serialize(obj, indent= 2)
|
55
|
+
# indent -1 to avoid indent
|
56
|
+
if obj.respond_to?(:to_rexml)
|
57
|
+
doc = REXML::Document.new()
|
58
|
+
SerializeHelper::serialize_rexml(doc, obj)
|
59
|
+
doc.write( xml_str = "" , indent, true)
|
60
|
+
xml_str
|
61
|
+
elsif (obj.respond_to?(:serialize_variables))
|
62
|
+
element_name = obj.serialize_name
|
63
|
+
doc = REXML::Document.new()
|
64
|
+
SerializeHelper::serialize_variables_rexml(doc.add_element(element_name), obj)
|
65
|
+
doc.write( xml_str = "", indent, true)
|
66
|
+
xml_str
|
67
|
+
else
|
68
|
+
obj.to_s.encode(:xml => :text)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @!visibility private
|
73
|
+
def self.serialize_to_file(file, obj)
|
74
|
+
File.open(file, 'w') do |f|
|
75
|
+
f.write(SerializeHelper::serialize(obj))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# @!visibility private
|
80
|
+
def symbol_to_name(symbol)
|
81
|
+
symbol.to_s.split('_').join(' ').capitalize
|
82
|
+
end
|
83
|
+
|
84
|
+
# @!visibility private
|
85
|
+
def map_symbol_to_row(symbol,type)
|
86
|
+
{
|
87
|
+
:id => symbol.to_s,
|
88
|
+
:name => symbol == :id ? 'Go id' : symbol_to_name(symbol),
|
89
|
+
:type =>type
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
# @!visibility private
|
94
|
+
def map_to_row(p)
|
95
|
+
case p[:type]
|
96
|
+
when :string then
|
97
|
+
map_symbol_to_row(p[:id],p[:type])
|
98
|
+
when :bool then
|
99
|
+
map_symbol_to_row(p[:id],p[:type])
|
100
|
+
when :date then
|
101
|
+
map_symbol_to_row(p[:id],p[:type])
|
102
|
+
when :notes then
|
103
|
+
{
|
104
|
+
:id => p[:id].to_s,
|
105
|
+
:name => symbol_to_name(p[:id]),
|
106
|
+
:type => p[:type],
|
107
|
+
:models => SerializeHelper.get_import_rows(:note)
|
108
|
+
}
|
109
|
+
when :tags then
|
110
|
+
{
|
111
|
+
:id => p[:id].to_s,
|
112
|
+
:type => p[:type],
|
113
|
+
:name => symbol_to_name(p[:id]),
|
114
|
+
}
|
115
|
+
when :persons then
|
116
|
+
{
|
117
|
+
:id => p[:id].to_s,
|
118
|
+
:type => p[:type],
|
119
|
+
:name => symbol_to_name(p[:id]),
|
120
|
+
:models => SerializeHelper.get_import_rows(:person)
|
121
|
+
}
|
122
|
+
when :custom_fields then
|
123
|
+
{
|
124
|
+
:id => p[:id].to_s,
|
125
|
+
:type => p[:type],
|
126
|
+
:name => symbol_to_name(p[:id]),
|
127
|
+
:models => SerializeHelper.get_import_rows(:custom_field)
|
128
|
+
}
|
129
|
+
when :custom_values then
|
130
|
+
{
|
131
|
+
:id => p[:id].to_s,
|
132
|
+
:type => p[:type],
|
133
|
+
:name => symbol_to_name(p[:id]),
|
134
|
+
:models => SerializeHelper.get_import_rows(:custom_value)
|
135
|
+
}
|
136
|
+
else
|
137
|
+
{
|
138
|
+
:id => p[:id].to_s,
|
139
|
+
:name => symbol_to_name(p[:id]),
|
140
|
+
:type => p[:type],
|
141
|
+
:model => SerializeHelper.get_import_rows(p[:type])
|
142
|
+
}
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# What fields/rows on the class is supposed to be used by the Gem to generate the xml
|
147
|
+
# This method uses #serialize_variables.
|
148
|
+
def get_import_rows
|
149
|
+
serialize_variables.map do |p|
|
150
|
+
map_to_row p
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# @!visibility private
|
155
|
+
def self.get_import_rows(type)
|
156
|
+
case type
|
157
|
+
when :person then
|
158
|
+
Person.new
|
159
|
+
when :source_ref then
|
160
|
+
ReferenceToSource.new
|
161
|
+
when :note then
|
162
|
+
Note.new
|
163
|
+
when :address then
|
164
|
+
Address.new
|
165
|
+
when :organization then
|
166
|
+
Organization.new
|
167
|
+
when :coworker_reference then
|
168
|
+
CoworkerReference.new
|
169
|
+
when :organization_reference then
|
170
|
+
OrganizationReference.new
|
171
|
+
when :custom_field then
|
172
|
+
CustomField.new
|
173
|
+
when :custom_value then
|
174
|
+
CustomValue.new
|
175
|
+
when :custom_field_reference then
|
176
|
+
CustomFieldReference.new
|
177
|
+
when :settings then
|
178
|
+
Settings.new
|
179
|
+
when :class_settings then
|
180
|
+
ClassSettings.new
|
181
|
+
else
|
182
|
+
raise "Unknown type: #{type}"
|
183
|
+
end.get_import_rows
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module GoImport
|
5
|
+
class Sources
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
end
|
9
|
+
|
10
|
+
def list()
|
11
|
+
Dir.entries(@path).select {
|
12
|
+
|f| f != '.' && f != '..'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_project_from_source(project_name, source_name)
|
17
|
+
if !source_exists?(source_name)
|
18
|
+
puts "The source '#{source_name}' doesnt exist."
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
if project_exists?(project_name)
|
23
|
+
puts "A project named '#{project_name}' already exists"
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
copy_source_to_folder(source_name, project_name)
|
29
|
+
|
30
|
+
install_gems_for_project(project_name)
|
31
|
+
return true
|
32
|
+
rescue
|
33
|
+
puts "Something when wrong (errors should have been printed above)..."
|
34
|
+
FileUtils.remove_dir(project_name, true)
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def source_exists?(name)
|
41
|
+
source = list.find { |s| s.downcase == name.downcase }
|
42
|
+
|
43
|
+
return !source.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def project_exists?(name)
|
48
|
+
# do we have a folder named 'name' in the current folder?
|
49
|
+
project = Dir.entries(Dir.pwd).find { |f| f.downcase == name.downcase}
|
50
|
+
|
51
|
+
return !project.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def copy_source_to_folder(source_name, project_name)
|
56
|
+
puts "Trying to create project '#{project_name}' from source '#{source_name}'..."
|
57
|
+
FileUtils.cp_r File.expand_path(source_name, @path), project_name
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def install_gems_for_project(project_name)
|
62
|
+
puts "Trying to verify that all required gems are installed..."
|
63
|
+
Dir.chdir(File.expand_path(project_name, Dir.pwd)) do
|
64
|
+
exec_but_dont_show_unless_error('bundle install --verbose')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def exec_but_dont_show_unless_error(cmd)
|
70
|
+
std_out_value = []
|
71
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
72
|
+
while std_line = stdout.gets
|
73
|
+
std_out_value << std_line
|
74
|
+
end
|
75
|
+
|
76
|
+
exit_status = wait_thr.value
|
77
|
+
if !exit_status.success?
|
78
|
+
puts "Command '#{cmd}' failed with #{exit_status}"
|
79
|
+
puts "Output from command:"
|
80
|
+
puts std_out_value
|
81
|
+
|
82
|
+
raise "failed exec #{cmd}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require 'open3'
|
3
|
+
module GoImport
|
4
|
+
class Templating
|
5
|
+
def initialize(path)
|
6
|
+
@path = path
|
7
|
+
end
|
8
|
+
|
9
|
+
def list()
|
10
|
+
Dir.entries(@path).select { |d| d != '.' && d != '..' }
|
11
|
+
end
|
12
|
+
|
13
|
+
def unpack(name, path)
|
14
|
+
template = list.find { |t| t == name }
|
15
|
+
if template
|
16
|
+
unpackedname = name
|
17
|
+
|
18
|
+
puts "Unpacking template #{name} to #{path}"
|
19
|
+
FileUtils.cp_r File.expand_path(name, @path), path
|
20
|
+
|
21
|
+
# Now make sure all gems in template are installed
|
22
|
+
puts "Making sure all needed gems are present"
|
23
|
+
Dir.chdir(File.expand_path(unpackedname, path)) do
|
24
|
+
exec_but_dont_show_unless_error('bundle install --verbose')
|
25
|
+
end
|
26
|
+
true
|
27
|
+
else
|
28
|
+
puts "Unable to find template #{name}"
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def exec_but_dont_show_unless_error(cmd)
|
35
|
+
std_out_value = []
|
36
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
37
|
+
while std_line = stdout.gets
|
38
|
+
std_out_value << std_line
|
39
|
+
end
|
40
|
+
|
41
|
+
exit_status = wait_thr.value
|
42
|
+
if !exit_status.success?
|
43
|
+
puts "Failed with #{exit_status}"
|
44
|
+
puts "std_out_value"
|
45
|
+
puts std_out_value
|
46
|
+
|
47
|
+
raise "failed exec #{cmd}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/go_import.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module GoImport
|
2
|
+
private
|
3
|
+
def self.require_all_in(folder)
|
4
|
+
Dir.glob(File.join( File.dirname(File.absolute_path(__FILE__)),folder), &method(:require))
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'go_import/errors'
|
8
|
+
require 'go_import/serialize_helper'
|
9
|
+
require 'go_import/model_helpers'
|
10
|
+
#FruitToLime::require_all_in 'go_import/model/*.rb'
|
11
|
+
GoImport::require_all_in 'go_import/model/*.rb'
|
12
|
+
require 'go_import/csv_helper'
|
13
|
+
require 'go_import/roo_helper'
|
14
|
+
require 'go_import/phone_helper'
|
15
|
+
require 'go_import/email_helper'
|
16
|
+
require 'go_import/excel_helper'
|
17
|
+
require 'go_import/templating'
|
18
|
+
require 'go_import/source'
|
19
|
+
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,62 @@
|
|
1
|
+
|
2
|
+
require 'go_import'
|
3
|
+
require_relative("../converter")
|
4
|
+
|
5
|
+
# COWORKER_FILE and other file names should be defined ../converter.rb
|
6
|
+
|
7
|
+
def process_rows(file_name)
|
8
|
+
data = File.open(file_name, 'r').read.encode('UTF-8',"ISO-8859-1")
|
9
|
+
rows = GoImport::CsvHelper::text_to_hashes(data)
|
10
|
+
rows.each do |row|
|
11
|
+
yield row
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def convert_source
|
16
|
+
puts "Trying to convert CSV source to LIME Go..."
|
17
|
+
|
18
|
+
converter = Converter.new
|
19
|
+
|
20
|
+
# A rootmodel is used to represent all entitite/models that is
|
21
|
+
# exported
|
22
|
+
rootmodel = GoImport::RootModel.new
|
23
|
+
|
24
|
+
converter.configure(rootmodel)
|
25
|
+
|
26
|
+
# coworkers
|
27
|
+
# start with these since they are referenced
|
28
|
+
# from everywhere....
|
29
|
+
if defined?(COWORKER_FILE) && !COWORKER_FILE.nil? && !COWORKER_FILE.empty?
|
30
|
+
process_rows COWORKER_FILE do |row|
|
31
|
+
rootmodel.add_coworker(converter.to_coworker(row))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# organizations
|
36
|
+
if defined?(ORGANIZATION_FILE) && !ORGANIZATION_FILE.nil? && !ORGANIZATION_FILE.empty?
|
37
|
+
process_rows ORGANIZATION_FILE do |row|
|
38
|
+
rootmodel.add_organization(converter.to_organization(row, rootmodel))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# persons
|
43
|
+
# depends on organizations
|
44
|
+
if defined?(PERSON_FILE) && !PERSON_FILE.nil? && !PERSON_FILE.empty?
|
45
|
+
process_rows PERSON_FILE do |row|
|
46
|
+
# adds it self to the employer
|
47
|
+
converter.to_person(row, rootmodel)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# deals
|
52
|
+
# deals can reference coworkers (responsible), organizations
|
53
|
+
# and persons (contact)
|
54
|
+
if defined?(DEAL_FILE) && !DEAL_FILE.nil? && !DEAL_FILE.empty?
|
55
|
+
process_rows DEAL_FILE do |row|
|
56
|
+
rootmodel.add_deal(converter.to_deal(row, rootmodel))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
return rootmodel
|
61
|
+
end
|
62
|
+
|
data/sources/csv/Gemfile
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'go_import'
|
2
|
+
|
3
|
+
# This converter will convert one or more CVS files into a LIME Go XML
|
4
|
+
# file.
|
5
|
+
|
6
|
+
# You need to customize this script to suit your CVS file(s).
|
7
|
+
|
8
|
+
# First we set the file names of your CVS files. If you dont need to
|
9
|
+
# import all kind of objects, just leave the filename empty or remove
|
10
|
+
# the line.
|
11
|
+
COWORKER_FILE = "data/coworkers.csv"
|
12
|
+
ORGANIZATION_FILE = "data/organizations.csv"
|
13
|
+
PERSON_FILE = "data/persons.csv"
|
14
|
+
DEAL_FILE = "data/deals.csv"
|
15
|
+
|
16
|
+
# Ie if you dont want to import deals, set DEAL_FILE = ""
|
17
|
+
|
18
|
+
class Converter
|
19
|
+
# Configure your root model, add custom fields and deal statuses.
|
20
|
+
def configure(rootmodel)
|
21
|
+
# add custom field to your model here. Custom fields can be
|
22
|
+
# added to organization, deal and person. Valid types are
|
23
|
+
# :String and :Link. If no type is specified :String is used
|
24
|
+
# as default.
|
25
|
+
rootmodel.settings.with_organization do |organization|
|
26
|
+
organization.set_custom_field( { :integrationid => 'external_url', :title => 'Link to external system', :type => :Link } )
|
27
|
+
end
|
28
|
+
|
29
|
+
rootmodel.settings.with_deal do |deal|
|
30
|
+
deal.add_status({:label => "1. Kvalificering", :integration_id => "qualification"})
|
31
|
+
deal.add_status({:label => "Vunnen", :integration_id => "won",
|
32
|
+
:assessment => GoImport::DealState::PositiveEndState })
|
33
|
+
deal.add_status({:label => "Lost", :integration_id => "Lost",
|
34
|
+
:assessment => GoImport::DealState::NegativeEndState })
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Turns a row from the organization csv file into a
|
39
|
+
# GoImport::Organization.
|
40
|
+
# Use rootmodel to locate other related stuff such coworker
|
41
|
+
def to_organization(row, rootmodel)
|
42
|
+
organization = GoImport::Organization.new
|
43
|
+
# Integrationid is typically the id in the system that
|
44
|
+
# we are getting the csv from. Must be set to be able
|
45
|
+
# to import the same file more than once without
|
46
|
+
# creating duplicates
|
47
|
+
organization.integration_id = row['id']
|
48
|
+
organization.name = row['name']
|
49
|
+
|
50
|
+
# Just setting all basic properties to show whats available
|
51
|
+
# Remove or fix...
|
52
|
+
organization.organization_number = 'a number' # needs clean up, should have helpers for that in lib. Swedish format.
|
53
|
+
organization.email = 'email to organizaiton, not the person'
|
54
|
+
organization.web_site = 'www.whatever.com'
|
55
|
+
organization.central_phone_number = '0000' # needs clean up, should have helpers for that in lib. Default swedish format, convert to global format
|
56
|
+
|
57
|
+
# Addresses consists of several parts in Go.
|
58
|
+
# Lots of other systems have the address all in one
|
59
|
+
# line, to be able to match when importing it is
|
60
|
+
# way better to split the addresses
|
61
|
+
organization.with_visit_address do |address|
|
62
|
+
address.street = 'visit street'
|
63
|
+
address.zip_code = 'visit zip'
|
64
|
+
address.city = 'visit city'
|
65
|
+
end
|
66
|
+
|
67
|
+
# Another example of setting address using
|
68
|
+
# helper to split '226 48 LUND' into zip and city
|
69
|
+
organization.with_postal_address do |address|
|
70
|
+
address.street = 'postal street'
|
71
|
+
address.parse_zip_and_address_se '226 48 LUND'
|
72
|
+
end
|
73
|
+
|
74
|
+
# Responsible coworker is set by first locating
|
75
|
+
# it in the root model and then setting a reference
|
76
|
+
# to him/her
|
77
|
+
# We need to be able handle missing coworkers here
|
78
|
+
coworker = rootmodel.find_coworker_by_integration_id row['responsible_id']
|
79
|
+
organization.responsible_coworker = coworker.to_reference
|
80
|
+
|
81
|
+
# Tags are set and defined at the same place
|
82
|
+
# Setting a tag: Imported is useful for the user
|
83
|
+
organization.set_tag("Imported")
|
84
|
+
|
85
|
+
# When imported from web based ERP or similair that
|
86
|
+
# client will continue to use it can be useful to be
|
87
|
+
# able to link from Go to the same record in the ERP
|
88
|
+
# FOr instance Lime links
|
89
|
+
organization.set_custom_value("external_url", "http://something.com?key=#{row['id']}")
|
90
|
+
|
91
|
+
return organization
|
92
|
+
end
|
93
|
+
|
94
|
+
# Turns a row from the coworker csv file into a GoImport::Coworker.
|
95
|
+
def to_coworker(row)
|
96
|
+
coworker = GoImport::Coworker.new
|
97
|
+
coworker.integration_id = row['id']
|
98
|
+
coworker.first_name = row['first_name']
|
99
|
+
coworker.last_name = row['last_name']
|
100
|
+
|
101
|
+
# Other optional attributes
|
102
|
+
coworker.email = 't@e.com'
|
103
|
+
coworker.direct_phone_number = '+46121212'
|
104
|
+
coworker.mobile_phone_number = '+46324234'
|
105
|
+
coworker.home_phone_number = '+46234234'
|
106
|
+
|
107
|
+
# Tags and custom fields are set the same
|
108
|
+
# way as on organizations
|
109
|
+
|
110
|
+
return coworker
|
111
|
+
end
|
112
|
+
|
113
|
+
# Turns a row from the person csv file into a GoImport::Person.
|
114
|
+
#
|
115
|
+
# You MUST add the new person to an existing organization. Use the
|
116
|
+
# rootmodel to find the organization and then add the person with
|
117
|
+
# organization.add_employee
|
118
|
+
def to_person(row, rootmodel)
|
119
|
+
person = GoImport::Person.new
|
120
|
+
person.integration_id = row['id']
|
121
|
+
# Note that Go has separate first and last names
|
122
|
+
# Some splitting might be necessary
|
123
|
+
person.first_name = row['first_name']
|
124
|
+
person.last_name = row['last_name']
|
125
|
+
# other optional attributes
|
126
|
+
person.direct_phone_number = '+4611111'
|
127
|
+
person.fax_phone_number = '+4623234234234'
|
128
|
+
person.mobile_phone_number = '+462321212'
|
129
|
+
person.email = 'x@y.com'
|
130
|
+
person.alternative_email = 'y@x.com'
|
131
|
+
person.with_postal_address do |address|
|
132
|
+
address.street = 'postal street'
|
133
|
+
address.parse_zip_and_address_se '226 48 LUND'
|
134
|
+
end
|
135
|
+
|
136
|
+
# Tags and custom fields are set the same
|
137
|
+
# way as on organizations
|
138
|
+
|
139
|
+
# set employer connection
|
140
|
+
employer_id = row['employer_id']
|
141
|
+
employer = rootmodel.find_organization_by_integration_id employer_id
|
142
|
+
employer.add_employee person
|
143
|
+
end
|
144
|
+
|
145
|
+
# Turns a row form the deal csv file into a GoImport::Deal. Use
|
146
|
+
# the rootmodel to find objects that should be linked to the new
|
147
|
+
# deal.
|
148
|
+
def to_deal(row, rootmodel)
|
149
|
+
deal = GoImport::Deal.new
|
150
|
+
deal.integration_id = row['id']
|
151
|
+
deal.name = row['name']
|
152
|
+
# should be integer, same currency should be used in
|
153
|
+
# the system
|
154
|
+
deal.value = row['value']
|
155
|
+
|
156
|
+
# find stuff connected to deal
|
157
|
+
responsible = rootmodel.find_coworker_by_integration_id row['responsible_id']
|
158
|
+
organization = rootmodel.find_organization_by_integration_id row['customer_id']
|
159
|
+
person = organization.find_employee_by_integration_id row['customer_contact_id']
|
160
|
+
# connect the deal by references
|
161
|
+
deal.responsible_coworker = responsible.to_reference
|
162
|
+
deal.customer = organization.to_reference
|
163
|
+
deal.customer_contact = person.to_reference
|
164
|
+
|
165
|
+
# other optional attributes
|
166
|
+
deal.probability = 50 # should be between 0 - 100
|
167
|
+
deal.order_date = '2014-01-05' # Format ?
|
168
|
+
|
169
|
+
# status, set this by either label, id or integration_id (use
|
170
|
+
# appropriate method to find status)
|
171
|
+
deal.status = rootmodel.settings.deal.find_status_by_label row['status']
|
172
|
+
|
173
|
+
# or set by existing status, search by label, integration_id
|
174
|
+
# (if string) or id (if integer).
|
175
|
+
# deal.status = "Won"
|
176
|
+
|
177
|
+
return deal
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,17 @@
|
|
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', 'organizations.csv')
|
8
|
+
coworkers_file = File.join(File.dirname(__FILE__), 'sample_data', 'coworkers.csv')
|
9
|
+
persons_file = File.join(File.dirname(__FILE__), 'sample_data', 'persons.csv')
|
10
|
+
deals_file = File.join(File.dirname(__FILE__), 'sample_data', 'deals.csv')
|
11
|
+
@model = exporter.to_model(coworkers_file, organizations_file, persons_file, deals_file)
|
12
|
+
end
|
13
|
+
it "will find something with a name" do
|
14
|
+
organization = @model.organizations[0]
|
15
|
+
organization.name.length.should > 0
|
16
|
+
end
|
17
|
+
end
|