amorail 0.1.9 → 0.2.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: 20a8ca62be5f80149cddb2e7e82442d611b9fe32
4
- data.tar.gz: 90ce153c4740de2c2049adcc2f473f6f1b0d9b57
3
+ metadata.gz: 6a49cf3e73052b401ec558f46cf546671cefd4ba
4
+ data.tar.gz: 05204059536051197800da4bd8f784c9dd13b0d2
5
5
  SHA512:
6
- metadata.gz: c0d2b86bbfef3d13494baffbe381ccf0e4ce4162100cecb37c92a301324c4d87fd7295a2873ba58ed04a1f3c8acadc34b2d281b6d887a9cb810328702617e418
7
- data.tar.gz: d8718c7c448a91b45be58d25ae26970c8c4b222c0dbee8682223548eb00df93fdaba99a340c508e961517b34ee1f026916c598dceecb74b933b97ccf051da95c
6
+ metadata.gz: ecdea4ff97ea0018b2b25cce5e049fef9fb8c7ecea9fffe88777f4b25fa0b98378233d8ef3abbd4adf27c29d8ceee205621339e2db4d3697392ea375e63ee484
7
+ data.tar.gz: 24379dc6fc1498860dadda55c13ebacf7bba1ccab4b9a058aad304eb22dbd2d64e7d10386e23f3f1d14912b11830c5dd23cd0c62f274f8e7f361a46ccb511cc7
data/.rubocop.yml CHANGED
@@ -30,3 +30,14 @@ Rails/Date:
30
30
 
31
31
  Rails/TimeZone:
32
32
  Enabled: false
33
+
34
+ Metrics/MethodLength:
35
+ Exclude:
36
+ - 'spec/**/*.rb'
37
+
38
+ Metrics/LineLength:
39
+ Exclude:
40
+ - 'spec/**/*.rb'
41
+
42
+ Style/WordArray:
43
+ Enabled: false
data/README.md CHANGED
@@ -143,6 +143,57 @@ contact.save!
143
143
  contact.update(linked_company_id: company.id)
