fruit_to_lime 2.0.1 → 2.1.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/lib/fruit_to_lime.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  module FruitToLime
2
+ private
2
3
  def self.require_all_in(folder)
3
4
  Dir.glob(File.join( File.dirname(File.absolute_path(__FILE__)),folder), &method(:require))
4
5
  end
5
6
 
6
7
  require 'fruit_to_lime/serialize_helper'
7
- require 'fruit_to_lime/address_helper'
8
8
  require 'fruit_to_lime/model_helpers'
9
9
  FruitToLime::require_all_in 'fruit_to_lime/model/*.rb'
10
10
  require 'fruit_to_lime/csv_helper'
@@ -9,11 +9,14 @@ module FruitToLime
9
9
  def initialize()
10
10
  end
11
11
 
12
+ # What fields/rows on the class is supposed to be used by the Gem to generate the xml
13
+ # This method uses {#serialize_variables}. It also adds {#country_name} to be serialized
12
14
  def get_import_rows
13
15
  (serialize_variables+[{:id=>:country_name, :type=>:string}]).map do |p|
14
16
  map_to_row p
15
17
  end
16
18
  end
19
+ # Used as a convenience in order to get country code from internally used {#country_code}
17
20
  def country_name
18
21
  if @country_code
19
22
  IsoCountryCodes.find(@country_code).name
@@ -21,6 +24,8 @@ module FruitToLime
21
24
  nil
22
25
  end
23
26
  end
27
+
28
+ # Used as a convenience in order to map country name to the internal {#country_code}
24
29
  def country_name=(name)
25
30
  @country_code = case name
26
31
  when nil
@@ -31,8 +36,26 @@ module FruitToLime
31
36
  IsoCountryCodes.search_by_name(name).first.alpha2
32
37
  end
33
38
  end
39
+ # parses a line like "226 48 LUND" into its corresponding
40
+ # zipcode and city properties on the address
34
41
  def parse_zip_and_address_se(line)
35
- FruitToLime::AddressHelper::parse_line_to_zip_and_address_se(line, self)
42
+ Address.parse_line_to_zip_and_address_se(line, self)
43
+ end
44
+
45
+ private
46
+ def self.parse_line_to_zip_and_address_se(line, address)
47
+ matched_zipcode = /^\d{3}\s?\d{2}/.match(line)
48
+ if matched_zipcode && matched_zipcode.length == 1
49
+ address.zip_code = matched_zipcode[0].strip()
50
+ matched_city = /\D*$/.match(line)
51
+ if matched_city && matched_city.length == 1
52
+ address.city = matched_city[0].strip()
53
+ return address
54
+ end
55
+ end
56
+ return nil
36
57
  end
58
+
59
+
37
60
  end
38
61
  end
@@ -5,7 +5,7 @@ module FruitToLime
5
5
 
6
6
  attr_accessor :id, :integration_id, :name, :description, :probability, :value, :order_date, :offer_date, :customer,
7
7
  :responsible_coworker, :customer_contact, :status
8
-
8
+ # you add custom values by using {#set_custom_value}
9
9
  attr_reader :custom_values
10
10
 
11
11
  def serialize_variables
@@ -19,25 +19,6 @@ module FruitToLime
19
19
  def empty?
20
20
  return !@integration_id && !@id && !@heading
21
21
  end
22
-
23
- # *** TODO: delete this?
24
- def same_as_this_method()
25
- if @integration_id
26
- return lambda { |org|
27
- org.integration_id == @integration_id
28
- }
29
- elsif @id
30
- return lambda { |org|
31
- org.id == @id
32
- }
33
- elsif @heading
34
- return lambda { |org|
35
- org.heading == @heading
36
- }
37
- else
38
- raise "No reference!"
39
- end
40
- end
41
22
  end
42
23
 
43
24
  class Organization
@@ -89,7 +70,7 @@ module FruitToLime
89
70
  end
90
71
 
91
72
  def add_employee(val)
92
- @employees = [] if @employees==nil
73
+ @employees = [] if @employees == nil
93
74
  person = if val.is_a? Person then val else Person.new(val) end
94
75
  @employees.push(person)
95
76
  person
@@ -101,6 +82,12 @@ module FruitToLime
101
82
  coworker
102
83
  end
103
84
 
85
+ def find_employee_by_integration_id(integration_id)
86
+ return @employees.find do |e|
87
+ e.integration_id == integration_id
88
+ end
89
+ end
90
+
104
91
  def serialize_variables
