capsule_crm 0.8.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 970a6f5219598a75460554b8447b1feb07714674
4
- data.tar.gz: 483c4c0ec0f5fa7639f3c8788d91ce195c51bce5
3
+ metadata.gz: 9c9c330d4eeb07e7c78b092407c54bde1d851b7d
4
+ data.tar.gz: 745c544f60e55e8d7ce5aa9e8e3abdb79c80c0e2
5
5
  SHA512:
6
- metadata.gz: 540692d5ab936b2e828feae94611b02875aee983d2d1e70ccc807ea679ccb9a544e85ab0ddea973fce8f48f2541790f7fc701943eb5f9d33c8e4d91c615df074
7
- data.tar.gz: f7ef2803939afa2b25c5c43176c073cfc3c4412a16ef1347cb428ba15b88a67510bfbc142e85749a59edeab2ef700b138b15e564f45b145e20c692b50e235272
6
+ metadata.gz: c8643c862014d2c0fa7980d6f9c6cdc82279a4fa9e513b556012e1bb902f325a1b61fbeb107d1f92dd5b781c0ce7ab4d5592f55921337c1dd85b90676d78d3f0
7
+ data.tar.gz: ff1850b21048a9994f05b1678895b522089c24240329d436da85e852874986049b8d53217b7122612c14488a8c0105092d59e036c288e61b4f339fc1b6d17a79
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
1
  --color
