move-to-go 5.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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/bin/move-to-go +210 -0
  3. data/lib/move-to-go/can_become_immutable.rb +29 -0
  4. data/lib/move-to-go/csv_helper.rb +47 -0
  5. data/lib/move-to-go/email_helper.rb +14 -0
  6. data/lib/move-to-go/errors.rb +31 -0
  7. data/lib/move-to-go/excel_helper.rb +10 -0
  8. data/lib/move-to-go/global_phone.json +6571 -0
  9. data/lib/move-to-go/model/address.rb +63 -0
  10. data/lib/move-to-go/model/class_settings.rb +50 -0
  11. data/lib/move-to-go/model/clientvisit.rb +10 -0
  12. data/lib/move-to-go/model/comment.rb +10 -0
  13. data/lib/move-to-go/model/coworker.rb +82 -0
  14. data/lib/move-to-go/model/coworker_reference.rb +33 -0
  15. data/lib/move-to-go/model/customfield.rb +87 -0
  16. data/lib/move-to-go/model/deal.rb +216 -0
  17. data/lib/move-to-go/model/deal_class_settings.rb +97 -0
  18. data/lib/move-to-go/model/deal_state.rb +15 -0
  19. data/lib/move-to-go/model/deal_status.rb +23 -0
  20. data/lib/move-to-go/model/deal_status_reference.rb +47 -0
  21. data/lib/move-to-go/model/deal_status_setting.rb +49 -0
  22. data/lib/move-to-go/model/documents.rb +76 -0
  23. data/lib/move-to-go/model/file.rb +193 -0
  24. data/lib/move-to-go/model/history.rb +148 -0
  25. data/lib/move-to-go/model/history_classification.rb +26 -0
  26. data/lib/move-to-go/model/link.rb +82 -0
  27. data/lib/move-to-go/model/organization.rb +250 -0
  28. data/lib/move-to-go/model/person.rb +164 -0
  29. data/lib/move-to-go/model/referencetosource.rb +58 -0
  30. data/lib/move-to-go/model/relation.rb +23 -0
  31. data/lib/move-to-go/model/rootmodel.rb +663 -0
  32. data/lib/move-to-go/model/salescall.rb +10 -0
  33. data/lib/move-to-go/model/settings.rb +61 -0
  34. data/lib/move-to-go/model/tag.rb +35 -0
  35. data/lib/move-to-go/model/talkedto.rb +10 -0
  36. data/lib/move-to-go/model/triedtoreach.rb +10 -0
  37. data/lib/move-to-go/model_helpers.rb +97 -0
  38. data/lib/move-to-go/phone_helper.rb +75 -0
  39. data/lib/move-to-go/roo_helper.rb +82 -0
  40. data/lib/move-to-go/serialize_helper.rb +199 -0
  41. data/lib/move-to-go/shard_helper.rb +96 -0
  42. data/lib/move-to-go/source.rb +108 -0
  43. data/lib/move-to-go/templating.rb +52 -0
  44. data/lib/move-to-go.rb +20 -0
  45. data/sources/VISMA/.gitignore +14 -0
  46. data/sources/VISMA/.move-to-go/readme.txt +1 -0
  47. data/sources/VISMA/.move-to-go/runner.rb +89 -0
  48. data/sources/VISMA/Database/KONTAKT.DBF +0 -0
  49. data/sources/VISMA/Database/KUND.DBF +0 -0
  50. data/sources/VISMA/Gemfile +5 -0
  51. data/sources/VISMA/converter.rb +120 -0
  52. data/sources/base-crm/.move-to-go/runner.rb +235 -0
  53. data/sources/base-crm/Gemfile +5 -0
  54. data/sources/base-crm/README.md +9 -0
  55. data/sources/base-crm/converter.rb +56 -0
  56. data/sources/base-crm/data/contacts.csv +13 -0
  57. data/sources/base-crm/data/coworkers.csv +3 -0
  58. data/sources/base-crm/data/deals.csv +5 -0
  59. data/sources/base-crm/data/histories.csv +6 -0
  60. data/sources/base-crm/data/leads.csv +4 -0
  61. data/sources/base-crm/data/tasks.csv +5 -0
  62. data/sources/csv/.gitignore +14 -0
  63. data/sources/csv/.move-to-go/readme.txt +1 -0
  64. data/sources/csv/.move-to-go/runner.rb +65 -0
  65. data/sources/csv/Gemfile +5 -0
  66. data/sources/csv/converter.rb +218 -0
  67. data/sources/csv/data/coworkers.csv +2 -0
  68. data/sources/csv/data/deals.csv +2 -0
  69. data/sources/csv/data/organizations.csv +2 -0
  70. data/sources/csv/data/persons.csv +2 -0
  71. data/sources/custom/.gitignore +14 -0
  72. data/sources/custom/.move-to-go/readme.txt +1 -0
  73. data/sources/custom/.move-to-go/runner.rb +30 -0
  74. data/sources/custom/Gemfile +4 -0
  75. data/sources/custom/converter.rb +45 -0
  76. data/sources/excel/.gitignore +14 -0
  77. data/sources/excel/.move-to-go/readme.txt +3 -0
  78. data/sources/excel/.move-to-go/runner.rb +140 -0
  79. data/sources/excel/Gemfile +7 -0
  80. data/sources/excel/converter.rb +188 -0
  81. data/sources/excel/files/avtal.docx +0 -0
  82. data/sources/excel/files/more/avtal.docx +0 -0
  83. data/sources/excel/files/more/offert-2.pdf +0 -0
  84. data/sources/excel/files/offert-2.docx +0 -0
  85. data/sources/excel/files/offert.docx +0 -0
  86. data/sources/excel/sample-data.xlsx +0 -0
  87. data/sources/excel-basic/.gitignore +14 -0
  88. data/sources/excel-basic/.move-to-go/readme.txt +3 -0
  89. data/sources/excel-basic/.move-to-go/runner.rb +139 -0
  90. data/sources/excel-basic/Exempelfil.xlsx +0 -0
  91. data/sources/excel-basic/Gemfile +6 -0
  92. data/sources/excel-basic/converter.rb +175 -0
  93. data/sources/excel-basic/files/avtal.docx +0 -0
  94. data/sources/excel-basic/files/more/avtal.docx +0 -0
  95. data/sources/excel-basic/files/more/offert-2.pdf +0 -0
  96. data/sources/excel-basic/files/offert-2.docx +0 -0
  97. data/sources/excel-basic/files/offert.docx +0 -0
  98. data/sources/lime-crm-basic/.gitignore +14 -0
  99. data/sources/lime-crm-basic/.move-to-go/readme.txt +1 -0
  100. data/sources/lime-crm-basic/.move-to-go/runner.rb +524 -0
  101. data/sources/lime-crm-basic/Gemfile +6 -0
  102. data/sources/lime-crm-basic/converter.rb +396 -0
  103. data/sources/lime-easy/.gitignore +14 -0
  104. data/sources/lime-easy/.move-to-go/readme.txt +1 -0
  105. data/sources/lime-easy/.move-to-go/runner.rb +348 -0
  106. data/sources/lime-easy/Export/readme.txt +6 -0
  107. data/sources/lime-easy/Gemfile +5 -0
  108. data/sources/lime-easy/converter.rb +362 -0
  109. data/sources/salesforce/.gitignore +14 -0
  110. data/sources/salesforce/.move-to-go/readme.txt +1 -0
  111. data/sources/salesforce/.move-to-go/runner.rb +404 -0
  112. data/sources/salesforce/Gemfile +6 -0
  113. data/sources/salesforce/Gemfile.lock +48 -0
  114. data/sources/salesforce/converter.rb +113 -0
  115. data/sources/salesforce/export/readme.txt +3 -0
  116. data/spec/address_spec.rb +49 -0
  117. data/spec/class_settings_spec.rb +37 -0
  118. data/spec/coworker_spec.rb +94 -0
  119. data/spec/custom_field_spec.rb +22 -0
  120. data/spec/deal_class_settings_spec.rb +116 -0
  121. data/spec/deal_spec.rb +232 -0
  122. data/spec/deal_status_reference_spec.rb +17 -0
  123. data/spec/documents_spec.rb +64 -0
  124. data/spec/file_spec.rb +178 -0
  125. data/spec/helpers/csv_helper_spec.rb +45 -0
  126. data/spec/helpers/email_helper_spec.rb +37 -0
  127. data/spec/helpers/phone_helper_spec.rb +119 -0
  128. data/spec/helpers/roo_helper_spec.rb +10 -0
  129. data/spec/helpers/serialize_helper_spec.rb +253 -0
  130. data/spec/helpers/shard_helper_spec.rb +141 -0
  131. data/spec/helpers/xsd_validate_spec.rb +57 -0
  132. data/spec/history_spec.rb +150 -0
  133. data/spec/link_spec.rb +107 -0
  134. data/spec/organization_spec.rb +221 -0
  135. data/spec/person_spec.rb +129 -0
  136. data/spec/rootmodel_spec.rb +993 -0
  137. data/spec/spec_helper.rb +30 -0
  138. metadata +362 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 30c626193cc7bca95c36653b34caaf2bf9e7b593