105
92
  [
106
93
  { :id => :id, :type => :string },
@@ -127,7 +114,7 @@ module FruitToLime
127
114
  def to_s
128
115
  return "#{name}"
129
116
  end
130
-
117
+
131
118
  def validate
132
119
  error = String.new
133
120
 
@@ -14,19 +14,6 @@ module FruitToLime
14
14
  def empty?
15
15
  return !@integration_id && !@id
16
16
  end
17
- def same_as_this_method()
18
- if @integration_id
19
- return lambda { |person|
20
- person.integration_id == @integration_id
21
- }
22
- elsif @id
23
- return lambda { |person|
24
- person.id == @id
25
- }
26
- else
27
- raise "No reference!"
28
- end
29
- end
30
17
  end
31
18
 
32
19
  class Person < PersonReference
@@ -35,6 +22,7 @@ module FruitToLime
35
22
  :direct_phone_number, :fax_phone_number, :mobile_phone_number, :home_phone_number,
36
23
  :position, :email, :alternative_email, :postal_address, :currently_employed,
37
24
  :organization
25
+ # you add custom values by using {#set_custom_value}
38
26
  attr_reader :custom_values
39
27
 
40
28
  def initialize(opt = nil)
@@ -93,6 +81,13 @@ module FruitToLime
93
81
  ]
94
82
  end
95
83
 
84
+ def to_reference()
85
+ reference = PersonReference.new
86
+ reference.id = @id
87
+ reference.integration_id = @integration_id
88
+ return reference
89
+ end
90
+
96
91
  def get_import_rows
97
92
  (serialize_variables + [ { :id => :organization, :type => :organization_reference } ]).map do |p|
98
93
  map_to_row p
@@ -36,7 +36,7 @@ module FruitToLime
36
36
  end
37
37
  return @name == other.name && @id == other.id && @format== other.format
38
38
  end
39
-
39
+ # Sets the id of this instance to the parameter supplied. Will also set {#name} and {#format} so that this reference is identified as a PAR identifier by Go.
40
40
  def par_se(id)
41
41
  @name = 'pase'
42
42
  @format = 'External'
@@ -1,9 +1,12 @@
1
1
  # encoding: utf-8
2
2
  module FruitToLime
3
+ # The root model for Go import. This class is the container for everything else.
3
4
  class RootModel
4
5
  # the import_coworker is a special coworker that is set as
5
6
  # responsible for objects that requires a coworker, eg a note.
6
- attr_accessor :settings, :organizations, :coworkers, :deals, :notes, :import_coworker
7
+ attr_accessor :import_coworker
8
+
9
+ attr_accessor :settings, :organizations, :coworkers, :deals, :notes
7
10
  def serialize_variables