2
- --format progress
2
+ --format documentation
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ ## 0.9.0
4
+
5
+ ### New Features
6
+
7
+ - Custom field support (@srbaker, @clod81)
8
+ - Add Organization#destroy (@danthompson)
9
+
10
+ ### Bug fixes
11
+
12
+ - Fixed init_collection method for when a single (#27) (@clod81)
data/README.md CHANGED
@@ -8,6 +8,8 @@ Version](https://badge.fury.io/rb/capsule_crm.png)](http://badge.fury.io/rb/caps
8
8
  Status](https://coveralls.io/repos/mattbeedle/capsule_crm/badge.png?branch=master)](https://coveralls.io/r/mattbeedle/capsule_crm)
9
9
  [![Dependency
10
10
  Status](https://gemnasium.com/mattbeedle/capsule_crm.png)](https://gemnasium.com/mattbeedle/capsule_crm)
11
+ [![Stories in
12
+ Ready](http://badge.waffle.io/mattbeedle/capsule_crm.png)](http://waffle.io/mattbeedle/capsule_crm)
11
13
 
12
14
  # CapsuleCRM
13
15
 
@@ -6,6 +6,7 @@ module CapsuleCRM
6
6
  include ActiveModel::Conversion
7
7
  include ActiveModel::Validations
8
8
 
9
+ include CapsuleCRM::Collection
9
10
  include CapsuleCRM::Associations::HasMany
10
11
  include CapsuleCRM::Associations::BelongsTo
11
12
  include CapsuleCRM::Taggable
@@ -254,9 +255,5 @@ module CapsuleCRM
254
255
  def update_record
255
256
  CapsuleCRM::Connection.put("/api/kase/#{id}", to_capsule_json)
256
257
  end
257
-
258
- def self.init_collection(results)
259
- CapsuleCRM::ResultsProxy.new(results.map { |item| new item })
260
- end
261
258
  end
262
- end
259
+ end
@@ -0,0 +1,9 @@
1
+ module CapsuleCRM::Collection
2
+ extend ActiveSupport::Concern
3
+
4
+ module ClassMethods
5
+ def init_collection(*collection)
6
+ collection.flatten.compact.map { |item| new item }
7
+ end
8
+ end
9
+ end
@@ -22,7 +22,7 @@ module CapsuleCRM
22
22
  end
23
23
 
24
24
  def self.put(path, params)
25
- faraday.put(path, params) do |request|
25
+ faraday.put(path, params.to_json) do |request|
26
26
  request.headers.update default_request_headers
27
27
  end.success?
28
28
  end
@@ -6,34 +6,89 @@ module CapsuleCRM
6
6
  include ActiveModel::Conversion
7
7
  include ActiveModel::Validations
8
8
 
9
+ include CapsuleCRM::Associations
10
+ include CapsuleCRM::Collection
11
+
9
12
  attribute :id, Integer
13
+ attribute :label, String
10
14
  attribute :date, DateTime
11
15
  attribute :tag, String
12
16
  attribute :boolean, Boolean
13
17
  attribute :text, String
14
- attribute :data_tag, String
18
+
19
+ validates :label, presence: true
20
+
21
+ belongs_to :party, class_name: 'CapsuleCRM::Party'
22
+
23
+ def self._for_party(party_id)
24
+ init_collection(
25
+ CapsuleCRM::Connection.
26
+ get("/api/party/#{party_id}/customfields")['customFields'].
27
+ fetch('customField', nil)
28
+ )
29
+ end
30
+
31
+ class << self
32
+ alias :_for_organization :_for_party
33
+ alias :_for_person :_for_party
34
+ end
35
+
36
+ def attributes=(attributes)
37
+ CapsuleCRM::HashHelper.underscore_keys!(attributes)
38
+ super(attributes)
39
+ self
40
+ end
15
41
 
16
42
  def self.create(attributes = {})
43
+ new(attributes).tap(&:save)
17
44
  end
18
45
 
19
46
  def self.create!(attribute = {})
47
+ new(attributes).tap(&:save)
20
48
  end
21
49
 
22
50
  def save
51
+ if valid?
52
+ update_record
53
+ else
54
+ false
55
+ end
23
56
  end
24
57
 
25
58
  def save!
59
+ if valid?
60
+ update_record
61
+ else
62
+ raise CapsuleCRM::Errors::RecordInvalid.new(self)
63
+ end
26
64
  end
27
65
 
28
66
  def destroy
29
67
  end
30
68
 
31
- private
32
-
33
- def create_record
69
+ def to_capsule_json
70
+ {
71
+ customFields: {
72
+ customField: [CapsuleCRM::HashHelper.camelize_keys(
73
+ {
74
+ id: id,
75
+ label: label,
76
+ date: date,
77
+ tag: tag,
78
+ boolean: boolean,
79
+ text: text,
80
+ }.delete_if { |key, value| value.blank? }
81
+ )]
82
+ }
83
+ }
34
84
  end
35
85
 
86
+ private
87
+
36
88
  def update_record
89
+ CapsuleCRM::Connection.post(
90
+ "/api/party/#{party.id}/customfields", to_capsule_json
91
+ )
37
92
  end
38
93
  end
39
- end
94
+ end
@@ -7,6 +7,7 @@ module CapsuleCRM
7
7
  include ActiveModel::Validations
8
8
 
9
9
  include CapsuleCRM::Associations
10
+ include CapsuleCRM::Collection
10
11
 
11
12
  attribute :id, Integer
12
13
  attribute :type, String
@@ -55,12 +56,6 @@ module CapsuleCRM
55
56
  )
56
57
  end
57
58
 
58
- def self.init_collection(collection)
59
- CapsuleCRM::ResultsProxy.new(
60
- [collection].flatten.delete_if(&:blank?).map { |item| new(item) }
61
- )
62
- end
63
-
64
59
  # Public: Underscore all of the attributes keys and set the attributes of
65
60
  # this history item
66
61
  #
@@ -355,4 +350,4 @@ module CapsuleCRM
355
350
  CapsuleCRM::Connection.put("/api/history/#{id}", to_capsule_json)
356
351
  end
357
352
  end
358
- end
353
+ end
@@ -2,6 +2,8 @@ module CapsuleCRM
2
2
  class Milestone
3
3
  include Virtus
4
4
 
5
+ include CapsuleCRM::Collection
6
+
5
7
  attribute :id, Integer
6
8
  attribute :name, String
7
9
  attribute :description, String
@@ -22,13 +24,5 @@ module CapsuleCRM
22
24
  def self.find_by_name(name)
23
25
  all.select { |item| item.name == name }.first
24
26
  end
25
-
26
- private
27
-
28
- def self.init_collection(collection)
29
- CapsuleCRM::ResultsProxy.new(
30
- collection.map { |attributes| new attributes }
31
- )
32
- end
33
27
  end
34
- end
28
+ end
@@ -6,8 +6,8 @@ module CapsuleCRM
6
6
  include ActiveModel::Conversion
7
7
  include ActiveModel::Validations
8
8
 
9
- include CapsuleCRM::Associations::HasMany
10
- include CapsuleCRM::Associations::BelongsTo
9
+ include CapsuleCRM::Associations
10
+ include CapsuleCRM::Collection
11
11
 
12
12
  attribute :id, Integer
13
13
  attribute :name, String
@@ -348,9 +348,5 @@ module CapsuleCRM
348
348
  CapsuleCRM::Connection.put("/api/opportunity/#{id}", attributes)
349
349
  self
350
350
  end
351
-
352
- def self.init_collection(collection)
353
- CapsuleCRM::ResultsProxy.new(collection.map { |item| new item })
354
- end
355
351
  end
356
- end
352
+ end
@@ -11,8 +11,9 @@ module CapsuleCRM
11
11
  include ActiveModel::Validations::Callbacks
12
12
 
13
13
  include CapsuleCRM::Associations::HasMany
14
- include CapsuleCRM::Taggable
14
+ include CapsuleCRM::Collection
15
15
  include CapsuleCRM::Contactable
16
+ include CapsuleCRM::Taggable
16
17
 
17
18
  attribute :id, Integer
18
19
  attribute :name, String
@@ -21,6 +22,7 @@ module CapsuleCRM
21
22
  validates :name, presence: true
22
23
 
23
24
  has_many :people, class_name: 'CapsuleCRM::Person', source: :organization
25
+ has_many :custom_fields, class_name: 'CapsuleCRM::CustomField', source: :organization
24
26
 
25
27
  # Public: Set the attributes of an organization
26
28
  #
@@ -227,12 +229,25 @@ module CapsuleCRM
227
229
  #
228
230
  # Returns a Hash
229
231
  def to_capsule_json
232
+ self.contacts = nil if self.contacts.blank?
230
233
  {
231
- organisation: attributes.merge(contacts: contacts.to_capsule_json).
234
+ organisation: attributes.merge(self.contacts ? {contacts: (self.contacts.is_a?(Hash) ? self.contacts : self.contacts.to_capsule_json)} : {}).
232
235
  stringify_keys
233
236
  }.stringify_keys
234
237
  end
235
238
 
239
+ # Public: Delete the organization in capsule
240
+ #
241
+ # Examples
242
+ #
243
+ # organization.destroy
244
+ #
245
+ # Return the CapsuleCRM::Organization
246
+ def destroy
247
+ self.id = nil if CapsuleCRM::Connection.delete("/api/party/#{id}")
248
+ self
249
+ end
250
+
236
251
  private
237
252
 
238
253
  def create_record
@@ -242,17 +257,8 @@ module CapsuleCRM
242
257
  end
243
258
 
244
259
  def update_record
245
- CapsuleCRM::Connection.put("/api/organisation/#{id}", attributes)
246
- end
247
-
248
- # Private: Build a ResultsProxy from a Array of CapsuleCRM::Organization
249
- # attributes
250
- #
251
- # collection - The Array of CapsuleCRM::Organization attributes hashes
252
- #
253
- # Returns a CapsuleCRM::ResultsProxy
254
- def self.init_collection(collection)
255
- CapsuleCRM::ResultsProxy.new(collection.map { |item| new item })
260
+ CapsuleCRM::Connection.put("/api/organisation/#{id}", to_capsule_json)
261
+ self
256
262
  end
257
263
  end
258
264
  end
@@ -2,6 +2,7 @@ module CapsuleCRM
2
2
  class Person < CapsuleCRM::Party
3
3
  include Virtus
4
4
 
5
+ include CapsuleCRM::Collection
5
6
  include CapsuleCRM::Contactable
6
7
  include CapsuleCRM::Associations::BelongsTo
7
8
 
@@ -20,6 +21,8 @@ module CapsuleCRM
20
21
  belongs_to :organization, class_name: 'CapsuleCRM::Organization',
21
22
  foreign_key: :organisation_id
22
23
 
24
+ has_many :custom_fields, class_name: 'CapsuleCRM::CustomField', source: :person
25
+
23
26
  validates :first_name, presence: { if: :first_name_required? }
24
27
  validates :last_name, presence: { if: :last_name_required? }
25
28
 
@@ -243,10 +246,11 @@ module CapsuleCRM
243
246
  #
244
247
  # Returns a Hash
245
248
  def to_capsule_json
249
+ self.contacts = nil if self.contacts.blank?
246
250
  {
247
251
  person: CapsuleCRM::HashHelper.camelize_keys(
248
252
  attributes.dup.delete_if { |key, value| value.blank? }.
249
- merge(contacts: contacts.to_capsule_json)
253
+ merge(self.contacts ? {contacts: (self.contacts.is_a?(Hash) ? self.contacts : self.contacts.to_capsule_json)} : {})
250
254
  )
251
255
  }.stringify_keys
252
256
  end
@@ -265,15 +269,6 @@ module CapsuleCRM
265
269
  self
266
270
  end
267
271
 
268
- # Private: Build a ResultsProxy from a Array of CapsuleCRM::Person attributes
269
- #
270
- # collection - The Array of CapsuleCRM::Person attributes hashes
271
- #
272
- # Returns a CapsuleCRM::ResultsProxy
273
- def self.init_collection(collection)
274
- CapsuleCRM::ResultsProxy.new(collection.map { |item| new item })
275
- end
276
-
277
272
  # Private: Determines whether the person first name is required. Either the
278
273
  # first or the last name is always required
279
274
  #
@@ -11,7 +11,7 @@ module CapsuleCRM
11
11
  def add_tag(tag_name)
12
12
  if id
13
13
  CapsuleCRM::Connection.post(
14
- "/api/#{api_singular_name}/#{id}/#{URI.encode(tag_name)}"
14
+ "/api/#{api_singular_name}/#{id}/tag/#{URI.encode(tag_name)}"
15
15
  )
16
16
  end
17
17
  end
@@ -19,13 +19,15 @@ module CapsuleCRM
19
19
  def remove_tag(tag_name)
20
20
  if id
21
21
  CapsuleCRM::Connection.delete(
22
- "/api/#{api_singular_name}/#{id}/#{URI.encode(tag_name)}"
22
+ "/api/#{api_singular_name}/#{id}/tag/#{URI.encode(tag_name)}"
23
23
  )
24
24
  end
25
25
  end
26
26
 
27
27
  def api_singular_name
28
- self.class.to_s.demodulize.downcase.singularize
28
+ class_name = self.class.superclass.to_s unless self.class.superclass == Object
29
+ class_name ||= self.class.to_s
30
+ class_name.demodulize.downcase.singularize
29
31
  end
30
32
  end
31
33
  end
@@ -7,6 +7,7 @@ module CapsuleCRM
7
7
  include ActiveModel::Validations
8
8
 
9
9
  include CapsuleCRM::Associations::BelongsTo
10
+ include CapsuleCRM::Collection
10
11
 
11
12
  attribute :id, Integer
12
13
  attribute :due_date, Date
@@ -147,10 +148,6 @@ module CapsuleCRM
147
148
  end
148
149
  end
149
150
 
150
- def self.init_collection(collection)
151
- CapsuleCRM::ResultsProxy.new(collection.map { |item| new item })
152
- end
153
-
154
151
  def create_record
155
152
  self.attributes = CapsuleCRM::Connection.post(
156
153
  create_url, to_capsule_json
@@ -175,4 +172,4 @@ module CapsuleCRM
175
172
  self
176
173
  end
177
174
  end
178
- end
175
+ end
@@ -1,3 +1,3 @@
1
1
  module CapsuleCrm
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end
data/lib/capsule_crm.rb CHANGED
@@ -4,6 +4,7 @@ require 'faraday_middleware'
4
4
  require 'virtus'
5
5
  require 'capsule_crm/capsule_jsonable'
6
6
  require 'capsule_crm/taggable'
7
+ require 'capsule_crm/collection'
7
8
  require 'capsule_crm/associations'
8
9
  require 'capsule_crm/address'
9
10
  require 'capsule_crm/case'
@@ -26,6 +27,7 @@ require 'capsule_crm/errors/record_invalid'
26
27
  require 'capsule_crm/contacts'
27
28
  require 'capsule_crm/contactable'
28
29
  require 'capsule_crm/configuration'
30
+ require 'capsule_crm/custom_field'
29
31
  require 'capsule_crm/opportunity'
30
32
  require 'capsule_crm/organization'
31
33
  require 'capsule_crm/participant'
@@ -0,0 +1,655 @@
1
+ require 'spec_helper'
2
+
3
+ describe CapsuleCRM::CustomField do
4
+ before { configure }
5
+
6
+ before do
7
+ stub_request(:get, /\/api\/users$/).
8
+ to_return(body: File.read('spec/support/all_users.json'))
9
+ stub_request(:get, /\/api\/opportunity\/milestones$/).
10
+ to_return(body: File.read('spec/support/milestones.json'))
11
+ end
12
+
13
+ it { should validate_presence_of(:label) }
14
+
15
+ describe '._for_party' do
16
+ let(:party) { Fabricate.build(:organization, id: 1) }
17
+
18
+ subject { CapsuleCRM::CustomField._for_party(party.id) }
19
+
20
+ context 'when there are some custom fields' do
21
+ before do
22
+ stub_request(:get, /\/api\/party\/#{party.id}\/customfields$/).
23
+ to_return(body: File.read('spec/support/all_customfields.json'))
24
+ end
25
+
26
+ it { should be_an(Array) }
27
+
28
+ it do
29
+ subject.all? { |item| item.is_a?(CapsuleCRM::CustomField) }.should be_true
30
+ end
31
+ end
32
+
33
+ context 'when there are no custom fields' do
34
+ before do
35
+ stub_request(:get, /\/api\/party\/#{party.id}\/customfields$/).
36
+ to_return(body: File.read('spec/support/no_customfields.json'))
37
+ end
38
+
39
+ it { should be_blank }
40
+ end
41
+ end
42
+
43
+ describe '.create' do
44
+ context 'when it belongs to a party' do
45
+ let(:organization) { Fabricate.build(:organization, id: 1) }
46
+ let(:location) { "https://sample.capsulecrm.com/api/party/#{organization.id}/customfields" }
47
+
48
+ subject do
49
+ CapsuleCRM::CustomField.create(
50
+ id: 100,
51
+ tag: 'The tag',
52
+ label: 'A field',
53
+ text: 'Some text',
54
+ date: Date.today,
55
+ boolean: true,
56
+ party: organization
57
+ )
58
+ end
59
+
60
+ before do
61
+ stub_request(:post, /\/api\/party\/#{organization.id}\/customfields$/).
62
+ to_return(headers: { 'Location' => location})
63
+ end
64
+
65
+ it { subject.id.should eql(100) }
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+
72
+
73
+ # describe '.create' do
74
+ # context 'when it belongs to a party' do
75
+ # let(:person) { Fabricate.build(:person, id: 1) }
76
+
77
+ # subject do
78
+ # CapsuleCRM::History.create(
79
+ # note: Faker::Lorem.paragraph, party: person
80
+ # )
81
+ # end
82
+
83
+ # let(:location) do
84
+ # "https://sample.capsulecrm.com/api/party/#{person.id}/history/101"
85
+ # end
86
+
87
+ # before do
88
+ # stub_request(:post, /\/api\/party\/#{person.id}\/history$/).
89
+ # to_return(headers: { 'Location' => location})
90
+ # end
91
+
92
+ # it { subject.id.should eql(101) }
93
+ # end
94
+
95
+
96
+
97
+ ####
98
+
99
+
100
+ # describe 'find' do
101
+ # before do
102
+ # stub_request(:get, /\/api\/history\/100$/).
103
+ # to_return(body: File.read('spec/support/history.json'))
104
+ # stub_request(:get, /\/api\/users$/).
105
+ # to_return(body: File.read('spec/support/all_users.json'))
106
+ # end
107
+
108
+ # subject { CapsuleCRM::History.find(100) }
109
+
110
+ # it { subject.type.should eql('Note') }
111
+
112
+ # it { subject.creator.should be_a(CapsuleCRM::User) }
113
+
114
+ # it { subject.entry_date.should_not be_blank }
115
+
116
+ # it { subject.subject.should_not be_blank }
117
+
118
+ # it { subject.note.should_not be_blank }
119
+
120
+ # it { subject.attachments.should be_a(Array) }
121
+
122
+ # it { subject.attachments.first.should be_a(CapsuleCRM::Attachment) }
123
+
124
+ # it { subject.attachments.first.filename.should eql('latin.doc') }
125
+
126
+ # it { subject.participants.should be_a(Array) }
127
+
128
+ # it { subject.participants.first.should be_a(CapsuleCRM::Participant) }
129
+
130
+ # it { subject.participants.first.name.should eql('Matt Beedle') }
131
+
132
+ # context 'when it belongs to a party' do
133
+ # before do
134
+ # stub_request(:get, /\/api\/party\/1$/).
135
+ # to_return(body: File.read('spec/support/person.json'))
136
+ # end
137
+
138
+ # it { subject.party_id.should_not be_blank }
139
+
140
+ # it { subject.party.should_not be_blank }
141
+ # end
142
+
143
+ # context 'when it belongs to a case' do
144
+ # before do
145
+ # stub_request(:get, /\/api\/kase\/5$/).
146
+ # to_return(body: File.read('spec/support/case.json'))
147
+ # end
148
+
149
+ # it { subject.case_id.should_not be_blank }
150
+
151
+ # it { subject.kase.should_not be_blank }
152
+ # end
153
+
154
+ # context 'when it belongs to an opportunity' do
155
+ # before do
156
+ # stub_request(:get, /\/api\/opportunity\/2$/).
157
+ # to_return(body: File.read('spec/support/opportunity.json'))
158
+ # end
159
+
160
+ # it { subject.opportunity_id.should_not be_blank }
161
+
162
+ # it { subject.opportunity.should_not be_blank }
163
+ # end
164
+ # end
165
+
166
+ # describe '#creator=' do
167
+ # let(:history) { CapsuleCRM::History.new }
168
+
169
+ # context 'when a String is supplied' do
170
+ # before do
171
+ # stub_request(:get, /\/api\/users$/).
172
+ # to_return(body: File.read('spec/support/all_users.json'))
173
+ # end
174
+
175
+ # context 'when the user exists' do
176
+ # before { history.creator = 'a.user' }
177
+
178
+ # it { history.creator.should be_a(CapsuleCRM::User) }
179
+ # end
180
+
181
+ # context 'when the user does not exist' do
182
+ # before { history.creator = 'asdfadsfdsaf' }
183
+
184
+ # it { history.creator.should be_blank }
185
+ # end
186
+ # end
187
+
188
+ # context 'when a CapsuleCRM::Person is supplied' do
189
+ # let(:user) { CapsuleCRM::User.new }
190
+
191
+ # before { history.creator = user }
192
+
193
+ # it { history.creator.should eql(user) }
194
+ # end
195
+ # end
196
+
197
+ # describe '.create' do
198
+ # context 'when it belongs to a party' do
199
+ # let(:person) { Fabricate.build(:person, id: 1) }
200
+
201
+ # subject do
202
+ # CapsuleCRM::History.create(
203
+ # note: Faker::Lorem.paragraph, party: person
204
+ # )
205
+ # end
206
+
207
+ # let(:location) do
208
+ # "https://sample.capsulecrm.com/api/party/#{person.id}/history/101"
209
+ # end
210
+
211
+ # before do
212
+ # stub_request(:post, /\/api\/party\/#{person.id}\/history$/).
213
+ # to_return(headers: { 'Location' => location})
214
+ # end
215
+
216
+ # it { subject.id.should eql(101) }
217
+ # end
218
+
219
+ # context 'when it belongs to a kase' do
220
+ # let(:kase) { Fabricate.build(:case, id: 2) }
221
+
222
+ # let(:location) do
223
+ # "https://sample.capsulecrm.com/api/kase/#{kase.id}/history/10"
224
+ # end
225
+
226
+ # subject do
227
+ # CapsuleCRM::History.create(note: Faker::Lorem.paragraph, kase: kase)
228
+ # end
229
+
230
+ # before do
231
+ # stub_request(:post, /\/api\/kase\/#{kase.id}\/history$/).
232
+ # to_return(headers: { 'Location' => location })
233
+ # end
234
+
235
+ # it { subject.id.should eql(10) }
236
+ # end
237
+
238
+ # context 'when it belongs to an opportunity' do
239
+ # let(:opportunity) { Fabricate.build(:opportunity, id: 1) }
240
+
241
+ # subject do
242
+ # CapsuleCRM::History.create(
243
+ # note: Faker::Lorem.paragraph, opportunity: opportunity
244
+ # )
245
+ # end
246
+
247
+ # let(:location) do
248
+ # [
249
+ # 'https://sample.capsulecrm.com/api/opportunity/',
250
+ # opportunity.id, '/history/9'
251
+ # ].join
252
+ # end
253
+
254
+ # before do
255
+ # stub_request(:post, /\/api\/opportunity\/#{opportunity.id}\/history$/).
256
+ # to_return(headers: { 'Location' => location })
257
+ # end
258
+
259
+ # it { subject.id.should eql(9) }
260
+ # end
261
+
262
+ # context 'when it is invalid' do
263
+ # subject { CapsuleCRM::History.create }
264
+
265
+ # it { should_not be_valid }
266
+ # end
267
+ # end
268
+
269
+ # describe '.create!' do
270
+ # context 'when it belongs to a party' do
271
+ # let(:person) { Fabricate.build(:person, id: 1) }
272
+
273
+ # subject do
274
+ # CapsuleCRM::History.create!(
275
+ # note: Faker::Lorem.paragraph, party: person
276
+ # )
277
+ # end
278
+
279
+ # let(:location) do
280
+ # "https://sample.capsulecrm.com/api/party/#{person.id}/history/101"
281
+ # end
282
+
283
+ # before do
284
+ # stub_request(:post, /\/api\/party\/#{person.id}\/history$/).
285
+ # to_return(headers: { 'Location' => location})
286
+ # end
287
+
288
+ # it { subject.id.should eql(101) }
289
+ # end
290
+
291
+ # context 'when it belongs to a kase' do
292
+ # let(:kase) { Fabricate.build(:case, id: 2) }
293
+
294
+ # let(:location) do
295
+ # "https://sample.capsulecrm.com/api/kase/#{kase.id}/history/10"
296
+ # end
297
+
298
+ # subject do
299
+ # CapsuleCRM::History.create!(note: Faker::Lorem.paragraph, kase: kase)
300
+ # end
301
+
302
+ # before do
303
+ # stub_request(:post, /\/api\/kase\/#{kase.id}\/history$/).
304
+ # to_return(headers: { 'Location' => location })
305
+ # end
306
+
307
+ # it { subject.id.should eql(10) }
308
+ # end
309
+
310
+ # context 'when it belongs to an opportunity' do
311
+ # let(:opportunity) { Fabricate.build(:opportunity, id: 1) }
312
+
313
+ # subject do
314
+ # CapsuleCRM::History.create!(
315
+ # note: Faker::Lorem.paragraph, opportunity: opportunity
316
+ # )
317
+ # end
318
+
319
+ # let(:location) do
320
+ # [
321
+ # 'https://sample.capsulecrm.com/api/opportunity/',
322
+ # opportunity.id, '/history/9'
323
+ # ].join
324
+ # end
325
+
326
+ # before do
327
+ # stub_request(:post, /\/api\/opportunity\/#{opportunity.id}\/history$/).
328
+ # to_return(headers: { 'Location' => location })
329
+ # end
330
+
331
+ # it { subject.id.should eql(9) }
332
+ # end
333
+
334
+ # context 'when it is invalid' do
335
+ # it do
336
+ # expect { CapsuleCRM::History.create! }.
337
+ # to raise_error(CapsuleCRM::Errors::RecordInvalid)
338
+ # end
339
+ # end
340
+ # end
341
+
342
+ # describe '#update_attributes' do
343
+ # context 'when the history is valid' do
344
+ # subject { Fabricate(:history, id: 2, party: Fabricate.build(:person)) }
345
+
346
+ # before do
347
+ # stub_request(:put, /api\/history\/2$/).to_return(status: 200)
348
+ # subject.update_attributes note: 'changed note text'
349
+ # end
350
+
351
+ # it { subject.note.should eql('changed note text') }
352
+
353
+ # it { should be_persisted }
354
+ # end
355
+
356
+ # context 'when the history is not valid' do
357
+ # subject do
358
+ # CapsuleCRM::History.new(id: 2)
359
+ # end
360
+
361
+ # before { subject.update_attributes subject: Faker::Lorem.sentence }
362
+
363
+ # it { subject.should_not be_valid }
364
+ # end
365
+ # end
366
+
367
+ # describe '#update_attributes!' do
368
+ # context 'when it is valid' do
369
+ # subject { Fabricate(:history, id: 3, party: Fabricate.build(:case)) }
370
+
371
+ # before do
372
+ # stub_request(:put, /api\/history\/3$/).to_return(status: 200)
373
+ # subject.update_attributes! note: 'some new note'
374
+ # end
375
+
376
+ # it { subject.note.should eql('some new note') }
377
+
378
+ # it { should be_persisted }
379
+ # end
380
+
381
+ # context 'when it is not valid' do
382
+ # subject { CapsuleCRM::History.new(id: 3) }
383
+
384
+ # it do
385
+ # expect { subject.update_attributes! subject: 'test' }.
386
+ # to raise_error(CapsuleCRM::Errors::RecordInvalid)
387
+ # end
388
+ # end
389
+ # end
390
+
391
+ # describe '#save' do
392
+ # context 'when it is a new record' do
393
+ # let(:history) { Fabricate.build(:history) }
394
+
395
+ # context 'when it belongs to a party' do
396
+ # let(:party) { Fabricate.build(:organization, id: 2) }
397
+
398
+ # let(:location) do
399
+ # "https://sample.capsulecrm.com/api/party/#{party.id}/history/101"
400
+ # end
401
+
402
+ # before do
403
+ # history.party = party
404
+ # stub_request(:post, /\/api\/party\/#{party.id}\/history$/).
405
+ # to_return(headers: { 'Location' => location })
406
+ # history.save
407
+ # end
408
+
409
+ # it { history.id.should eql(101) }
410
+
411
+ # it { history.should be_persisted }
412
+ # end
413
+
414
+ # context 'when it belongs to a kase' do
415
+ # let(:kase) { Fabricate.build(:case, id: 5) }
416
+
417
+ # let(:location) do
418
+ # "https://sample.capsulecrm.com/api/kase/#{kase.id}/history/10005"
419
+ # end
420
+
421
+ # before do
422
+ # history.kase = kase
423
+ # stub_request(:post, /\/api\/kase\/#{kase.id}\/history$/).
424
+ # to_return(headers: { 'Location' => location })
425
+ # history.save
426
+ # end
427
+
428
+ # it { history.id.should eql(10005) }
429
+
430
+ # it { history.should be_persisted }
431
+ # end
432
+
433
+ # context 'when it belongs to an opportunity' do
434
+ # let(:opportunity) { Fabricate.build(:opportunity, id: 3) }
435
+
436
+ # let(:location) do
437
+ # [
438
+ # 'https://sample.capsulecrm.com/api/opportunity/',
439
+ # opportunity.id, '/history/101'
440
+ # ].join
441
+ # end
442
+
443
+ # before do
444
+ # history.opportunity = opportunity
445
+ # stub_request(
446
+ # :post, /\/api\/opportunity\/#{opportunity.id}\/history$/
447
+ # ).to_return(headers: { 'Location' => location })
448
+ # history.save
449
+ # end
450
+
451
+ # it { history.id.should eql(101) }
452
+
453
+ # it { history.should be_persisted }
454
+ # end
455
+ # end
456
+
457
+ # context 'when it is an existing record' do
458
+ # let(:history) do
459
+ # Fabricate.build(:history, party: Fabricate.build(:person), id: 10)
460
+ # end
461
+
462
+ # before do
463
+ # stub_request(:put, /\/api\/history\/#{history.id}$/).
464
+ # to_return(status: 200)
465
+ # history.save
466
+ # end
467
+
468
+ # it { history.should be_persisted }
469
+ # end
470
+ # end
471
+
472
+ # describe '#save!' do
473
+ # context 'when it is a new record' do
474
+ # context 'when it is invalid' do
475
+ # let(:history) { CapsuleCRM::History.new(id: 5) }
476
+
477
+ # it 'should raise an error' do
478
+ # expect { history.save! }.
479
+ # to raise_error(CapsuleCRM::Errors::RecordInvalid)
480
+ # end
481
+ # end
482
+
483
+ # let(:history) { Fabricate.build(:history) }
484
+
485
+ # context 'when it belongs to a party' do
486
+ # let(:party) { Fabricate.build(:organization, id: 2) }
487
+
488
+ # let(:location) do
489
+ # "https://sample.capsulecrm.com/api/party/#{party.id}/history/101"
490
+ # end
491
+
492
+ # before do
493
+ # history.party = party
494
+ # stub_request(:post, /\/api\/party\/#{party.id}\/history$/).
495
+ # to_return(headers: { 'Location' => location })
496
+ # history.save!
497
+ # end
498
+
499
+ # it { history.id.should eql(101) }
500
+
501
+ # it { history.should be_persisted }
502
+ # end
503
+
504
+ # context 'when it belongs to a kase' do
505
+ # let(:kase) { Fabricate.build(:case, id: 5) }
506
+
507
+ # let(:location) do
508
+ # "https://sample.capsulecrm.com/api/kase/#{kase.id}/history/10005"
509
+ # end
510
+
511
+ # before do
512
+ # history.kase = kase
513
+ # stub_request(:post, /\/api\/kase\/#{kase.id}\/history$/).
514
+ # to_return(headers: { 'Location' => location })
515
+ # history.save!
516
+ # end
517
+
518
+ # it { history.id.should eql(10005) }
519
+
520
+ # it { history.should be_persisted }
521
+ # end
522
+
523
+ # context 'when it belongs to an opportunity' do
524
+ # let(:opportunity) { Fabricate.build(:opportunity, id: 3) }
525
+
526
+ # let(:location) do
527
+ # [
528
+ # 'https://sample.capsulecrm.com/api/opportunity/',
529
+ # opportunity.id, '/history/101'
530
+ # ].join
531
+ # end
532
+
533
+ # before do
534
+ # history.opportunity = opportunity
535
+ # stub_request(
536
+ # :post, /\/api\/opportunity\/#{opportunity.id}\/history$/
537
+ # ).to_return(headers: { 'Location' => location })
538
+ # history.save!
539
+ # end
540
+
541
+ # it { history.id.should eql(101) }
542
+
543
+ # it { history.should be_persisted }
544
+ # end
545
+ # end
546
+
547
+ # context 'when it is an existing record' do
548
+ # context 'when it is valid' do
549
+ # let(:history) do
550
+ # Fabricate.build(:history, party: Fabricate.build(:person), id: 10)
551
+ # end
552
+
553
+ # before do
554
+ # stub_request(:put, /\/api\/history\/#{history.id}$/).
555
+ # to_return(status: 200)
556
+ # history.save!
557
+ # end
558
+
559
+ # it { history.should be_persisted }
560
+ # end
561
+
562
+ # context 'when it is not valid' do
563
+ # let(:history) { CapsuleCRM::History.new(id: 1) }
564
+
565
+ # it 'should raise an error' do
566
+ # expect { history.save! }.
567
+ # to raise_error(CapsuleCRM::Errors::RecordInvalid)
568
+ # end
569
+ # end
570
+ # end
571
+ # end
572
+
573
+ # describe '#destroy' do
574
+ # let(:history) { Fabricate.build(:history, id: 19) }
575
+
576
+ # before do
577
+ # stub_request(:delete, /\/api\/history\/#{history.id}$/).
578
+ # to_return(status: 200)
579
+ # history.destroy
580
+ # end
581
+
582
+ # subject { history }
583
+
584
+ # it { should_not be_persisted }
585
+ # end
586
+
587
+ # describe '#new_record?' do
588
+ # context 'when the history item is a new record' do
589
+ # let(:history) { CapsuleCRM::History.new }
590
+
591
+ # subject { history.new_record? }
592
+
593
+ # it { should be_true }
594
+ # end
595
+
596
+ # context 'when the history item is not a new record' do
597
+ # let(:history) { CapsuleCRM::History.new(id: 1) }
598
+
599
+ # subject { history.new_record? }
600
+
601
+ # it { should be_false }
602
+ # end
603
+ # end
604
+
605
+ # describe '#persisted?' do
606
+ # context 'when the history item is persisted' do
607
+ # let(:history) { CapsuleCRM::History.new(id: 1) }
608
+
609
+ # subject { history.persisted? }
610
+
611
+ # it { should be_true }
612
+ # end
613
+
614
+ # context 'when the hitory item is not persisted' do
615
+ # let(:history) { CapsuleCRM::History.new }
616
+
617
+ # subject { history.persisted? }
618
+
619
+ # it { should be_false }
620
+ # end
621
+ # end
622
+
623
+ # describe '#to_capsule_json' do
624
+ # let(:creator) { CapsuleCRM::User.new(username: Faker::Name.name) }
625
+
626
+ # let(:history) do
627
+ # CapsuleCRM::History.new(
628
+ # type: 'Note', entry_date: Time.now, creator: creator,
629
+ # subject: Faker::Lorem.sentence, note: Faker::Lorem.paragraph,
630
+ # participants: [participant]
631
+ # )
632
+ # end
633
+
634
+ # let(:participant) do
635
+ # CapsuleCRM::Participant.new(
636
+ # name: Faker::Name.name, email_address: Faker::Internet.email,
637
+ # role: 'TO'
638
+ # )
639
+ # end
640
+
641
+ # subject { history.to_capsule_json }
642
+
643
+ # let(:participants_json) { subject[:historyItem]['participants'] }
644
+
645
+ # it { subject.keys.first.should eql(:historyItem) }
646
+
647
+ # it { subject[:historyItem]['entryDate'].should eql(history.entry_date) }
648
+
649
+ # it { subject[:historyItem]['creator'].should eql(creator.username) }
650
+
651
+ # it { subject[:historyItem]['note'].should eql(history.note) }
652
+
653
+ # it { subject[:historyItem].should have_key('note') }
654
+ # end
655
+ # end
@@ -91,4 +91,18 @@ describe CapsuleCRM::Organization do
91
91
 
92
92
  it { email_json.should have_key('emailAddress') }
93
93
  end
94
+
95
+ describe '#destroy' do
96
+ let(:organization) { CapsuleCRM::Organization.new(id: 1) }
97
+
98
+ before do
99
+ stub_request(:delete, /\/api\/party\/#{organization.id}/).
100
+ to_return(status: 200)
101
+ organization.destroy
102
+ end
103
+
104
+ it { expect(organization.id).to be_blank }
105
+
106
+ it { expect(organization).to_not be_persisted }
107
+ end
94
108
  end
@@ -32,7 +32,13 @@ describe CapsuleCRM::Person do
32
32
  end
33
33
 
34
34
  context 'when there is 1 person for the organization' do
35
- pending
35
+ before do
36
+ stub_request(:get, /\/api\/party\/1\/people$/).
37
+ to_return(body: File.read('spec/support/single_user.json'))
38
+ end
39
+ subject { CapsuleCRM::Person._for_organization(1) }
40
+
41
+ it { should be_a(Array) }
36
42
  end
37
43
 
38
44
  context 'when there are no people for the organization' do
@@ -7,6 +7,9 @@ class TaggableItem
7
7
  attribute :id
8
8
  end
9
9
 
10
+ class SubclassedTaggableItem < TaggableItem
11
+ end
12
+
10
13
  describe CapsuleCRM::Taggable do
11
14
  before { configure }
12
15
 
@@ -39,7 +42,7 @@ describe CapsuleCRM::Taggable do
39
42
 
40
43
  before do
41
44
  loc = 'https://sample.capsulecrm.com/api/party/1000/tag/A%20Test%20Tag'
42
- stub_request(:post, /\/api\/taggableitem\/1\/A%20Test%20Tag$/).
45
+ stub_request(:post, /\/api\/taggableitem\/1\/tag\/A%20Test%20Tag$/).
43
46
  to_return(headers: { 'Location' => loc })
44
47
  end
45
48
 
@@ -66,7 +69,7 @@ describe CapsuleCRM::Taggable do
66
69
 
67
70
  before do
68
71
  loc = 'https://sample.capsulecrm.com/api/party/1000/tag/A%20Test%20Tag'
69
- stub_request(:delete, /\/api\/taggableitem\/1\/A%20Test%20Tag$/).
72
+ stub_request(:delete, /\/api\/taggableitem\/1\/tag\/A%20Test%20Tag$/).
70
73
  to_return(headers: { 'Location' => loc })
71
74
  end
72
75
 
@@ -81,4 +84,14 @@ describe CapsuleCRM::Taggable do
81
84
  it { subject.should be_nil }
82
85
  end
83
86
  end
87
+
88
+ describe '#api_singular_name' do
89
+ it 'turns the class name into appropriate api name' do
90
+ TaggableItem.new.api_singular_name.should == 'taggableitem'
91
+ end
92
+
93
+ it 'gives the superclass unless Object to work with Organization/Person subclassing of Party' do
94
+ SubclassedTaggableItem.new.api_singular_name.should == 'taggableitem'
95
+ end
96
+ end
84
97
  end
@@ -0,0 +1,23 @@
1
+ {
2
+ "customFields": {
3
+ "customField": [
4
+ {
5
+ "id": "1",
6
+ "tag": "Staff",
7
+ "label": "NI Number",
8
+ "text": "12345678"
9
+ },
10
+ {
11
+ "id": "1",
12
+ "tag": "Staff",
13
+ "label": "Start Date",
14
+ "date": "2011-03-13T00:00:00Z"
15
+ },
16
+ {
17
+ "id": "1",
18
+ "label": "Send newsletter",
19
+ "boolean": "true"
20
+ }
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "customFields": {
3
+ "@size": "0"
4
+ }
5
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "parties":
3
+ {
4
+ "@size":"1",
5
+ "person":
6
+ {
7
+ "id":"100",
8
+ "contacts":
9
+ {
10
+ "email":
11
+ {
12
+ "id":"25101754",
13
+ "emailAddress":"aa@aa.com"
14
+ }
15
+ },
16
+ "pictureURL": "",
17
+ "createdOn":"2011-08-10T01:58:49Z",
18
+ "updatedOn":"2011-08-10T03:20:43Z",
19
+ "firstName":"aaa",
20
+ "lastName":"bbb",
21
+ "organisationId":"1",
22
+ "organisationName":"test"
23
+ }
24
+ }
25
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capsule_crm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Beedle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-10 00:00:00.000000000 Z
11
+ date: 2013-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -244,6 +244,7 @@ files:
244
244
  - .gitignore
245
245
  - .rspec
246
246
  - .travis.yml
247
+ - CHANGELOG.md
247
248
  - Gemfile
248
249
  - Guardfile
249
250
  - LICENSE.txt
@@ -260,6 +261,7 @@ files:
260
261
  - lib/capsule_crm/attachment.rb
261
262
  - lib/capsule_crm/capsule_jsonable.rb
262
263
  - lib/capsule_crm/case.rb
264
+ - lib/capsule_crm/collection.rb
263
265
  - lib/capsule_crm/configuration.rb
264
266
  - lib/capsule_crm/connection.rb
265
267
  - lib/capsule_crm/contactable.rb
@@ -298,6 +300,7 @@ files:
298
300
  - spec/lib/capsule_crm/contacts_spec.rb
299
301
  - spec/lib/capsule_crm/country_spec.rb
300
302
  - spec/lib/capsule_crm/currency_spec.rb
303
+ - spec/lib/capsule_crm/custom_field_spec.rb
301
304
  - spec/lib/capsule_crm/email_spec.rb
302
305
  - spec/lib/capsule_crm/history_spec.rb
303
306
  - spec/lib/capsule_crm/milestone_spec.rb
@@ -311,6 +314,7 @@ files:
311
314
  - spec/lib/capsule_crm/user_spec.rb
312
315
  - spec/spec_helper.rb
313
316
  - spec/support/all_cases.json
317
+ - spec/support/all_customfields.json
314
318
  - spec/support/all_history.json
315
319
  - spec/support/all_opportunities.json
316
320
  - spec/support/all_parties.json
@@ -325,11 +329,13 @@ files:
325
329
  - spec/support/helpers.rb
326
330
  - spec/support/history.json
327
331
  - spec/support/milestones.json
332
+ - spec/support/no_customfields.json
328
333
  - spec/support/no_history.json
329
334
  - spec/support/opportunity.json
330
335
  - spec/support/organisation.json
331
336
  - spec/support/person.json
332
337
  - spec/support/shared_examples/contactable.rb
338
+ - spec/support/single_user.json
333
339
  - spec/support/task.json
334
340
  - spec/support/task_categories.json
335
341
  homepage: ''
@@ -370,6 +376,7 @@ test_files:
370
376
  - spec/lib/capsule_crm/contacts_spec.rb
371
377
  - spec/lib/capsule_crm/country_spec.rb
372
378
  - spec/lib/capsule_crm/currency_spec.rb
379
+ - spec/lib/capsule_crm/custom_field_spec.rb
373
380
  - spec/lib/capsule_crm/email_spec.rb
374
381
  - spec/lib/capsule_crm/history_spec.rb
375
382
  - spec/lib/capsule_crm/milestone_spec.rb
@@ -383,6 +390,7 @@ test_files:
383
390
  - spec/lib/capsule_crm/user_spec.rb
384
391
  - spec/spec_helper.rb
385
392
  - spec/support/all_cases.json
393
+ - spec/support/all_customfields.json
386
394
  - spec/support/all_history.json
387
395
  - spec/support/all_opportunities.json
388
396
  - spec/support/all_parties.json
@@ -397,10 +405,12 @@ test_files:
397
405
  - spec/support/helpers.rb
398
406
  - spec/support/history.json
399
407
  - spec/support/milestones.json
408
+ - spec/support/no_customfields.json
400
409
  - spec/support/no_history.json
401
410
  - spec/support/opportunity.json
402
411
  - spec/support/organisation.json
403
412
  - spec/support/person.json
404
413
  - spec/support/shared_examples/contactable.rb
414
+ - spec/support/single_user.json
405
415
  - spec/support/task.json
406
416
  - spec/support/task_categories.json