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 +4 -4
- data/.rubocop.yml +11 -0
- data/README.md +51 -0
- data/lib/amorail/entities/contact.rb +6 -0
- data/lib/amorail/entities/contact_link.rb +32 -0
- data/lib/amorail/entities/lead.rb +15 -0
- data/lib/amorail/entities/leadable.rb +20 -6
- data/lib/amorail/entity/finders.rb +17 -0
- data/lib/amorail/version.rb +1 -1
- data/spec/contact_link_spec.rb +40 -0
- data/spec/contact_spec.rb +23 -0
- data/spec/fixtures/contact_find.json +4 -0
- data/spec/fixtures/contacts_links.json +15 -0
- data/spec/fixtures/leads.json +69 -0
- data/spec/fixtures/leads_links.json +15 -0
- data/spec/helpers/webmock_helpers.rb +59 -0
- data/spec/lead_spec.rb +29 -0
- data/spec/support/leadable_example.rb +19 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a49cf3e73052b401ec558f46cf546671cefd4ba
|
4
|
+
data.tar.gz: 05204059536051197800da4bd8f784c9dd13b0d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecdea4ff97ea0018b2b25cce5e049fef9fb8c7ecea9fffe88777f4b25fa0b98378233d8ef3abbd4adf27c29d8ceee205621339e2db4d3697392ea375e63ee484
|
7
|
+
data.tar.gz: 24379dc6fc1498860dadda55c13ebacf7bba1ccab4b9a058aad304eb22dbd2d64e7d10386e23f3f1d14912b11830c5dd23cd0c62f274f8e7f361a46ccb511cc7
|
data/.rubocop.yml
CHANGED
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
|
|
@@ -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
|
-
|
5
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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] || [])
|
data/lib/amorail/version.rb
CHANGED
@@ -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
|
|
@@ -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
|
+
}
|
@@ -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.
|
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-
|
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
|