8
11
  [
9
12
  {:id => :settings, :type => :settings},
@@ -54,17 +57,6 @@ module FruitToLime
54
57
  yield note
55
58
  end
56
59
 
57
- # *** TODO:
58
- #
59
- # delete find_organization_by_reference and
60
- #same_as_this_method from organization?
61
- def find_organization_by_reference(organization_reference)
62
- same_as_this = organization_reference.same_as_this_method
63
- return @organizations.find do |org|
64
- same_as_this.call(org)
65
- end
66
- end
67
-
68
60
  def find_coworker_by_integration_id(integration_id)
69
61
  return @coworkers.find do |coworker|
70
62
  coworker == integration_id
@@ -77,6 +69,7 @@ module FruitToLime
77
69
  end
78
70
  end
79
71
 
72
+ # find deals for organization using {Organization#integration_id}
80
73
  def find_deals_for_organization(organization)
81
74
  deals = []
82
75
 
@@ -87,6 +80,7 @@ module FruitToLime
87
80
  return deals
88
81
  end
89
82
 
83
+ # Returns a string describing problems with the data. For instance if integration_id for any entity is not unique.
90
84
  def sanity_check
91
85
  error = String.new
92
86
 
@@ -113,7 +107,7 @@ module FruitToLime
113
107
 
114
108
  # returns all items from the object array with duplicate keys.
115
109
  # To get all organizations with the same integration_id use
116
- # get_duplicates(organizations, {|org| org.integration_id})
110
+ # `get_duplicates(organizations, {|org| org.integration_id})`
117
111
  def get_duplicates(objects, &key)
118
112
  uniq_items = objects.uniq {|item| key.call(item)}.compact
119
113
 
@@ -142,6 +136,7 @@ module FruitToLime
142
136
  return error.strip
143
137
  end
144
138
 
139
+ # @!visibility private
145
140
  def to_rexml(doc)
146
141
  element_name = serialize_name
147
142
  elem = doc.add_element(element_name,{"Version"=>"v2_0"})
@@ -3,6 +3,7 @@ module FruitToLime
3
3
  class Settings
4
4
  include SerializeHelper
5
5
  attr_reader :organization, :person, :deal
6
+
6
7
  def with_organization
7
8
  @organization = ClassSettings.new if @organization ==nil
8
9
  yield @organization
@@ -15,6 +16,7 @@ module FruitToLime
15
16
  @deal = ClassSettings.new if @deal ==nil
16
17
  yield @deal
17
18
  end
19
+
18
20
  def initialize(opt = nil)
19
21
  if opt != nil
20
22
  serialize_variables.each do |myattr|
@@ -13,7 +13,8 @@ module FruitToLime
13
13
  @value = val
14
14
  end
15
15
  end
16
-
16
+
17
+ # @!visibility private
17
18
  def to_rexml(elem)
18
19
  element_name = serialize_name
19
20
  elem.add_element(element_name).text = @value.to_s.encode('utf-8')
@@ -1,7 +1,7 @@
1
1
  module FruitToLime
2
2
  module ModelHasCustomFields
3
3
  def set_custom_value(value, field)
4
- @custom_values = [] if @custom_values==nil
4
+ @custom_values = [] if @custom_values == nil
5
5
  custom_value = CustomValue.new()
6
6
  custom_value.value = value
7
7
  custom_value.field = field
@@ -15,6 +15,7 @@ module FruitToLime
15
15
  @custom_values.push custom_value
16
16
  return custom_value
17
17
  end
18
+ # Note that this method is obsolete and will be removed later on. Please use {#set_custom_value}
18
19
  def set_custom_field(obj)
19
20
  value = obj[:value]
20
21
  ref = CustomFieldReference.new(obj)
@@ -23,6 +24,7 @@ module FruitToLime
23
24
  end
24
25
 
25
26
  module ModelWithIntegrationIdSameAs
27
+ # check if other is same as regarding integration_id or id
26
28
  def same_as?(other)
27
29
  if @integration_id!=nil && @integration_id == other.integration_id
28
30
  return true
@@ -34,14 +36,10 @@ module FruitToLime
34
36
  end
35
37
  end
36
38
 
37
- module ModelHasTags
38
- def add_tag(str)
39
- @tags = [] if @tags == nil
40
- @tags.push(Tag.new(str))
41
- end
39
+ module ModelHasTags
42
40
  def set_tag(str)
43
41
  @tags = [] if @tags == nil
44
- if ! @tags.any? {|tag| tag.value = str }
42
+ if ! @tags.any? {|tag| tag.value == str }
45
43
  @tags.push(Tag.new(str))
46
44
  end
47
45
  end
@@ -11,6 +11,7 @@ module FruitToLime
11
11
  SerializeHelper::serialize_to_file(file, self)
12
12
  end
13
13
 
14
+ # @!visibility private
14
15
  def self.serialize_variables_rexml(elem, obj)
15
16
  if (obj.respond_to?(:serialize_variables))
16
17
  obj.serialize_variables.each do |serialize_variable|
@@ -37,6 +38,7 @@ module FruitToLime
37
38
  raise "Do not know how to handle #{obj.class} !!"
38
39
  end
39
40
 
41
+ # @!visibility private
40
42
  def self.serialize_rexml(elem, obj)
41
43
  if obj.respond_to?(:to_rexml)
42
44
  obj.to_rexml(elem)
@@ -48,6 +50,7 @@ module FruitToLime
48
50
  end
49
51
  end
50
52
 
53
+ # @!visibility private
51
54
  def self.serialize(obj, indent= 2)
52
55
  # indent -1 to avoid indent
53
56
  if obj.respond_to?(:to_rexml)
@@ -66,16 +69,19 @@ module FruitToLime
66
69
  end
67
70
  end
68
71
 
72
+ # @!visibility private
69
73
  def self.serialize_to_file(file, obj)
70
74
  File.open(file, 'w') do |f|
71
75
  f.write(SerializeHelper::serialize(obj))
72
76
  end
73
77
  end
74
78
 
79
+ # @!visibility private
75
80
  def symbol_to_name(symbol)
76
81
  symbol.to_s.split('_').join(' ').capitalize
77
82
  end
78
83
 
84
+ # @!visibility private
79
85
  def map_symbol_to_row(symbol,type)
80
86
  {
81
87
  :id => symbol.to_s,
@@ -84,6 +90,7 @@ module FruitToLime
84
90
  }
85
91
  end
86
92
 
93
+ # @!visibility private
87
94
  def map_to_row(p)
88
95
  case p[:type]
89
96
  when :string then
@@ -136,12 +143,15 @@ module FruitToLime
136
143
  end
137
144
  end
138
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.
139
148
  def get_import_rows
140
149
  serialize_variables.map do |p|
141
150
  map_to_row p
142
151
  end
143
152
  end
144
153
 
154
+ # @!visibility private
145
155
  def self.get_import_rows(type)
146
156
  case type
147
157
  when :person then
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'fruit_to_lime'
3
3
 
4
- describe FruitToLime::AddressHelper do
4
+ describe FruitToLime::Address do
5
5
  describe "Parse line with swedish zip and city into zipcode" do
6
6
  let (:zip_code) {
7
7
  address = FruitToLime::Address.new
@@ -76,9 +76,9 @@ describe FruitToLime::SerializeHelper do
76
76
  addr.city = "Ankeborg"
77
77
  end
78
78
  p.currently_employed=true
79
- p.add_tag("tag:anka")
80
- p.add_tag("tag:Bj\u{00F6}rk")
81
- p.add_tag("tag:<Bj\u{00F6}rk>")
79
+ p.set_tag("tag:anka")
80
+ p.set_tag("tag:Bj\u{00F6}rk")
81
+ p.set_tag("tag:<Bj\u{00F6}rk>")
82
82
  p.set_custom_field({:integration_id=>"2", :value=>"cf value"})
83
83
  p.set_custom_field({:integration_id=>"3", :value=>"cf Bj\u{00F6}rk"})
84
84
  p.set_custom_field({:integration_id=>"4", :value=>"cf <Bj\u{00F6}rk>"})
@@ -127,8 +127,8 @@ describe FruitToLime::SerializeHelper do
127
127
  source.par_se('122345')
128
128
  end
129
129
  #o.source_ref = {:name=>'Go',:id=>"PASE122345"}
130
- o.add_tag("tag:bibliotek")
131
- o.add_tag("tag:Bj\u{00F6}rk")
130
+ o.set_tag("tag:bibliotek")
131
+ o.set_tag("tag:Bj\u{00F6}rk")
132
132
  o.set_custom_field({:integration_id=>"2", :value=>"cf value"})
133
133
  o.set_custom_field({:integration_id=>"3", :value=>"cf Bj\u{00F6}rk"})
134
134
  o.with_postal_address do |addr|
@@ -17,8 +17,8 @@ describe FruitToLime::SerializeHelper do
17
17
  source.par_se('122345')
18
18
  end
19
19
  #o.source_ref = {:name=>'Go',:id=>"PASE122345"}
20
- o.add_tag("tag:bibliotek")
21
- o.add_tag("tag:Bj\u{00F6}rk")
20
+ o.set_tag("tag:bibliotek")
21
+ o.set_tag("tag:Bj\u{00F6}rk")
22
22
  o.set_custom_field({:integration_id=>"2", :value=>"cf value"})
23
23
  o.set_custom_field({:integration_id=>"3", :value=>"cf Bj\u{00F6}rk"})
24
24
  o.with_postal_address do |addr|
@@ -0,0 +1,152 @@
1
+ <GoImport Version='v2_0'
2
+ ><Settings
3
+ ><Organization
4
+ ><CustomFields
5
+ ><CustomField
6
+ ><Title
7
+ >Link to external system</Title
8
+ ><Type
9
+ >Link</Type
10
+ ></CustomField
11
+ ></CustomFields
12
+ ></Organization
13
+ ></Settings
14
+ ><Coworkers
15
+ ><Coworker
16
+ ><IntegrationId
17
+ >import</IntegrationId
18
+ ><FirstName
19
+ >Import</FirstName
20
+ ></Coworker
21
+ ><Coworker
22
+ ><IntegrationId
23
+ >666</IntegrationId
24
+ ><FirstName
25
+ >Evil</FirstName
26
+ ><LastName
27
+ >Elvis</LastName
28
+ ><Email
29
+ >t@e.com</Email
30
+ ><DirectPhoneNumber
31
+ >+46121212</DirectPhoneNumber
32
+ ><MobilePhoneNumber
33
+ >+46324234</MobilePhoneNumber
34
+ ><HomePhoneNumber
35
+ >+46234234</HomePhoneNumber
36
+ ></Coworker
37
+ ></Coworkers
38
+ ><Organizations
39
+ ><Organization
40
+ ><IntegrationId
41
+ >6</IntegrationId
42
+ ><Name
43
+ >Alfs Mjukvaruutveckling</Name
44
+ ><OrganizationNumber
45
+ >a number</OrganizationNumber
46
+ ><PostalAddress
47
+ ><Street
48
+ >postal street</Street
49
+ ><ZipCode
50
+ >226 48</ZipCode
51
+ ><City
52
+ >LUND</City
53
+ ></PostalAddress
54
+ ><VisitAddress
55
+ ><Street
56
+ >visit street</Street
57
+ ><ZipCode
58
+ >visit zip</ZipCode
59
+ ><City
60
+ >visit city</City
61
+ ></VisitAddress
62
+ ><CentralPhoneNumber
63
+ >0000</CentralPhoneNumber
64
+ ><Email
65
+ >email to organizaiton, not the person</Email
66
+ ><WebSite
67
+ >www.whatever.com</WebSite
68
+ ><Employees
69
+ ><Person
70
+ ><IntegrationId
71
+ >123</IntegrationId
72
+ ><FirstName
73
+ >Rune</FirstName
74
+ ><LastName
75
+ >Rebellion</LastName
76
+ ><DirectPhoneNumber
77
+ >+4611111</DirectPhoneNumber
78
+ ><FaxPhoneNumber
79
+ >+4623234234234</FaxPhoneNumber
80
+ ><MobilePhoneNumber
81
+ >+462321212</MobilePhoneNumber
82
+ ><Email
83
+ >x@y.com</Email
84
+ ><AlternativeEmail
85
+ >y@x.com</AlternativeEmail
86
+ ><PostalAddress
87
+ ><Street
88
+ >postal street</Street
89
+ ><ZipCode
90
+ >226 48</ZipCode
91
+ ><City
92
+ >LUND</City
93
+ ></PostalAddress
94
+ ><CurrentlyEmployed
95
+ >true</CurrentlyEmployed
96
+ ></Person
97
+ ></Employees
98
+ ><CustomValues
99
+ ><CustomValue
100
+ ><Field
101
+ >external_url</Field
102
+ ><Value
103
+ >http://something.com?key=6</Value
104
+ ></CustomValue
105
+ ></CustomValues
106
+ ><Tags
107
+ ><Tag
108
+ >Imported</Tag
109
+ ></Tags
110
+ ><ResponsibleCoworker
111
+ ><Heading
112
+ >Evil Elvis</Heading
113
+ ><IntegrationId
114
+ >666</IntegrationId
115
+ ></ResponsibleCoworker
116
+ ></Organization
117
+ ></Organizations
118
+ ><Deals
119
+ ><Deal
120
+ ><IntegrationId
121
+ >333</IntegrationId
122
+ ><Name
123
+ >Feta affären</Name
124
+ ><Probability
125
+ >50</Probability
126
+ ><Value
127
+ >10000</Value
128
+ ><OfferDate
129
+ >2013-12-01</OfferDate
130
+ ><OrderDate
131
+ >2014-01-05</OrderDate
132
+ ><Customer
133
+ ><IntegrationId
134
+ >6</IntegrationId
135
+ ><Heading
136
+ >Alfs Mjukvaruutveckling</Heading
137
+ ></Customer
138
+ ><ResponsibleCoworker
139
+ ><Heading
140
+ >Evil Elvis</Heading
141
+ ><IntegrationId
142
+ >666</IntegrationId
143
+ ></ResponsibleCoworker
144
+ ><CustomerContact
145
+ ><IntegrationId
146
+ >123</IntegrationId
147
+ ></CustomerContact
148
+ ></Deal
149
+ ></Deals
150
+ ><Notes
151
+ /></GoImport
152
+ >
@@ -1,34 +1,192 @@
1
1
  require 'fruit_to_lime'
2
2
 
3
- class ToModel
4
- def to_organization(row)
3
+ class Exporter
4
+ # turns a row from the organization cssv file into
5
+ # a fruit_to_lime model that is used to generate xml
6
+ # Uses rootmodel to locate other related stuff such
7
+ # coworker
8
+ def to_organization(row, rootmodel)
5
9
  organization = FruitToLime::Organization.new
10
+ # Integrationid is typically the id in the system that
11
+ # we are getting the csv from. Must be set to be able
12
+ # to import the same file more than once without
13
+ # creating duplicates
6
14
  organization.integration_id = row['id']
7
15
  organization.name = row['name']
16
+ # Just setting all basic properties to show whats available
17
+ # Remove or fix...
18
+ organization.organization_number = 'a number' # needs clean up, should have helpers for that in lib. Swedish format.
19
+ organization.email = 'email to organizaiton, not the person'
20
+ organization.web_site = 'www.whatever.com'
21
+ organization.central_phone_number = '0000' # needs clean up, should have helpers for that in lib. Default swedish format, convert to global format
22
+
23
+ # Addresses consists of several parts in Go.
24
+ # Lots of other systems have the address all in one
25
+ # line, to be able to match when importing it is
26
+ # way better to split the addresses
27
+ organization.with_visit_address do |address|
28
+ address.street = 'visit street'
29
+ address.zip_code = 'visit zip'
30
+ address.city = 'visit city'
31
+ end
32
+
33
+ # Another example of setting address using
34
+ # helper to split '226 48 LUND' into zip and city
35
+ organization.with_postal_address do |address|
36
+ address.street = 'postal street'
37
+ address.parse_zip_and_address_se '226 48 LUND'
38
+ end
39
+
40
+ # Responsible coworker is set by first locating
41
+ # it in the root model and then setting a reference
42
+ # to him/her
43
+ # We need to be able handle missing coworkers here
44
+ coworker = rootmodel.find_coworker_by_integration_id row['responsible_id']
45
+ organization.responsible_coworker = coworker.to_reference
46
+
47
+ # Tags are set and defined at the same place
48
+ # Setting a tag: Imported is useful for the user
49
+ organization.set_tag("Imported")
50
+
51
+ # When imported from web based ERP or similair that
52
+ # client will continue to use it can be useful to be
53
+ # able to link from Go to the same record in the ERP
54
+ # FOr instance Lime links
55
+ organization.set_custom_value("http://something.com?key=#{row['id']}", "external_url")
56
+
8
57
  return organization
9
58
  end
10
59
 
60
+ def to_coworker(row)
61
+ coworker = FruitToLime::Coworker.new
62
+ coworker.integration_id = row['id']
63
+ coworker.first_name = row['first_name']
64
+ coworker.last_name = row['last_name']
65
+ # Other optional attributes
66
+ coworker.email = 't@e.com'
67
+ coworker.direct_phone_number = '+46121212'
68
+ coworker.mobile_phone_number = '+46324234'
69
+ coworker.home_phone_number = '+46234234'
70
+
71
+ # Tags and custom fields are set the same
72
+ # way as on organizations
73
+
74
+ return coworker
75
+ end
76
+
77
+ def to_person(row, rootmodel)
78
+ person = FruitToLime::Person.new
79
+ person.integration_id = row['id']
80
+ # Note that Go has separate first and last names
81
+ # Some splitting might be necessary
82
+ person.first_name = row['first_name']
83
+ person.last_name = row['last_name']
84
+ # other optional attributes
85
+ person.direct_phone_number = '+4611111'
86
+ person.fax_phone_number = '+4623234234234'
87
+ person.mobile_phone_number = '+462321212'
88
+ person.email = 'x@y.com'
89
+ person.alternative_email = 'y@x.com'
90
+ person.with_postal_address do |address|
91
+ address.street = 'postal street'
92
+ address.parse_zip_and_address_se '226 48 LUND'
93
+ end
94
+
95
+ # Tags and custom fields are set the same
96
+ # way as on organizations
97
+
98
+ # set employer connection
99
+ employer_id = row['employer_id']
100
+ employer = rootmodel.find_organization_by_integration_id employer_id
101
+ employer.add_employee person
102
+ end
103
+
104
+ def to_deal(row, rootmodel)
105
+ deal = FruitToLime::Deal.new
106
+ deal.integration_id = row['id']
107
+ deal.name = row['name']
108
+ # should be integer, same currency should be used in
109
+ # the system
110
+ deal.value = row['value']
111
+
112
+ # find stuff connected to deal
113
+ responsible = rootmodel.find_coworker_by_integration_id row['responsible_id']
114
+ organization = rootmodel.find_organization_by_integration_id row['customer_id']
115
+ person = organization.find_employee_by_integration_id row['customer_contact_id']
116
+ # connect the deal by references
117
+ deal.responsible_coworker = responsible.to_reference
118
+ deal.customer = organization.to_reference
119
+ deal.customer_contact = person.to_reference
120
+
121
+ # other optional attributes
122
+ deal.probability = 50 # should be between 0 - 100
123
+ deal.order_date = '2014-01-05' # Format ?
124
+ deal.offer_date = '2013-12-01' # Format ?
125
+
126
+ # status, how do we set this ?
127
+
128
+ return deal
129
+ end
130
+
11
131
  def configure(model)
12
132
  # add custom field to your model here. Custom fields can be
13
133
  # added to organization, deal and person. Valid types are
14
134
  # :String and :Link. If no type is specified :String is used
15
135
  # as default.
136
+ model.settings.with_organization do |organization|
137
+ organization.set_custom_field( { :integrationid => 'external_url', :title => 'Link to external system', :type => :Link } )
138
+ end
139
+ end
16
140
 
17
- model.settings.with_deal do |deal|
18
- deal.set_custom_field( { :integrationid => 'discount_url', :title => 'Rabatt url', :type => :Link } )
141
+ def process_rows(file_name)
142
+ data = File.open(file_name, 'r').read.encode('UTF-8',"ISO-8859-1")
143
+ rows = FruitToLime::CsvHelper::text_to_hashes(data)
144
+ rows.each do |row|
145
+ yield row
19
146
  end
20
147
  end
21
148
 
22
- def to_model(organization_file_name)
149
+ def to_model(coworkers_filename, organization_filename, persons_filename, deals_filename)
150
+ # A rootmodel is used to represent all entitite/models
151
+ # that is exported
23
152
  rootmodel = FruitToLime::RootModel.new
153
+
24
154
  configure rootmodel
25
- if organization_file_name != nil
26
- organization_file_data = File.open(organization_file_name, 'r').read.encode('UTF-8',"ISO-8859-1")
27
- rows = FruitToLime::CsvHelper::text_to_hashes(organization_file_data)
28
- rows.each do |row|
29
- rootmodel.organizations.push(to_organization(row))
155
+
156
+ # coworkers
157
+ # start with these since they are referenced
158
+ # from everywhere....
159
+ if coworkers_filename != nil
160
+ process_rows coworkers_filename do |row|
161
+ rootmodel.add_coworker(to_coworker(row))
162
+ end
163
+ end
164
+
165
+ # organizations
166
+ if organization_filename != nil
167
+ process_rows organization_filename do |row|
168
+ rootmodel.organizations.push(to_organization(row, rootmodel))
169
+ end
170
+ end
171
+
172
+ # persons
173
+ # depends on organizations
174
+ if persons_filename != nil
175
+ process_rows persons_filename do |row|
176
+ # adds it self to the employer
177
+ to_person(row, rootmodel)
30
178
  end
31
179
  end
180
+
181
+ # deals
182
+ # deals can reference coworkers (responsible), organizations
183
+ # and persons (contact)
184
+ if deals_filename != nil
185
+ process_rows deals_filename do |row|
186
+ rootmodel.deals.push(to_deal(row, rootmodel))
187
+ end
188
+ end
189
+
32
190
  return rootmodel
33
191
  end
34
192
 
@@ -44,24 +202,29 @@ require "fileutils"
44
202
  require 'pathname'
45
203
 
46
204
  class Cli < Thor
47
- desc "to_go ORGANIZATIONS FILE", "Exports xml to FILE using for ORGANIZATIONS csv file."
48
- def to_go(organizations, file = nil)
49
- file = 'export.xml' if file == nil
50
- toModel = ToModel.new()
51
- model = toModel.to_model(organizations)
205
+ desc "to_go", "Generates a Go XML file"
206
+ method_option :output, :desc => "Path to file where xml will be output", :default => "export.xml", :type => :string
207
+ method_option :organizations, :desc => "Path to organization csv file", :type => :string
208
+ method_option :persons, :desc => "Path to persons csv file", :type => :string
209
+ method_option :coworkers, :desc => "Path to coworkers csv file", :type => :string
210
+ method_option :deals, :desc => "Path to deals csv file", :type => :string
211
+ def to_go
212
+ output = options.output
213
+ exporter = Exporter.new()
214
+ model = exporter.to_model(options.coworkers, options.organizations, options.persons, options.deals)
52
215
  error = model.sanity_check
53
216
  if error.empty?
54
217
  validation_errors = model.validate
55
218
 
56
219
  if validation_errors.empty?
57
- model.serialize_to_file(file)
58
- puts "'#{organizations}' has been converted into '#{file}'."
220
+ model.serialize_to_file(output)
221
+ puts "Generated Go XML file: '#{output}'."
59
222
  else
60
- puts "'#{organizations}' could not be converted due to"
223
+ puts "Could not generate file due to"
61
224
  puts validation_errors
62
225
  end
63
226
  else
64
- puts "'#{organizations}' could not be converted due to"
227
+ puts "Could not generate file due to"
65
228
  puts error
66
229
  end
67
230
  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
@@ -0,0 +1,2 @@
1
+ id;first_name;last_name
2
+ 666;Evil;Elvis
@@ -0,0 +1,2 @@
1
+ id;name;value;responsible_id;customer_id;customer_contact_id
2
+ 333;Feta affären;10000;666;6;123
@@ -1,2 +1,2 @@
1
- id;name;
2
- 6;Alfs Mjukvaruutveckling
1
+ id;name;responsible_id
2
+ 6;Alfs Mjukvaruutveckling;666
@@ -0,0 +1,2 @@
1
+ id;employer_id;first_name;last_name
2
+ 123;6;Rune;Rebellion
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fruit_to_lime
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-04-10 00:00:00.000000000 Z
14
+ date: 2014-04-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: iso_country_codes
@@ -135,7 +135,6 @@ executables:
135
135
  extensions: []
136
136
  extra_rdoc_files: []
137
137
  files:
138
- - lib/fruit_to_lime/address_helper.rb
139
138
  - lib/fruit_to_lime/csv_helper.rb
140
139
  - lib/fruit_to_lime/model/address.rb
141
140
  - lib/fruit_to_lime/model/class_settings.rb
@@ -158,12 +157,16 @@ files:
158
157
  - lib/fruit_to_lime.rb
159
158
  - bin/fruit_to_lime
160
159
  - templates/csv/convert.rb
160
+ - templates/csv/export.xml
161
161
  - templates/csv/Gemfile
162
162
  - templates/csv/lib/tomodel.rb
163
163
  - templates/csv/Rakefile.rb
164
+ - templates/csv/spec/exporter_spec.rb
165
+ - templates/csv/spec/sample_data/coworkers.csv
166
+ - templates/csv/spec/sample_data/deals.csv
164
167
  - templates/csv/spec/sample_data/organizations.csv
168
+ - templates/csv/spec/sample_data/persons.csv
165
169
  - templates/csv/spec/spec_helper.rb
166
- - templates/csv/spec/tomodel_spec.rb
167
170
  - templates/excel/convert.rb
168
171
  - templates/excel/Gemfile
169
172
  - templates/excel/lib/tomodel.rb
@@ -177,8 +180,8 @@ files:
177
180
  - templates/sqlserver/Rakefile.rb
178
181
  - templates/sqlserver/spec/spec_helper.rb
179
182
  - templates/sqlserver/spec/tomodel_spec.rb
183
+ - spec/address_spec.rb
180
184
  - spec/custom_field_spec.rb
181
- - spec/helpers/address_helper_spec.rb
182
185
  - spec/helpers/csv_helper_spec.rb
183
186
  - spec/helpers/roo_helper_spec.rb
184
187
  - spec/helpers/serialize_helper_spec.rb
@@ -211,8 +214,8 @@ signing_key:
211
214
  specification_version: 3
212
215
  summary: Library to generate Lime Go xml import format
213
216
  test_files:
217
+ - spec/address_spec.rb
214
218
  - spec/custom_field_spec.rb
215
- - spec/helpers/address_helper_spec.rb
216
219
  - spec/helpers/csv_helper_spec.rb
217
220
  - spec/helpers/roo_helper_spec.rb
218
221
  - spec/helpers/serialize_helper_spec.rb
@@ -1,18 +0,0 @@
1
- module FruitToLime
2
- module AddressHelper
3
- # parses a line like "226 48 LUND" into its corresponding
4
- # zipcode and city properties on the address
5
- def self.parse_line_to_zip_and_address_se(line, address)
6
- matched_zipcode = /^\d{3}\s?\d{2}/.match(line)
7
- if matched_zipcode && matched_zipcode.length == 1
8
- address.zip_code = matched_zipcode[0].strip()
9
- matched_city = /\D*$/.match(line)
10
- if matched_city && matched_city.length == 1
11
- address.city = matched_city[0].strip()
12
- return address
13
- end
14
- end
15
- return nil
16
- end
17
- end
18
- end
@@ -1,14 +0,0 @@
1
- require 'spec_helper'
2
- require 'tomodel'
3
-
4
- describe 'ToModel' do
5
- before(:all) do
6
- toModel = ToModel.new
7
- organizations_file =File.join(File.dirname(__FILE__), 'sample_data', 'organizations.csv')
8
- @model = toModel.to_model(organizations_file)
9
- end
10
- it "will find something with a name" do
11
- organization = @model.organizations[0]
12
- organization.name.length.should > 0
13
- end
14
- end