144
144
  ```
145
145
 
146
+ ### Querying
147
+
148
+ Load by id
149
+
150
+ ```ruby
151
+ Amorail::Contact.find(223) #=> #<Amorail::Contact ...>
152
+ ```
153
+
154
+ Load many entites by array of ids
155
+
156
+ ```ruby
157
+ Amorail::Contact.find_all(123, 124) #=> [#<Amorail::Contact ...>, ...]
158
+ ```
159
+
160
+ Load by query
161
+
162
+ ```ruby
163
+ Amorail::Contact.find_by_query("my_company") #=> [#<Amorail::Contact ...>, ...]
164
+ ```
165
+
166
+
167
+ Load contacts associated with lead
168
+
169
+ ```ruby
170
+ lead = Amorail::Lead.find(1)
171
+ lead.contacts #=> [#<Amorail::Contact ...>, ...]
172
+ ```
173
+
174
+ Load company associated with contact
175
+
176
+ ```ruby
177
+ contact = Amorail::Contact.find(1)
178
+ contact.company #=> #<Amorail::Company ...>
179
+ ```
180
+
181
+ Load leads associated with contact
182
+
183
+ ```ruby
184
+ contact = Amorail::Contact.find(1)
185
+ contact.leads #=> [#<Amorail::Lead ...>, ...]
186
+ ```
187
+
188
+ Load contacts-leads pairs
189
+
190
+ ```ruby
191
+ # Load all contact-leads pairs for contacts
192
+ Amorail::ContactLink.find_by_contacts(1, 2)
193
+
194
+ # Load all contact-leads pairs for leads
195
+ Amorail::ContactLink.find_by_leads(1, 2)
196
+ ```
146
197
 
147
198
  ### Properties Configuration
148
199
 
@@ -14,6 +14,12 @@ module Amorail
14
14
 
15
15
  validates :name, presence: true
16
16
 
17
+ # Clear company cache
18
+ def reload
19
+ @company = nil
20
+ super
21
+ end
22
+
17
23
  def company
18
24
  return if linked_company_id.nil?
19
25
  @company ||= Amorail::Company.find(linked_company_id)
@@ -0,0 +1,32 @@
1
+ module Amorail
2
+ # AmoCRM contact-link join model
3
+ class ContactLink < Amorail::Entity
4
+ amo_names "contacts", "links"
5
+
6
+ amo_field :contact_id, :lead_id
7
+
8
+ class << self
9
+ # Find links by contacts ids
10
+ def find_by_contacts(*ids)
11
+ ids = ids.first if ids.size == 1 && ids.first.is_a?(Array)
12
+ response = Amorail.client.safe_request(
13
+ :get,
14
+ remote_url('links'),
15
+ contacts_link: ids
16
+ )
17
+ load_many(response)
18
+ end
19
+
20
+ # Find links by leads ids
21
+ def find_by_leads(*ids)
22
+ ids = ids.first if ids.size == 1 && ids.first.is_a?(Array)
23
+ response = Amorail.client.safe_request(
24
+ :get,
25
+ remote_url('links'),
26
+ deals_link: ids
27
+ )
28
+ load_many(response)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -6,5 +6,20 @@ module Amorail
6
6
  amo_field :name, :price, :status_id, :tags
7
7
 
8
8
  validates :name, :status_id, presence: true
9
+
10
+ def reload
11
+ @contacts = nil
12
+ super
13
+ end
14
+
15
+ # Return list of associated contacts
16
+ def contacts
17
+ fail NotPersisted if id.nil?
18
+ @contacts ||=
19
+ begin
20
+ links = Amorail::ContactLink.find_by_leads(id)
21
+ links.empty? ? [] : Amorail::Contact.find_all(links.map(&:contact_id))
22
+ end
23
+ end
9
24
  end
10
25
  end
@@ -1,14 +1,28 @@
1
1
  module Amorail
2
2
  # Lead associations
3
3
  module Leadable
4
- def linked_leads_id
5
- @linked_leads_id ||= []
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ amo_field :linked_leads_id
8
+ end
9
+
10
+ # Set initial value for linked_leads_id to []
11
+ def initialize(*args)
12
+ super
13
+ self.linked_leads_id ||= []
14
+ end
15
+
16
+ # Clear leads cache on reload
17
+ def reload
18
+ @leads = nil
19
+ super
6
20
  end
7
21
 
8
- def params
9
- data = super
10
- data[:linked_leads_id] = linked_leads_id unless linked_leads_id.empty?
11
- data
22
+ # Return all linked leads
23
+ def leads
24
+ return [] if linked_leads_id.empty?
25
+ @leads ||= Amorail::Lead.find_all(linked_leads_id)
12
26
  end
13
27
  end
14
28
  end
@@ -14,6 +14,17 @@ module Amorail # :nodoc: all
14
14
  rec
15
15
  end
16
16
 
17
+ def find_all(*ids)
18
+ ids = ids.first if ids.size == 1 && ids.first.is_a?(Array)
19
+
20
+ response = Amorail.client.safe_request(
21
+ :get,
22
+ remote_url('list'),
23
+ id: ids
24
+ )
25
+ load_many(response)
26
+ end
27
+
17
28
  # Find AMO entities by query
18
29
  # Returns array of matching entities.
19
30
  def find_by_query(q)
@@ -22,6 +33,12 @@ module Amorail # :nodoc: all
22
33
  remote_url('list'),
23
34
  query: q
24
35
  )
36
+ load_many(response)
37
+ end
38
+
39
+ private
40
+
41
+ def load_many(response)
25
42
  return [] unless response.status == 200
26
43
 
27
44
  (response.body['response'][amo_response_name] || [])
@@ -1,4 +1,4 @@
1
1
  # Amorail version
2
2
  module Amorail
3
- VERSION = "0.1.9"
3
+ VERSION = "0.2.0"
4
4
  end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Amorail::ContactLink do
4
+ before { mock_api }
5
+
6
+ describe ".attributes" do
7
+ subject { described_class.attributes }
8
+
9
+ it_behaves_like 'entity_class'
10
+
11
+ specify do
12
+ is_expected.to include(
13
+ :contact_id,
14
+ :lead_id
15
+ )
16
+ end
17
+ end
18
+
19
+ describe ".find_by_leads" do
20
+ before { leads_links_stub(Amorail.config.api_endpoint, [2]) }
21
+
22
+ it "returns list of contact links" do
23
+ res = described_class.find_by_leads(2)
24
+ expect(res.size).to eq 2
25
+ expect(res.first.contact_id).to eq "101"
26
+ expect(res.last.contact_id).to eq "102"
27
+ end
28
+ end
29
+
30
+ describe ".find_by_contacts" do
31
+ before { contacts_links_stub(Amorail.config.api_endpoint, [101]) }
32
+
33
+ it "returns list of contact links" do
34
+ res = described_class.find_by_contacts(101)
35
+ expect(res.size).to eq 2
36
+ expect(res.first.lead_id).to eq "1"
37
+ expect(res.last.lead_id).to eq "2"
38
+ end
39
+ end
40
+ end
data/spec/contact_spec.rb CHANGED
@@ -78,6 +78,7 @@ describe Amorail::Contact do
78
78
  expect(obj.email).to eq "foo@tb.com"
79
79
  expect(obj.phone).to eq "1111 111 111"
80
80
  expect(obj.params[:id]).to eq 101
81
+ expect(obj.linked_leads_id).to contain_exactly("1872746", "1885024")
81
82
  end
82
83
 
83
84
  it "returns nil" do
@@ -113,6 +114,28 @@ describe Amorail::Contact do
113
114
  end
114
115
  end
115
116
 
117
+ describe ".find_all" do
118
+ before { contacts_find_all_stub(Amorail.config.api_endpoint, [101, 102]) }
119
+ before { contacts_find_all_stub(Amorail.config.api_endpoint, [105, 104], false) }
120
+
121
+ it "loads entities" do
122
+ res = described_class.find_all(101, 102)
123
+ expect(res.size).to eq 2
124
+ expect(res.first.id).to eq 101
125
+ expect(res.last.id).to eq 102
126
+ expect(res.first.company_name).to eq "Foo Inc."
127
+ expect(res.last.email).to eq "foo2@tb.com"
128
+ expect(res.first.phone).to eq "1111 111 111"
129
+ expect(res.first.params[:id]).to eq 101
130
+ end
131
+
132
+ it "returns empty array" do
133
+ res = described_class.find_all([105, 104])
134
+ expect(res).to be_a(Array)
135
+ expect(res).to be_empty
136
+ end
137
+ end
138
+
116
139
  describe "#save" do
117
140
  before { contact_create_stub(Amorail.config.api_endpoint) }
118
141
 
@@ -7,6 +7,10 @@
7
7
  "account_id": "8195968",
8
8
  "last_modified": 1423139130,
9
9
  "company_name": "Foo Inc.",
10
+ "linked_leads_id": [
11
+ "1872746",
12
+ "1885024"
13
+ ],
10
14
  "custom_fields":
11
15
  [
12
16
  {
@@ -0,0 +1,15 @@
1
+ {
2
+ "response": {
3
+ "links": [
4
+ {
5
+ "contact_id": "101",
6
+ "lead_id": "1",
7
+ "last_modified": 1374741830
8
+ },
9
+ {
10
+ "contact_id": "101",
11
+ "lead_id": "2",
12
+ "last_modified": 1374839942
13
+ }]
14
+ }
15
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "response": {
3
+ "leads": [
4
+ {
5
+ "id": "1",
6
+ "name": "Research new technologies",
7
+ "last_modified": 1374656336,
8
+ "status_id": "7046196",
9
+ "price": "500000",
10
+ "responsible_user_id": "103586",
11
+ "tags":[
12
+ {
13
+ "id": "960472",
14
+ "name": "USA"},
15
+ {
16
+ "id": "960854",
17
+ "name": "Lead"
18
+ }
19
+ ],
20
+ "date_create": 1386014400,
21
+ "account_id": "7046192",
22
+ "created_user_id": "4502311",
23
+ "custom_fields": [
24
+ {
25
+ "id": "484604",
26
+ "name": "field",
27
+ "values": [
28
+ {
29
+ "value": "text"
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ },
35
+ {
36
+ "id": "2",
37
+ "name": "Sell it!",
38
+ "last_modified": 1374656336,
39
+ "status_id": "7046196",
40
+ "price": "100000",
41
+ "responsible_user_id": "103586",
42
+ "tags":[
43
+ {
44
+ "id": "960472",
45
+ "name": "USA"},
46
+ {
47
+ "id": "960854",
48
+ "name": "Lead"
49
+ }
50
+ ],
51
+ "date_create": 1386014400,
52
+ "account_id": "7046192",
53
+ "created_user_id": "4502311",
54
+ "custom_fields": [
55
+ {
56
+ "id": "484604",
57
+ "name": "field",
58
+ "values": [
59
+ {
60
+ "value": "text"
61
+ }
62
+ ]
63
+ }
64
+ ]
65
+ }
66
+ ],
67
+ "server_time": 1374839787
68
+ }
69
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "response": {
3
+ "links": [
4
+ {
5
+ "contact_id": "101",
6
+ "lead_id": "2",
7
+ "last_modified": 1374839942
8
+ },
9
+ {
10
+ "contact_id": "102",
11
+ "lead_id": "2",
12
+ "last_modified": 1374839942
13
+ }]
14
+ }
15
+ }
@@ -122,6 +122,24 @@ module AmoWebMock
122
122
  end
123
123
  end
124
124
 
125
+ def contacts_find_all_stub(endpoint, ids, success = true)
126
+ if success
127
+ stub_request(
128
+ :get,
129
+ "#{endpoint}/private/api/v2/json/contacts/list?#{ids.to_query('id')}")
130
+ .to_return(
131
+ body: File.read('./spec/fixtures/contact_find_query.json'),
132
+ headers: { 'Content-Type' => 'application/json' },
133
+ status: 200
134
+ )
135
+ else
136
+ stub_request(
137
+ :get,
138
+ "#{endpoint}/private/api/v2/json/contacts/list?#{ids.to_query('id')}")
139
+ .to_return(status: 204)
140
+ end
141
+ end
142
+
125
143
  def company_create_stub(endpoint)
126
144
  stub_request(:post, endpoint + '/private/api/v2/json/company/set')
127
145
  .to_return(
@@ -130,4 +148,45 @@ module AmoWebMock
130
148
  status: 200
131
149
  )
132
150
  end
151
+
152
+ def leads_stub(endpoint, ids, success = true)
153
+ if success
154
+ stub_request(
155
+ :get,
156
+ "#{endpoint}/private/api/v2/json/leads/list?#{ids.to_query('id')}")
157
+ .to_return(
158
+ body: File.read('./spec/fixtures/leads.json'),
159
+ headers: { 'Content-Type' => 'application/json' },
160
+ status: 200
161
+ )
162
+ else
163
+ stub_request(
164
+ :get,
165
+ "#{endpoint}/private/api/v2/json/leads/list?#{ids.to_query('id')}")
166
+ .to_return(status: 204)
167
+ end
168
+ end
169
+
170
+ def contacts_links_stub(endpoint, ids)
171
+ stub_request(:get, endpoint + "/private/api/v2/json/contacts/links?#{ids.to_query('contacts_link')}")
172
+ .to_return(
173
+ body: File.read('./spec/fixtures/contacts_links.json'),
174
+ headers: { 'Content-Type' => 'application/json' },
175
+ status: 200
176
+ )
177
+ end
178
+
179
+ def leads_links_stub(endpoint, ids, success = true)
180
+ if success
181
+ stub_request(:get, endpoint + "/private/api/v2/json/contacts/links?#{ids.to_query('deals_link')}")
182
+ .to_return(
183
+ body: File.read('./spec/fixtures/leads_links.json'),
184
+ headers: { 'Content-Type' => 'application/json' },
185
+ status: 200
186
+ )
187
+ else
188
+ stub_request(:get, endpoint + "/private/api/v2/json/contacts/links?#{ids.to_query('deals_link')}")
189
+ .to_return(status: 204)
190
+ end
191
+ end
133
192
  end
data/spec/lead_spec.rb CHANGED
@@ -41,4 +41,33 @@ describe Amorail::Lead do
41
41
  specify { is_expected.to include(status_id: 2) }
42
42
  specify { is_expected.to include(tags: 'test lead') }
43
43
  end
44
+
45
+ describe "#contacts" do
46
+ let(:lead) { described_class.new(id: 2) }
47
+
48
+ it "fails if not persisted" do
49
+ expect { described_class.new.contacts }
50
+ .to raise_error(Amorail::Entity::NotPersisted)
51
+ end
52
+
53
+ context "has contacts" do
54
+ before { leads_links_stub(Amorail.config.api_endpoint, [2]) }
55
+ before { contacts_find_all_stub(Amorail.config.api_endpoint, [101, 102]) }
56
+
57
+ it "loads contacts for lead" do
58
+ res = lead.contacts
59
+ expect(res.size).to eq 2
60
+ expect(res.first.id).to eq 101
61
+ expect(res.last.id).to eq 102
62
+ end
63
+ end
64
+
65
+ context "no contacts" do
66
+ before { leads_links_stub(Amorail.config.api_endpoint, [2], false) }
67
+
68
+ it "returns empty" do
69
+ expect(lead.contacts).to be_empty
70
+ end
71
+ end
72
+ end
44
73
  end
@@ -11,4 +11,23 @@ shared_examples 'leadable' do
11
11
  specify { is_expected.to include(:linked_leads_id) }
12
12
  specify { expect(subject.fetch(:linked_leads_id)).to include(100) }
13
13
  end
14
+
15
+ describe "#leads" do
16
+ before { leads_stub(Amorail.config.api_endpoint, [1, 2]) }
17
+
18
+ let(:leadable) { described_class.new(linked_leads_id: ['1', '2']) }
19
+
20
+ it "loads leads" do
21
+ expect(leadable.leads.size).to eq 2
22
+ expect(leadable.leads.first).to be_a(Amorail::Lead)
23
+ expect(leadable.leads.first.name).to eq "Research new technologies"
24
+ end
25
+
26
+ it "cache results" do
27
+ url = URI.join(Amorail.config.api_endpoint, Amorail::Lead.remote_url('list'))
28
+ leadable.leads
29
+ leadable.leads
30
+ expect(WebMock).to have_requested(:get, url).with(query: { id: [1, 2] }).once
31
+ end
32
+ end
14
33
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amorail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alekseenkoss
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-10-27 00:00:00.000000000 Z
12
+ date: 2015-11-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -194,6 +194,7 @@ files:
194
194
  - lib/amorail/engine.rb
195
195
  - lib/amorail/entities/company.rb
196
196
  - lib/amorail/entities/contact.rb
197
+ - lib/amorail/entities/contact_link.rb
197
198
  - lib/amorail/entities/lead.rb
198
199
  - lib/amorail/entities/leadable.rb
199
200
  - lib/amorail/entities/task.rb
@@ -207,6 +208,7 @@ files:
207
208
  - lib/tasks/amorail.rake
208
209
  - spec/client_spec.rb
209
210
  - spec/company_spec.rb
211
+ - spec/contact_link_spec.rb
210
212
  - spec/contact_spec.rb
211
213
  - spec/entity_spec.rb
212
214
  - spec/fixtures/account_response.json
@@ -215,6 +217,9 @@ files:
215
217
  - spec/fixtures/contact_find.json
216
218
  - spec/fixtures/contact_find_query.json
217
219
  - spec/fixtures/contact_update.json
220
+ - spec/fixtures/contacts_links.json
221
+ - spec/fixtures/leads.json
222
+ - spec/fixtures/leads_links.json
218
223
  - spec/fixtures/my_contact_find.json
219
224
  - spec/helpers/webmock_helpers.rb
220
225
  - spec/lead_spec.rb
@@ -253,6 +258,7 @@ summary: Ruby API client for AmoCRM
253
258
  test_files:
254
259
  - spec/client_spec.rb
255
260
  - spec/company_spec.rb
261
+ - spec/contact_link_spec.rb
256
262
  - spec/contact_spec.rb
257
263
  - spec/entity_spec.rb
258
264
  - spec/fixtures/account_response.json
@@ -261,6 +267,9 @@ test_files:
261
267
  - spec/fixtures/contact_find.json
262
268
  - spec/fixtures/contact_find_query.json
263
269
  - spec/fixtures/contact_update.json
270
+ - spec/fixtures/contacts_links.json
271
+ - spec/fixtures/leads.json
272
+ - spec/fixtures/leads_links.json
264
273
  - spec/fixtures/my_contact_find.json
265
274
  - spec/helpers/webmock_helpers.rb
266
275
  - spec/lead_spec.rb