capsulecrmii 0.0.5

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 (44) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +10 -0
  3. data/README.rdoc +33 -0
  4. data/Rakefile +9 -0
  5. data/capsulecrm.gemspec +23 -0
  6. data/examples.rb +82 -0
  7. data/lib/capsulecrm.rb +45 -0
  8. data/lib/capsulecrm/address.rb +23 -0
  9. data/lib/capsulecrm/base.rb +176 -0
  10. data/lib/capsulecrm/child.rb +24 -0
  11. data/lib/capsulecrm/child_collection.rb +14 -0
  12. data/lib/capsulecrm/collection.rb +14 -0
  13. data/lib/capsulecrm/contact.rb +27 -0
  14. data/lib/capsulecrm/custom_field.rb +41 -0
  15. data/lib/capsulecrm/email.rb +64 -0
  16. data/lib/capsulecrm/history.rb +32 -0
  17. data/lib/capsulecrm/history_item.rb +20 -0
  18. data/lib/capsulecrm/organisation.rb +41 -0
  19. data/lib/capsulecrm/party.rb +114 -0
  20. data/lib/capsulecrm/person.rb +126 -0
  21. data/lib/capsulecrm/phone.rb +15 -0
  22. data/lib/capsulecrm/record_not_found.rb +1 -0
  23. data/lib/capsulecrm/recorn_not_recognised.rb +1 -0
  24. data/lib/capsulecrm/tag.rb +12 -0
  25. data/lib/capsulecrm/version.rb +3 -0
  26. data/lib/capsulecrm/website.rb +19 -0
  27. data/test/create_person_test.rb +36 -0
  28. data/test/fixtures/responses/create_person.yml +59 -0
  29. data/test/fixtures/responses/party_history.yml +45 -0
  30. data/test/fixtures/responses/party_tags.yml +26 -0
  31. data/test/fixtures/responses/person_find_all.yml +28 -0
  32. data/test/fixtures/responses/person_find_all_with_limit.yml +26 -0
  33. data/test/fixtures/responses/person_find_all_with_offset.yml +28 -0
  34. data/test/fixtures/responses/person_find_by_id.yml +102 -0
  35. data/test/fixtures/responses/update_person.yml +85 -0
  36. data/test/fixtures/responses/update_person_without_changes.yml +28 -0
  37. data/test/party_dot_find_test.rb +40 -0
  38. data/test/party_dot_history_test.rb +29 -0
  39. data/test/party_dot_tags_test.rb +30 -0
  40. data/test/person_dot_find_all_test.rb +48 -0
  41. data/test/person_dot_find_by_id_test.rb +61 -0
  42. data/test/test_helper.rb +52 -0
  43. data/test/update_person_test.rb +46 -0
  44. metadata +131 -0
