capsulecrmii 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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