move-to-go 5.0.11 → 5.4.1
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.
- checksums.yaml +5 -5
- data/bin/move-to-go +11 -1
- data/lib/move-to-go/model/file.rb +12 -7
- data/lib/move-to-go/model/history.rb +6 -1
- data/lib/move-to-go/model/history_classification.rb +3 -0
- data/lib/move-to-go/model/link.rb +12 -7
- data/lib/move-to-go/model/meeting.rb +219 -0
- data/lib/move-to-go/model/organization.rb +9 -1
- data/lib/move-to-go/model/person.rb +11 -1
- data/lib/move-to-go/model/rootmodel.rb +147 -5
- data/lib/move-to-go/model/todo.rb +182 -0
- data/lib/move-to-go/roo_helper.rb +7 -2
- data/lib/move-to-go/serialize_helper.rb +18 -0
- data/lib/move-to-go/shard_helper.rb +16 -0
- data/lib/move-to-go/source.rb +2 -0
- data/sources/excel/.move-to-go/runner.rb +48 -0
- data/sources/excel/converter.rb +61 -1
- data/sources/excel/sample-data.xlsx +0 -0
- data/sources/lime-easy/.move-to-go/runner.rb +149 -32
- data/sources/lime-easy/converter.rb +23 -7
- data/spec/file_spec.rb +27 -0
- data/spec/helpers/xsd_validate_spec.rb +87 -17
- data/spec/link_spec.rb +28 -2
- data/spec/meeting_spec.rb +152 -0
- data/spec/todo_spec.rb +149 -0
- metadata +12 -5
@@ -0,0 +1,182 @@
|
|
1
|
+
module MoveToGo
|
2
|
+
class Todo < CanBecomeImmutable
|
3
|
+
include SerializeHelper
|
4
|
+
##
|
5
|
+
# :attr_accessor: id
|
6
|
+
immutable_accessor :id
|
7
|
+
##
|
8
|
+
# :attr_accessor: integration_id
|
9
|
+
immutable_accessor :integration_id
|
10
|
+
|
11
|
+
attr_reader :text
|
12
|
+
attr_reader :date_start, :date_start_has_time, :date_checked
|
13
|
+
attr_reader :organization, :created_by, :assigned_coworker, :person, :deal
|
14
|
+
|
15
|
+
def initialize(opt = nil)
|
16
|
+
if !opt.nil?
|
17
|
+
serialize_variables.each do |myattr|
|
18
|
+
val = opt[myattr[:id]]
|
19
|
+
instance_variable_set("@" + myattr[:id].to_s, val) if val != nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def serialize_variables
|
25
|
+
[ :id, :text, :integration_id ].map {
|
26
|
+
|p| {
|
27
|
+
:id => p,
|
28
|
+
:type => :string
|
29
|
+
}
|
30
|
+
} +
|
31
|
+
[
|
32
|
+
{ :id => :date_start, :type => :datetime },
|
33
|
+
{ :id => :date_start_has_time, :type => :bool },
|
34
|
+
{ :id => :date_checked, :type => :datetime },
|
35
|
+
{ :id => :created_by_reference, :type => :coworker_reference, :element_name => :created_by },
|
36
|
+
{ :id => :assigned_coworker_reference, :type => :coworker_reference, :element_name => :assigned_coworker },
|
37
|
+
{ :id => :organization_reference, :type => :organization_reference, :element_name => :organization },
|
38
|
+
{ :id => :deal_reference, :type => :deal_reference, :element_name => :deal },
|
39
|
+
{ :id => :person_reference, :type => :person_reference, :element_name => :person }
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_import_rows
|
44
|
+
(serialize_variables + [
|
45
|
+
{ :id => :organization, :type => :organization_reference},
|
46
|
+
{ :id => :person, :type => :person_reference}
|
47
|
+
]).map do |p|
|
48
|
+
map_to_row p
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def serialize_name
|
53
|
+
"Todo"
|
54
|
+
end
|
55
|
+
|
56
|
+
def organization=(org)
|
57
|
+
raise_if_immutable
|
58
|
+
@organization_reference = OrganizationReference.from_organization(org)
|
59
|
+
|
60
|
+
if org.is_a?(Organization)
|
61
|
+
@organization = org
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def created_by=(coworker)
|
66
|
+
raise_if_immutable
|
67
|
+
@created_by_reference = CoworkerReference.from_coworker(coworker)
|
68
|
+
|
69
|
+
if coworker.is_a?(Coworker)
|
70
|
+
@created_by = coworker
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def assigned_coworker=(coworker)
|
75
|
+
raise_if_immutable
|
76
|
+
@assigned_coworker_reference = CoworkerReference.from_coworker(coworker)
|
77
|
+
|
78
|
+
if coworker.is_a?(Coworker)
|
79
|
+
@assigned_coworker = coworker
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def person=(person)
|
84
|
+
raise_if_immutable
|
85
|
+
@person_reference = PersonReference.from_person(person)
|
86
|
+
|
87
|
+
if person.is_a?(Person)
|
88
|
+
@person = person
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def deal=(deal)
|
93
|
+
raise_if_immutable
|
94
|
+
@deal_reference = DealReference.from_deal(deal)
|
95
|
+
|
96
|
+
if deal.is_a?(Deal)
|
97
|
+
@deal = deal
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def text=(text)
|
102
|
+
raise_if_immutable
|
103
|
+
@text = text
|
104
|
+
|
105
|
+
if @text.nil?
|
106
|
+
return
|
107
|
+
end
|
108
|
+
|
109
|
+
if @text.length == 0
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
@text.strip!
|
114
|
+
|
115
|
+
# remove form feeds
|
116
|
+
@text.gsub!("\f", "")
|
117
|
+
|
118
|
+
# remove vertical spaces
|
119
|
+
@text.gsub!("\v", "")
|
120
|
+
|
121
|
+
# remove backspace
|
122
|
+
@text.gsub!("\b", "")
|
123
|
+
end
|
124
|
+
|
125
|
+
def date_start=(datetime)
|
126
|
+
begin
|
127
|
+
@date_start = DateTime.parse(datetime)
|
128
|
+
rescue
|
129
|
+
puts "\nParsed datetime '#{datetime}' for date_start but got error"
|
130
|
+
raise
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def date_start_has_time=(bool)
|
135
|
+
@date_start_has_time = bool
|
136
|
+
end
|
137
|
+
|
138
|
+
def date_checked=(datetime)
|
139
|
+
if datetime.is_a?(DateTime)
|
140
|
+
@date_checked = datetime
|
141
|
+
return
|
142
|
+
end
|
143
|
+
|
144
|
+
begin
|
145
|
+
@date_checked = DateTime.parse(datetime) if datetime != ""
|
146
|
+
rescue
|
147
|
+
puts "\nParsed datetime '#{datetime}' for date_checked but got error"
|
148
|
+
raise
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def validate
|
153
|
+
error = String.new
|
154
|
+
|
155
|
+
if (@text.nil? || @text.empty?)
|
156
|
+
error = "Text is required for todo\n"
|
157
|
+
end
|
158
|
+
|
159
|
+
if @created_by.nil?
|
160
|
+
error = "#{error}Created_by is required for todo\n"
|
161
|
+
end
|
162
|
+
|
163
|
+
if @assigned_coworker_reference.nil?
|
164
|
+
error = "#{error}Assigned_coworker is required for todo\n"
|
165
|
+
end
|
166
|
+
|
167
|
+
if @date_start.nil?
|
168
|
+
error = "#{error}Date_start is required for todo\n"
|
169
|
+
end
|
170
|
+
|
171
|
+
if @date_start_has_time.nil?
|
172
|
+
error = "#{error}Date_start_has_time is required for todo\n"
|
173
|
+
end
|
174
|
+
|
175
|
+
if @organization.nil?
|
176
|
+
error = "#{error}Organization is required for todo\n"
|
177
|
+
end
|
178
|
+
|
179
|
+
return error
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require "csv"
|
2
|
+
require "roo"
|
3
|
+
include Roo::Formatters::Base
|
4
|
+
|
2
5
|
module MoveToGo
|
3
6
|
# @example transform xlsx file into rows
|
4
7
|
# organizations_path = File.join(File.dirname(__FILE__), 'organizations.xlsx') # same path as this file
|
@@ -34,7 +37,9 @@ module MoveToGo
|
|
34
37
|
def rows_for_sheet(sheet)
|
35
38
|
column_headers = {}
|
36
39
|
1.upto(@data.last_column(sheet)) do |col|
|
37
|
-
|
40
|
+
header = @data.cell(1, col, sheet)
|
41
|
+
raise "Missing header in row 1, col #{col} in sheet '#{sheet}'" if header == nil
|
42
|
+
column_headers[col] = header.encode('UTF-8')
|
38
43
|
end
|
39
44
|
|
40
45
|
rs = []
|
@@ -68,7 +73,7 @@ module MoveToGo
|
|
68
73
|
when :date, :datetime
|
69
74
|
onecell.to_s
|
70
75
|
when :time
|
71
|
-
|
76
|
+
integer_to_timestring(onecell)
|
72
77
|
when :formula
|
73
78
|
onecell.to_s
|
74
79
|
when :link
|
@@ -119,6 +119,20 @@ module MoveToGo
|
|
119
119
|
:type => p[:type],
|
120
120
|
:models => SerializeHelper.get_import_rows(:history)
|
121
121
|
}
|
122
|
+
when :todos then
|
123
|
+
{
|
124
|
+
:id => p[:id].to_s,
|
125
|
+
:name => symbol_to_name(p[:id]),
|
126
|
+
:type => p[:type],
|
127
|
+
:models => SerializeHelper.get_import_rows(:todo)
|
128
|
+
}
|
129
|
+
when :meetings then
|
130
|
+
{
|
131
|
+
:id => p[:id].to_s,
|
132
|
+
:name => symbol_to_name(p[:id]),
|
133
|
+
:type => p[:type],
|
134
|
+
:models => SerializeHelper.get_import_rows(:meeting)
|
135
|
+
}
|
122
136
|
when :tags then
|
123
137
|
{
|
124
138
|
:id => p[:id].to_s,
|
@@ -173,6 +187,10 @@ module MoveToGo
|
|
173
187
|
ReferenceToSource.new
|
174
188
|
when :history then
|
175
189
|
History.new
|
190
|
+
when :todo then
|
191
|
+
Todo.new
|
192
|
+
when :meeting then
|
193
|
+
Meeting.new
|
176
194
|
when :address then
|
177
195
|
Address.new
|
178
196
|
when :organization then
|
@@ -19,6 +19,8 @@ module MoveToGo
|
|
19
19
|
model.organizations.each{|key, org| add_organization(org)}
|
20
20
|
model.deals.each{|key, deal| add_deal(deal)}
|
21
21
|
model.histories.each{|key, history| add_history(history)}
|
22
|
+
model.todos.each{|key, todo| add_todo(todo)}
|
23
|
+
model.meetings.each{|key, meeting| add_meeting(meeting)}
|
22
24
|
add_documents(model.documents)
|
23
25
|
|
24
26
|
return_value = @shards
|
@@ -40,6 +42,20 @@ module MoveToGo
|
|
40
42
|
@current_shard_count += 1
|
41
43
|
end
|
42
44
|
|
45
|
+
private
|
46
|
+
def add_todo(todo)
|
47
|
+
check_or_create_new_chard()
|
48
|
+
@current_shard.add_todo(todo)
|
49
|
+
@current_shard_count += 1
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def add_meeting(meeting)
|
54
|
+
check_or_create_new_chard()
|
55
|
+
@current_shard.add_meeting(meeting)
|
56
|
+
@current_shard_count += 1
|
57
|
+
end
|
58
|
+
|
43
59
|
private
|
44
60
|
def add_deal(deal)
|
45
61
|
check_or_create_new_chard()
|
data/lib/move-to-go/source.rb
CHANGED
@@ -75,7 +75,9 @@ module MoveToGo
|
|
75
75
|
private
|
76
76
|
def copy_source_to_folder(source_name, project_name)
|
77
77
|
puts "Trying to create project '#{project_name}' from source '#{source_name}'..."
|
78
|
+
|
78
79
|
FileUtils.cp_r ::File.expand_path(source_name, @path), project_name
|
80
|
+
puts 'ok'
|
79
81
|
end
|
80
82
|
|
81
83
|
private
|
@@ -65,6 +65,22 @@ def convert_source
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
if defined?(TODO_SHEET)
|
69
|
+
if excel_workbook.has_sheet?(TODO_SHEET)
|
70
|
+
todo_rows = excel_workbook.rows_for_sheet TODO_SHEET
|
71
|
+
else
|
72
|
+
puts "WARNING: can't find sheet '#{TODO_SHEET}'"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if defined?(MEETING_SHEET)
|
77
|
+
if excel_workbook.has_sheet?(MEETING_SHEET)
|
78
|
+
meeting_rows = excel_workbook.rows_for_sheet MEETING_SHEET
|
79
|
+
else
|
80
|
+
puts "WARNING: can't find sheet '#{MEETING_SHEET}'"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
68
84
|
if defined?(FILE_SHEET)
|
69
85
|
if excel_workbook.has_sheet?(FILE_SHEET)
|
70
86
|
file_rows = excel_workbook.rows_for_sheet FILE_SHEET
|
@@ -73,6 +89,14 @@ def convert_source
|
|
73
89
|
end
|
74
90
|
end
|
75
91
|
|
92
|
+
if defined?(LINK_SHEET)
|
93
|
+
if excel_workbook.has_sheet?(LINK_SHEET)
|
94
|
+
link_rows = excel_workbook.rows_for_sheet LINK_SHEET
|
95
|
+
else
|
96
|
+
puts "WARNING: can't find sheet '#{LINK_SHEET}'"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
76
100
|
# Then we create a rootmodel that will contain all data that
|
77
101
|
# should be exported to LIME Go.
|
78
102
|
rootmodel = MoveToGo::RootModel.new
|
@@ -128,6 +152,24 @@ def convert_source
|
|
128
152
|
end
|
129
153
|
end
|
130
154
|
|
155
|
+
# Todo must be owned by a coworker and the be added to
|
156
|
+
# organizations
|
157
|
+
if defined?(todo_rows) && !todo_rows.nil?
|
158
|
+
puts "Trying to convert todos..."
|
159
|
+
todo_rows.with_progress().each do |row|
|
160
|
+
rootmodel.add_todo(converter.to_todo(row, rootmodel))
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Meeting must be owned by a coworker and the be added to
|
165
|
+
# organizations
|
166
|
+
if defined?(meeting_rows) && !meeting_rows.nil?
|
167
|
+
puts "Trying to convert meetings..."
|
168
|
+
meeting_rows.with_progress().each do |row|
|
169
|
+
rootmodel.add_meeting(converter.to_meeting(row, rootmodel))
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
131
173
|
if defined?(file_rows) && !file_rows.nil?
|
132
174
|
puts "Trying to convert files..."
|
133
175
|
file_rows.with_progress().each do |row|
|
@@ -135,6 +177,12 @@ def convert_source
|
|
135
177
|
end
|
136
178
|
end
|
137
179
|
|
180
|
+
if defined?(link_rows) && !link_rows.nil?
|
181
|
+
puts "Trying to convert links..."
|
182
|
+
link_rows.with_progress().each do |row|
|
183
|
+
rootmodel.add_link(converter.to_link(row, rootmodel))
|
184
|
+
end
|
185
|
+
end
|
138
186
|
return rootmodel
|
139
187
|
end
|
140
188
|
|
data/sources/excel/converter.rb
CHANGED
@@ -17,6 +17,9 @@ PERSON_SHEET = "Kontaktperson"
|
|
17
17
|
DEAL_SHEET = "Affär"
|
18
18
|
HISTORY_SHEET = "Anteckningar"
|
19
19
|
FILE_SHEET = "Dokument"
|
20
|
+
LINK_SHEET = "Links"
|
21
|
+
TODO_SHEET = "Att göra"
|
22
|
+
MEETING_SHEET = "Möten"
|
20
23
|
|
21
24
|
# Then you need to modify the script below according to the TODO
|
22
25
|
# comments.
|
@@ -140,6 +143,8 @@ class Converter
|
|
140
143
|
person.mobile_phone_number, person.direct_phone_number =
|
141
144
|
MoveToGo::PhoneHelper.parse_numbers(row['Telefon'], [",", "/", "\\"])
|
142
145
|
|
146
|
+
person.has_mail_consent = row['MailConsent'] == "Ja"
|
147
|
+
|
143
148
|
return person
|
144
149
|
end
|
145
150
|
|
@@ -160,8 +165,9 @@ class Converter
|
|
160
165
|
|
161
166
|
def to_file(row, rootmodel)
|
162
167
|
file = MoveToGo::File.new()
|
163
|
-
|
164
168
|
file.organization = rootmodel.find_organization_by_integration_id(row['Företag'])
|
169
|
+
file.person = rootmodel.find_person_by_integration_id(row['Person'])
|
170
|
+
file.deal = rootmodel.find_deal_by_integration_id(row['Affär'])
|
165
171
|
file.created_by = rootmodel.find_coworker_by_integration_id(row['Skapad Av'])
|
166
172
|
file.name = row['Namn']
|
167
173
|
file.description = row['Kommentar']
|
@@ -170,6 +176,60 @@ class Converter
|
|
170
176
|
return file
|
171
177
|
end
|
172
178
|
|
179
|
+
def to_link(row, rootmodel)
|
180
|
+
link = MoveToGo::Link.new()
|
181
|
+
|
182
|
+
link.organization = rootmodel.find_organization_by_integration_id(row['Företag'])
|
183
|
+
link.person = rootmodel.find_person_by_integration_id(row['Person'])
|
184
|
+
link.deal = rootmodel.find_deal_by_integration_id(row['Affär'])
|
185
|
+
link.created_by = rootmodel.find_coworker_by_integration_id(row['Skapad Av'])
|
186
|
+
link.name = row['Namn']
|
187
|
+
link.description = row['Kommentar']
|
188
|
+
link.url = row['URL']
|
189
|
+
|
190
|
+
return link
|
191
|
+
end
|
192
|
+
|
193
|
+
def to_todo(row, rootmodel)
|
194
|
+
todo = MoveToGo::Todo.new()
|
195
|
+
|
196
|
+
todo.text = row['Text']
|
197
|
+
todo.created_by = rootmodel.find_coworker_by_integration_id(row['Skapad Av'])
|
198
|
+
todo.organization = rootmodel.find_organization_by_integration_id(row['Företag'])
|
199
|
+
todo.person = rootmodel.find_person_by_integration_id(row['Person'])
|
200
|
+
todo.deal = rootmodel.find_deal_by_integration_id(row['Affär'])
|
201
|
+
todo.assigned_coworker = rootmodel.find_coworker_by_integration_id(row['Delegerad till'])
|
202
|
+
todo.date_checked = row['Avbockad']
|
203
|
+
|
204
|
+
if (row['Tid'].nil? || row['Tid'] == "")
|
205
|
+
todo.date_start = row['Datum']
|
206
|
+
todo.date_start_has_time = false
|
207
|
+
else
|
208
|
+
todo.date_start = "#{row['Datum']} #{row['Tid']}"
|
209
|
+
todo.date_start_has_time = true
|
210
|
+
end
|
211
|
+
|
212
|
+
return todo
|
213
|
+
end
|
214
|
+
|
215
|
+
def to_meeting(row, rootmodel)
|
216
|
+
meeting = MoveToGo::Meeting.new()
|
217
|
+
|
218
|
+
meeting.heading = row['Rubrik']
|
219
|
+
meeting.text = row['Text']
|
220
|
+
meeting.created_by = rootmodel.find_coworker_by_integration_id(row['Skapad Av'])
|
221
|
+
meeting.organization = rootmodel.find_organization_by_integration_id(row['Företag'])
|
222
|
+
meeting.person = rootmodel.find_person_by_integration_id(row['Person'])
|
223
|
+
meeting.deal = rootmodel.find_deal_by_integration_id(row['Affär'])
|
224
|
+
meeting.assigned_coworker = rootmodel.find_coworker_by_integration_id(row['Delegerad till'])
|
225
|
+
|
226
|
+
meeting.date_start = "#{row['Datum']} #{row['Tid']}"
|
227
|
+
meeting.date_start_has_time = true
|
228
|
+
meeting.date_stop = "#{row['Datum']} #{row['SlutTid']}"
|
229
|
+
|
230
|
+
return meeting
|
231
|
+
end
|
232
|
+
|
173
233
|
# HOOKS
|
174
234
|
#
|
175
235
|
# Sometimes you need to add exra information to the rootmodel, this can be done
|
Binary file
|