@@ -0,0 +1,14 @@
1
+ class CapsuleCRM::Collection < Array
2
+
3
+
4
+ # nodoc
5
+ def initialize(klass, data)
6
+ return if data.nil?
7
+ [data].flatten.each do |attributes|
8
+ attributes = klass.attributes_from_xml_hash(attributes)
9
+ self.push klass.new(attributes)
10
+ end
11
+ end
12
+
13
+
14
+ end
@@ -0,0 +1,27 @@
1
+ class CapsuleCRM::Contact < CapsuleCRM::Child
2
+
3
+ attr_accessor :type
4
+ define_attribute_methods [:type]
5
+
6
+ # nodoc
7
+ def attributes
8
+ attrs = {}
9
+ arr = [:type]
10
+ arr.each do |key|
11
+ attrs[key] = self.send(key)
12
+ end
13
+ attrs
14
+ end
15
+
16
+ # nodoc
17
+ def type=(value)
18
+ type_will_change! unless value == type
19
+ @type = value
20
+ end
21
+
22
+ # nodoc
23
+ def self.xml_map
24
+ map = {'type' => 'type'}
25
+ super.merge map
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ class CapsuleCRM::CustomField < CapsuleCRM::Child
2
+
3
+ attr_accessor :boolean
4
+ attr_accessor :date
5
+ attr_accessor :label
6
+ attr_accessor :text
7
+
8
+
9
+ # nodoc
10
+ def boolean=(value)
11
+ return @boolean = true if value.to_s == 'true'
12
+ @boolean = false
13
+ end
14
+
15
+
16
+ # nodoc
17
+ def date=(value)
18
+ value = Time.parse(value) if value.is_a?(String)
19
+ @date = value
20
+ end
21
+
22
+
23
+ # nodoc
24
+ def value
25
+ date || text || boolean
26
+ end
27
+
28
+
29
+ # nodoc
30
+ def self.xml_map
31
+ map = {
32
+ 'label' => 'label',
33
+ 'text' => 'text',
34
+ 'date' => 'date',
35
+ 'boolean' => 'boolean'
36
+ }
37
+ super.merge map
38
+ end
39
+
40
+
41
+ end
@@ -0,0 +1,64 @@
1
+ class CapsuleCRM::Email < CapsuleCRM::Contact
2
+
3
+ attr_accessor :address
4
+ define_attribute_methods [:address]
5
+
6
+
7
+ # nodoc
8
+ def attributes
9
+ attrs = {}
10
+ arr = [:address, :type]
11
+ arr.each do |key|
12
+ attrs[key] = self.send(key)
13
+ end
14
+ attrs
15
+ end
16
+
17
+ # nodoc
18
+ def address=(value)
19
+ address_will_change! unless value == address
20
+ @address = value
21
+ end
22
+
23
+ # nodoc
24
+ def dirty_attributes
25
+ Hash[attributes.select { |k,v| changed.include? k.to_s }]
26
+ end
27
+
28
+ def parent_type
29
+ return "person" if self.parent.class == CapsuleCRM::Person
30
+ return "organisation" if self.parent.class == CapsuleCRM::Organisation
31
+ raise "Unknown Parent Type"
32
+ end
33
+
34
+ # nodoc
35
+ def save
36
+ path = ["", "api", parent_type, self.parent.id].join("/")
37
+ options = {:root => 'person', :path => path}
38
+ attrs = new_record?? attributes : {:id => id}.merge(dirty_attributes)
39
+ success = self.class.update id, attrs, options
40
+ changed_attributes.clear if success
41
+ success
42
+ end
43
+
44
+ # uses xml_map() to convert :attributes into an xml string
45
+ def self.attributes_to_xml(attributes, root=nil)
46
+ xml = {"contacts" => {"email" => {}}}
47
+ map = xml_map.invert
48
+ attributes.each do |k,v|
49
+ key = map[k.to_s]
50
+ xml["contacts"]["email"][key] = v
51
+ end
52
+ xml.to_xml :root => root
53
+ end
54
+
55
+ # nodoc
56
+ def self.xml_map
57
+ map = {
58
+ 'emailAddress' => 'address'
59
+ }
60
+ super.merge map
61
+ end
62
+
63
+
64
+ end
@@ -0,0 +1,32 @@
1
+ module CapsuleCRM::History
2
+ # Reload history
3
+ def history!
4
+ @history = nil
5
+ history
6
+ end
7
+
8
+ # Load history if not loaded
9
+ def history
10
+ return @history if @history
11
+
12
+ path = self.class.get_path
13
+ path = [path, id, 'history'].join '/'
14
+ last_response = self.class.get(path)
15
+ data = last_response['history'].try(:[], 'historyItem')
16
+ @history = CapsuleCRM::HistoryItem.init_many(self, data)
17
+ end
18
+
19
+
20
+ def add_history(note)
21
+ if note
22
+ path = [self.class.get_path, self.id, 'history'].join '/'
23
+ self.class.create(Hash[{:note => note}], {:root => 'historyItem', :path => path})
24
+
25
+ # TODO : Should be optimized so it doesn't reload history each time
26
+ @history = nil
27
+ end
28
+ end
29
+
30
+ alias :add_note :add_history
31
+ end
32
+
@@ -0,0 +1,20 @@
1
+ class CapsuleCRM::HistoryItem < CapsuleCRM::Child
2
+ attr_reader :id
3
+ attr_accessor :type
4
+ attr_accessor :entry_date
5
+ attr_accessor :creator
6
+ attr_accessor :subject
7
+ attr_accessor :note
8
+
9
+ def self.xml_map
10
+ map = {
11
+ "id" => 'id',
12
+ "type" => 'type',
13
+ "entryDate" => 'entry_date',
14
+ "creator" => 'creator',
15
+ "subject" => 'subject',
16
+ "note" => 'note'
17
+ }
18
+ super.merge map
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ class CapsuleCRM::Organisation < CapsuleCRM::Party
2
+
3
+ attr_accessor :about
4
+ attr_accessor :name
5
+
6
+
7
+ # nodoc
8
+ def people
9
+ return @people if @people
10
+ path = self.class.get_path
11
+ path = [path, '/', id, '/people'].join
12
+ last_response = self.class.get(path)
13
+ @people = CapsuleCRM::Person.init_many(last_response)
14
+ end
15
+
16
+
17
+ # nodoc
18
+ def self.init_many(response)
19
+ data = response['parties']['organisation']
20
+ CapsuleCRM::Collection.new(self, data)
21
+ end
22
+
23
+
24
+ # nodoc
25
+ def self.init_one(response)
26
+ data = response['organisation']
27
+ new(attributes_from_xml_hash(data))
28
+ end
29
+
30
+
31
+ # nodoc
32
+ def self.xml_map
33
+ map = {
34
+ 'about' => 'about',
35
+ 'name' => 'name'
36
+ }
37
+ super.merge map
38
+ end
39
+
40
+
41
+ end
@@ -0,0 +1,114 @@
1
+ class CapsuleCRM::Party < CapsuleCRM::Base
2
+ include CapsuleCRM::History
3
+
4
+ # nodoc
5
+ def addresses
6
+ return @addresses if @addresses
7
+ data = raw_data['contacts'].try(:[], 'address')
8
+ @addresses = CapsuleCRM::Address.init_many(self, data)
9
+ end
10
+
11
+
12
+ # nodoc
13
+ def custom_fields
14
+ return @custom_fields if @custom_fields
15
+ path = self.class.get_path
16
+ path = [path, '/', id, '/customfield'].join
17
+ last_response = self.class.get(path)
18
+ data = last_response['customFields'].try(:[], 'customField')
19
+ @custom_fields = CapsuleCRM::CustomField.init_many(self, data)
20
+ end
21
+
22
+ def tags
23
+ return @tags if @tags
24
+ path = self.class.get_path
25
+ path = [path, '/', id, '/tag'].join
26
+ last_response = self.class.get(path)
27
+ data = last_response['tags'].try(:[], 'tag')
28
+ @tags = CapsuleCRM::Tag.init_many(self, data)
29
+ end
30
+
31
+ def tag_names
32
+ tags.map(&:name)
33
+ end
34
+
35
+ # nodoc
36
+ def emails
37
+ return @emails if @emails
38
+ data = raw_data['contacts'].try(:[], 'email')
39
+ @emails = CapsuleCRM::Email.init_many(self, data)
40
+ end
41
+
42
+
43
+ # nodoc
44
+ def phone_numbers
45
+ return @phone_numbers if @phone_numbers
46
+ data = raw_data['contacts'].try(:[], 'phone')
47
+ @phone_numbers = CapsuleCRM::Phone.init_many(self, data)
48
+ end
49
+
50
+ # nodoc
51
+ def websites
52
+ return @websites if @websites
53
+ data = raw_data['contacts'].try(:[], 'website')
54
+ @websites = CapsuleCRM::Website.init_many(self, data)
55
+ end
56
+
57
+ def is?(kind)
58
+ required_class = kind.to_s.camelize
59
+ self.class.to_s.include? required_class
60
+ end
61
+
62
+ def tag(value)
63
+ # unset tags so that if anyone were to request tags again, it
64
+ # requests an update from the server.
65
+ @tags = nil
66
+ path = self.class.get_path
67
+ tag = URI.escape(value.to_s)
68
+ path = [path, id, 'tag', tag].join('/')
69
+ req = self.class.post(path)
70
+ req.response.code == ("201" || "200")
71
+ end
72
+
73
+
74
+ def untag(value)
75
+ # unset tags so that if anyone were to request tags again, it
76
+ # requests an update from the server.
77
+ @tags = nil
78
+ path = self.class.get_path
79
+ tag = URI.escape(value.to_s)
80
+ path = [path, id, 'tag', tag].join('/')
81
+ req = self.class.delete(path)
82
+ req.response.code == "200"
83
+ end
84
+
85
+ # nodoc
86
+ def self.get_path
87
+ '/api/party'
88
+ end
89
+
90
+
91
+ def self.find_all_by_email(email, options={})
92
+ options[:email] = email
93
+ find_all(options)
94
+ end
95
+
96
+
97
+ # nodoc
98
+ def self.find_by_email(email)
99
+ find_all_by_email(email, :limit => 1, :offset => 0).first
100
+ end
101
+
102
+
103
+ # nodoc
104
+ def self.search(query, options={})
105
+ options[:q] = query
106
+ find_all(options)
107
+ end
108
+
109
+ def self.init_one(response)
110
+ return CapsuleCRM::Person.init_one(response) if response['person']
111
+ return CapsuleCRM::Organisation.init_one(response) if response['organisation']
112
+ raise CapsuleCRM::RecordNotRecognised, "Could not recognise returned entity type: #{response}"
113
+ end
114
+ end
@@ -0,0 +1,126 @@
1
+ class CapsuleCRM::Person < CapsuleCRM::Party
2
+
3
+ attr_accessor :about
4
+ attr_accessor :first_name
5
+ attr_accessor :job_title
6
+ attr_accessor :last_name
7
+ attr_accessor :organisation_id
8
+ attr_accessor :title
9
+ attr_accessor :note
10
+
11
+ define_attribute_methods [:about, :first_name, :last_name, :job_title, :organisation_id, :title]
12
+
13
+
14
+ # nodoc
15
+ def attributes
16
+ attrs = {}
17
+ arr = [:about, :first_name, :last_name, :title, :job_title]
18
+ arr.each do |key|
19
+ attrs[key] = self.send(key)
20
+ end
21
+ attrs
22
+ end
23
+
24
+
25
+ # nodoc
26
+ def first_name=(value)
27
+ first_name_will_change! unless value == first_name
28
+ @first_name = value
29
+ end
30
+
31
+
32
+ # nodoc
33
+ def last_name=(value)
34
+ last_name_will_change! unless value == last_name
35
+ @last_name = value
36
+ end
37
+
38
+
39
+ # nodoc
40
+ def title=(value)
41
+ title_will_change! unless value == title
42
+ @title = value
43
+ end
44
+
45
+
46
+ # nodoc
47
+ def organisation
48
+ return nil if organisation_id.nil?
49
+ @organisation ||= CapsuleCRM::Organisation.find(organisation_id)
50
+ end
51
+
52
+
53
+ # nodoc
54
+ def save
55
+ new_record?? create : update
56
+ end
57
+
58
+
59
+ private
60
+
61
+
62
+ # nodoc
63
+ def create
64
+ path = '/api/person'
65
+ options = {:root => 'person', :path => path}
66
+ new_id = self.class.create dirty_attributes, options
67
+ unless new_id
68
+ errors << self.class.last_response.response.message
69
+ return false
70
+ end
71
+ @errors = []
72
+ changed_attributes.clear
73
+ self.id = new_id
74
+ self
75
+ end
76
+
77
+
78
+ # nodoc
79
+ def dirty_attributes
80
+ Hash[attributes.select { |k,v| changed.include? k.to_s }]
81
+ end
82
+
83
+
84
+ # nodoc
85
+ def update
86
+ path = '/api/person/' + id.to_s
87
+ options = {:root => 'person', :path => path}
88
+ success = self.class.update id, dirty_attributes, options
89
+ changed_attributes.clear if success
90
+ success
91
+ end
92
+
93
+
94
+ # -- Class methods --
95
+
96
+
97
+ # nodoc
98
+ def self.init_many(response)
99
+ data = response['parties']['person']
100
+ CapsuleCRM::Collection.new(self, data)
101
+ end
102
+
103
+
104
+ # nodoc
105
+ def self.init_one(response)
106
+ data = response['person']
107
+ new(attributes_from_xml_hash(data))
108
+ end
109
+
110
+
111
+ # nodoc
112
+ def self.xml_map
113
+ map = {
114
+ 'about' => 'about',
115
+ 'firstName' => 'first_name',
116
+ 'jobTitle' => 'job_title',
117
+ 'lastName' => 'last_name',
118
+ 'organisationId' => 'organisation_id',
119
+ 'title' => 'title',
120
+ 'note' => 'note'
121
+ }
122
+ super.merge map
123
+ end
124
+
125
+
126
+ end