4
+ data.tar.gz: 0ffa9010615f179ed02e9c0a51b7f9723eee3cfd
5
+ SHA512:
6
+ metadata.gz: 6338cf52b8472ffd1d4ccc2a494d2191549b27aa290e8feed5971e9716f7d9eac84662dc87a472c40b7830cbda310b1390209763fdaa03817116c22e11c42119
7
+ data.tar.gz: d961df52d8fa809abd86d355420da3eaf626b60a04a8bcac207829d911943cae79fe9b5c8eaa2ad01bba18232a60308bb00e03bc46c95a9182e7f2c3bc25ee43
data/bin/move-to-go ADDED
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require_relative '../lib/move-to-go'
5
+ require 'progress'
6
+
7
+
8
+ RUNNER_DIR = ".move-to-go"
9
+
10
+ class MoveToGoCommandLine < Thor
11
+
12
+ desc "about", "About move-to-go"
13
+ def about()
14
+ puts "move-to-go is an migration tool for LIME Go. It can take virtually any input source and create import data files that LIME Go likes."
15
+ puts "move-to-go has some predefined sources that will make it easy for you to migrate your data."
16
+ puts ""
17
+ end
18
+
19
+ desc "list-sources", "Lists the available sources"
20
+ def list_sources()
21
+ puts "The following sources are available:"
22
+ puts
23
+
24
+ sources = MoveToGo::Sources.new(source_path)
25
+ sources.list().each do |s|
26
+ puts "\t#{s}"
27
+ end
28
+
29
+ puts "\nCreate a new project with 'move-to-go new <PROJECT> <SOURCE>' with one of these sources."
30
+ puts "Use 'move-to-go about <SOURCE>' for more information about a specific source."
31
+ end
32
+
33
+ desc "about <SOURCE>", "Prints information about the specifed source"
34
+ def about(source)
35
+ sources = MoveToGo::Sources.new(source_path)
36
+
37
+ sources.about_source(source)
38
+ end
39
+
40
+ desc "new <PROJECT> <SOURCE>", "Creates a new migration project with a specifed name and source"
41
+ def new(project, source)
42
+ sources = MoveToGo::Sources.new(source_path)
43
+
44
+ if sources.create_project_from_source(project, source)
45
+ puts "\nProject '#{project}' created from source '#{source}'."
46
+ puts "Modify the #{project}/converter.rb script to suit your source."
47
+ puts "Use 'move-to-go run' from the project directory to create the zip file for LIME Go."
48
+ end
49
+ end
50
+
51
+ desc "run", "Executes the current project and create a go.zip file with data and files. Existing go.zip will be overwritten, use --output to specify a different filename."
52
+ option(:output,
53
+ :desc => "Name of the file where the converted source will be saved. This file should be sent to LIME Go. If the file already exist it will be replaced.",
54
+ :type => :string,
55
+ :required => false)
56
+ option(:ignore_invalid_files,
57
+ :desc => "Output will be created even if the import contains missing or invalid files",
58
+ :type => :boolean,
59
+ :required => false)
60
+ option(:log_to_file,
61
+ :desc => "Console output will be redirected to file",
62
+ :type => :string,
63
+ :required => false)
64
+ option(:max_file_size,
65
+ :desc => "Maximum size in bytes of documents included in zip",
66
+ :type => :numeric,
67
+ :required => false)
68
+ option(:output_documents,
69
+ :desc => "Name of the file to put imported documents in (default in same as --output)",
70
+ :type => :string,
71
+ :required => false)
72
+ option(:shard_size,
73
+ :desc => "Large imports are sharded into several zip-files. This property sets how many objects each zip-file should contain. Default is 25 000",
74
+ :type => :numeric,
75
+ :required => false)
76
+ def run_import()
77
+ if !options.log_to_file.nil?
78
+ $stdout = File.new(options.log_to_file == "log_to_file" ? "move-to-go.log" : options.log_to_file, 'w')
79
+ $stdout.sync = true
80
+ end
81
+ max_file_size = options.max_file_size.nil? ? MoveToGo::File::DEFAULT_MAX_FILE_SIZE : options.max_file_size
82
+
83
+ if !is_valid_project?
84
+ return
85
+ end
86
+
87
+ runner_file = ::File.expand_path("./#{RUNNER_DIR}/runner.rb", Dir.pwd)
88
+ require(runner_file)
89
+ model = convert_source()
90
+
91
+ if model.documents.files.length > 0 && (!defined?(FILES_FOLDER) || FILES_FOLDER.empty?())
92
+ puts "WARNING: It looks like you are importing files but FILES_FOLDER has not been set in your converter.rb."
93
+ puts "WARNING: FILES_FOLDER should be set unless you are only importing files with absolute paths."
94
+ end
95
+
96
+ if model.documents.files.length > 0 && (!defined?(FILES_FOLDER_AT_CUSTOMER) || FILES_FOLDER_AT_CUSTOMER.empty?())
97
+ puts "WARNING: It looks like you are importing files but FILES_FOLDER_AT_CUSTOMER has not been set in your converter.rb"
98
+ puts "WARNING: This means that files with an absolute path will be imported with their original path. Set this constant if you want to get files from the FILES_FOLDER directory."
99
+ end
100
+
101
+ is_ok, error_msg, warnings_msg = can_be_serialized?(model, options.ignore_invalid_files, max_file_size)
102
+ if is_ok
103
+
104
+ if options.ignore_invalid_files && model.documents.files.length > 0
105
+ log_and_remove_invalid_files model, max_file_size
106
+ end
107
+ model.report_rootmodel_status()
108
+
109
+ puts "Starting sharding of model..."
110
+ sharder = MoveToGo::ShardHelper.new(options.shard_size)
111
+ models_to_serialize = sharder.shard_model(model)
112
+
113
+ if models_to_serialize.length > 1
114
+ puts "Import is large and will be broken into #{models_to_serialize.length} files"
115
+ end
116
+
117
+ models_to_serialize.each_with_index do |model, i|
118
+ go_data_zip = options.output.nil? == true ? "go" : options.output
119
+ go_data_zip += "_#{i}.zip"
120
+ go_files = options.output_documents.nil? == true ? nil : ::File.basename(options.output_documents,File.extname(options.output_documents))
121
+ model.save_to_zip(go_data_zip, go_files)
122
+ puts "Source has been been converted into '#{go_data_zip}'."
123
+ puts " - and files into '#{go_files}.zip'." if !go_files.nil?
124
+ if !warnings_msg.empty?
125
+ puts "WARNINGS: "
126
+ puts warnings_msg
127
+ end
128
+ end
129
+ else
130
+ puts "ERROR: Source could not be converted due to:"
131
+ puts error_msg
132
+
133
+ if !options.ignore_invalid_files &&
134
+ model.documents.files.any? {|file| file.validate.empty?}
135
+ puts "move-to-go detected invalid files (see above), you can ignore these with the option --ignore-invalid-files."
136
+ end
137
+ end
138
+ end
139
+
140
+ private
141
+ def log_and_remove_invalid_files(model, max_file_size)
142
+ if model.documents.files.length > 0
143
+ file_log_header = "name;integration_id;path;organization.integrationid;organization.name;deal.integrationid;deal.name;file.size"
144
+ file_log = ""
145
+ files_to_remove = []
146
+ model.documents.files.with_progress(" - Trying to log files that can't be found...").each do |file|
147
+ if !::File.exists?(file.path_for_project)
148
+ file_log = "#{file_log}#{file.name};#{file.integration_id};#{file.path};#{file.organization.nil? ? '' : file.organization.integration_id};#{file.organization.nil? ? '' : file.organization.name};#{file.deal.nil? ? '' : file.deal.integration_id};#{file.deal.nil? ? '' : file.deal.name};0\n"
149
+ files_to_remove.push file
150
+ elsif ::File.size(file.path_for_project) > max_file_size
151
+ file_log = "#{file_log}#{file.name};#{file.integration_id};#{file.path};#{file.organization.nil? ? '' : file.organization.integration_id};#{file.organization.nil? ? '' : file.organization.name};#{file.deal.nil? ? '' : file.deal.integration_id};#{file.deal.nil? ? '' : file.deal.name};#{::File.size(file.path_for_project)}\n"
152
+ files_to_remove.push file
153
+ end
154
+ end
155
+
156
+ files_to_remove.each do |file|
157
+ model.documents.files.delete file
158
+ end
159
+
160
+ if file_log.length > 0
161
+ log_filename = 'move-to-go-invalid-files.csv'
162
+ ::File.open(log_filename, 'w') { |f|
163
+ f.puts file_log_header
164
+ f.puts file_log
165
+ }
166
+ puts "WARNING: move-to-go has invalid files (#{files_to_remove.length} of #{model.documents.files.length}). Filenames of all ignored files has been written to '#{log_filename}'."
167
+ else
168
+ puts "All files are OK."
169
+ end
170
+ end
171
+ end
172
+
173
+ private
174
+ def can_be_serialized?(rootmodel, ignore_invalid_files, max_file_size)
175
+ is_ok = false
176
+ error = rootmodel.sanity_check
177
+ if error.empty?
178
+ error, warnings = rootmodel.validate(ignore_invalid_files, max_file_size)
179
+
180
+ if error.empty?
181
+ is_ok = true
182
+ end
183
+ end
184
+
185
+ return [is_ok, error, warnings]
186
+ end
187
+
188
+ private
189
+ def is_valid_project?()
190
+ if Dir.exists?(RUNNER_DIR) == false
191
+ puts "This doesnt look like a move-to-go project. Are you in the right directory or did you mess with the '#{RUNNER_DIR}' folder?"
192
+ return false
193
+ end
194
+
195
+ runner_file = File.expand_path("./#{RUNNER_DIR}/runner.rb", Dir.pwd)
196
+ if File.exists?(runner_file) == false
197
+ puts "I can't run this project. Did you mess with the '#{RUNNER_DIR}' folder?"
198
+ return false
199
+ end
200
+
201
+ return true
202
+ end
203
+
204
+ private
205
+ def source_path()
206
+ File.expand_path("../sources", File.dirname(__FILE__))
207
+ end
208
+ end
209
+
210
+ MoveToGoCommandLine.start(ARGV)
@@ -0,0 +1,29 @@
1
+
2
+ module MoveToGo
3
+ class CanBecomeImmutable
4
+ def self.immutable_accessor(name)
5
+ define_method(name) do
6
+ return instance_variable_get("@#{name}")
7
+ end
8
+
9
+ define_method("#{name}=") do |value|
10
+ raise_if_immutable
11
+ instance_variable_set("@#{name}", value)
12
+ end
13
+ end
14
+
15
+ def raise_if_immutable
16
+ if @is_immutable
17
+ raise ObjectIsImmutableError
18
+ end
19
+ end
20
+
21
+ def set_is_immutable()
22
+ @is_immutable = true
23
+ end
24
+
25
+ def is_immutable()
26
+ @is_immutable
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require "csv"
2
+ module MoveToGo
3
+ module CsvHelper
4
+
5
+ # @example Detect column separator and transform to hashes
6
+ # hashes = MoveToGo::CsvHelper.text_to_hashes(text)
7
+ #
8
+ # @example Use specific column separator and transform to hashes
9
+ # column_separator = ','
10
+ # hashes = MoveToGo::CsvHelper.text_to_hashes(text, column_separator)
11
+ def self.text_to_hashes(text, column_separator = nil, row_separator = :auto, quote_char = '"')
12
+ if !text
13
+ raise "Missing text"
14
+ end
15
+
16
+ if !column_separator
17
+ column_separator = self.detect_col_sep text
18
+ end
19
+
20
+ rows = CSV.parse(text.strip,{:col_sep => column_separator,
21
+ :row_sep => row_separator, :quote_char => quote_char})
22
+ map = {}
23
+ first = rows.first
24
+ (0 .. first.length-1).each do |i|
25
+ map[i] = first[i]
26
+ end
27
+ rs = []
28
+ (1 .. rows.length-1).each do |i|
29
+ r={}
30
+ (0 .. map.length-1).each do |j|
31
+ r[map[j]] = rows[i][j]
32
+ end
33
+ rs.push(r)
34
+ end
35
+ return rs
36
+ end
37
+
38
+ private
39
+ def self.detect_col_sep(text)
40
+ firstline = text.split('\n').first
41
+ col_seps = [';','\t',',']
42
+ return col_seps.find do |c|
43
+ firstline.include? c
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,14 @@
1
+ require "sixarm_ruby_email_address_validation"
2
+
3
+ module MoveToGo
4
+ # The EmailHelper helps you validate email addresses.
5
+ class EmailHelper
6
+ def self.is_valid?(email)
7
+ begin
8
+ return (email =~ EmailAddressValidation::Pattern) ? true : false
9
+ rescue
10
+ return false
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ module MoveToGo
2
+ class AlreadyAddedError < StandardError
3
+ end
4
+
5
+ class IntegrationIdIsRequiredError < StandardError
6
+ end
7
+
8
+ class InvalidCustomFieldError < StandardError
9
+ end
10
+
11
+ class InvalidRelationError < StandardError
12
+ end
13
+
14
+ class InvalidValueError < StandardError
15
+ def initalize(value)
16
+ super("#{value} is not a valid value.")
17
+ end
18
+ end
19
+
20
+ class InvalidDealStatusError < StandardError
21
+ end
22
+
23
+ class InvalidHistoryClassificationError < StandardError
24
+ def initalize(classification)
25
+ super("#{classification} is not a valid history classification")
26
+ end
27
+ end
28
+
29
+ class ObjectIsImmutableError < StandardError
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ module MoveToGo
2
+ # The ExcelHelper just makes it a little bit easier to open an
3
+ # excel file in the imports. With ExcelHelper you don't need to
4
+ # know anything about Roo and RooHelper.
5
+ class ExcelHelper
6
+ def self.Open(excel_filename)
7
+ return RooHelper.new(Roo::Excelx.new(excel_filename))
8
+ end
9
+ end
10
+ end