nutshell-crm-api 0.1.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 +7 -0
- data/.gitignore +21 -0
- data/.rbenv-version +1 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/README.md +37 -0
- data/Rakefile +16 -0
- data/lib/nutshell-crm-api.rb +471 -0
- data/lib/nutshell-crm-api/version.rb +3 -0
- data/nutshell-crm-api.gemspec +29 -0
- data/spec/nutshell-crm_spec.rb +102 -0
- data/spec/spec_helper.rb +5 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b5e4313404f12a0dd297d7c8160a98189d204f4e
|
4
|
+
data.tar.gz: d5a1e365173d1a0b3c6868969bf260ee2958704c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 070a8da9f109823ad981b20af96426b5992ca2d70ad89e6101fdc32f032a03742009f26210dc021b1a7ffb2e701e00395ea65e2ea3206fc11feb2c94fc5bc4f2
|
7
|
+
data.tar.gz: 2621cb2fae04b5ea4a1331663fa9dc725ca10304de0ab1ad9c2aea93475c7ca7ee18641674e623673fe01c3c4395580a9b172de1ba96e4d3b694dbb6a1538d00
|
data/.gitignore
ADDED
data/.rbenv-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.2-p290
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Nutshell CRM [](http://travis-ci.org/mshafrir/nutshell-crm)
|
2
|
+
|
3
|
+
Author: [mshafrir@gmail.com](mailto:mshafrir@gmail.com)
|
4
|
+
|
5
|
+
## Description ##
|
6
|
+
|
7
|
+
Nutshell Crm is a Ruby wrapper for the Nutshell Crm API.
|
8
|
+
|
9
|
+
[Nutshell API Reference](http://www.nutshell.com/api/)
|
10
|
+
|
11
|
+
## Reference ##
|
12
|
+
|
13
|
+
- {NutshellCrm::Client}
|
14
|
+
|
15
|
+
|
16
|
+
## Install ##
|
17
|
+
|
18
|
+
gem install nutshell-crm
|
19
|
+
|
20
|
+
|
21
|
+
## Example Usage ##
|
22
|
+
|
23
|
+
require "nutshell-crm"
|
24
|
+
|
25
|
+
# Instantiate the Nutshell client.
|
26
|
+
nutshell = NutshellCrm::Client.new "user@example.com", "MY_API_KEY"
|
27
|
+
|
28
|
+
# Get the first open lead with stub data (default).
|
29
|
+
nutshell.find_leads({status: 0}).first
|
30
|
+
#=> {"stub"=>true, "id"=>1001, "entityType"=>"Leads", "name"=>"Lead\u20131001", "status"=>0, "primaryAccountName"=>nil}
|
31
|
+
|
32
|
+
# Enable non-stub responses.
|
33
|
+
nutshell.stub_responses = false
|
34
|
+
|
35
|
+
# Get the first open lead with full data.
|
36
|
+
nutshell.find_leads({status: 0}).first
|
37
|
+
#=> {"id"=>1001, "entityType"=>"Leads", "name"=>"Lead\u20131001", "status"=>0, "primaryAccountName"=>nil, "creator"=>{}}
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/task'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
task :local_test do
|
7
|
+
exec 'rbenv local 1.9.2-p290 && bundle exec rspec spec/nutshell-crm_spec.rb && rbenv local 1.9.3'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :doc do
|
11
|
+
exec 'yardoc && cp -vR doc/ ../nutshell-crm-docs && cd ../nutshell-crm-docs && git add . && git commit -am "Update documentation." && git push origin gh-pages'
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default do
|
15
|
+
exec 'bundle exec rspec'
|
16
|
+
end
|
@@ -0,0 +1,471 @@
|
|
1
|
+
require "nutshell-crm-api/version"
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'httparty'
|
5
|
+
|
6
|
+
# @author Michael Shafrir
|
7
|
+
module NutshellCrmAPI
|
8
|
+
class Client
|
9
|
+
|
10
|
+
attr_accessor :api_url
|
11
|
+
|
12
|
+
# Global setting for stubResponses parameter.
|
13
|
+
attr_accessor :stub_responses
|
14
|
+
|
15
|
+
include HTTParty
|
16
|
+
format :json
|
17
|
+
|
18
|
+
# A new instance of the NutshellCrm client.
|
19
|
+
# Configure at https://app01.nutshell.com/setup/api-key
|
20
|
+
#
|
21
|
+
# @param [String] username
|
22
|
+
# @param [String] api_key
|
23
|
+
# API key
|
24
|
+
def initialize(username, api_key)
|
25
|
+
@username = username
|
26
|
+
@api_key = api_key
|
27
|
+
@stub_responses = nil
|
28
|
+
|
29
|
+
result = exec_request(build_payload({:username => @username}), 'http://api.nutshell.com/v1/json')
|
30
|
+
api_host = result['api']
|
31
|
+
@api_url = "https://#{api_host}/api/v1/json"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Saves the given e-mail message.
|
35
|
+
#
|
36
|
+
# @param [String] e-mail in RFC 822 format
|
37
|
+
def add_email(email_string)
|
38
|
+
exec_request build_payload({:emailString => email_string})
|
39
|
+
end
|
40
|
+
|
41
|
+
# Gets all of the custom fields available for Leads, Accounts and Contacts, including appropriate meta-information.
|
42
|
+
#
|
43
|
+
# @return [Object] the custom fields available for Leads, Accounts and Contacts, including appropriate meta-information
|
44
|
+
def describe_custom_fields
|
45
|
+
exec_request build_payload
|
46
|
+
end
|
47
|
+
|
48
|
+
# Edit an account.
|
49
|
+
#
|
50
|
+
# @param [Integer] account_id
|
51
|
+
# account ID to edit
|
52
|
+
# @param [String] rev
|
53
|
+
# the revision
|
54
|
+
# @param [Hash] account
|
55
|
+
# updated account information
|
56
|
+
def edit_account(account_id, rev, account)
|
57
|
+
exec_request build_payload({:accountId => account_id, :rev => rev, :account => account})
|
58
|
+
end
|
59
|
+
|
60
|
+
# Edit an activity.
|
61
|
+
def edit_activity(activity_id, rev, activity)
|
62
|
+
exec_request build_payload({:activityId => activity_id, :rev => rev, :activity => activity})
|
63
|
+
end
|
64
|
+
|
65
|
+
# Edit a contact.
|
66
|
+
def edit_contact(contact_id, rev, contact)
|
67
|
+
exec_request build_payload({:contactId => contact_id, :rev => rev, :contact => contact})
|
68
|
+
end
|
69
|
+
|
70
|
+
# Edit a lead.
|
71
|
+
def edit_lead(lead_id, rev, lead)
|
72
|
+
exec_request build_payload({:leadId => lead_id, :rev => rev, :lead => lead})
|
73
|
+
end
|
74
|
+
|
75
|
+
# Update a process step.
|
76
|
+
def edit_step(step_id, rev, step)
|
77
|
+
exec_request build_payload({:stepId => step_id, :rev => rev, :step => step})
|
78
|
+
end
|
79
|
+
|
80
|
+
# Edit a task.
|
81
|
+
def edit_task(task_id, rev, task)
|
82
|
+
exec_request build_payload({:taskId => task_id, :rev => rev, :task => task})
|
83
|
+
end
|
84
|
+
|
85
|
+
# Find accounts matching a specified query.
|
86
|
+
def find_accounts(query, order_by = nil, order_direction = nil, limit = nil, page = nil, stub_responses = nil)
|
87
|
+
params = {:query => query, :orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page, :stubResponses => stub_responses}
|
88
|
+
payload = build_payload params
|
89
|
+
exec_request(payload)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get all active account types (to be applied to an account).
|
93
|
+
def find_account_types(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
94
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
95
|
+
payload = build_payload params
|
96
|
+
exec_request(payload)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Find activities matching a specified query.
|
100
|
+
def find_activities(query, order_by = nil, order_direction = nil, limit = nil, page = nil, stub_responses = nil)
|
101
|
+
params = {:query => query, :orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page, :stubResponses => stub_responses}
|
102
|
+
payload = build_payload params
|
103
|
+
exec_request(payload)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Get all active activity types.
|
107
|
+
def find_activity_types(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
108
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
109
|
+
payload = build_payload params
|
110
|
+
exec_request(payload)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Get all active Competitors.
|
114
|
+
def find_competitors(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
115
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
116
|
+
payload = build_payload params
|
117
|
+
exec_request(payload)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Find contacts associated with a specified account or lead.
|
121
|
+
def find_contacts(query, order_by = nil, order_direction = nil, limit = nil, page = nil, stub_responses = nil)
|
122
|
+
params = {:query => query, :orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page, :stubResponses => stub_responses}
|
123
|
+
payload = build_payload params
|
124
|
+
exec_request(payload)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get all active Delays (seen in Step responses in availableDelayIds).
|
128
|
+
def find_delays(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
129
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
130
|
+
payload = build_payload params
|
131
|
+
exec_request(payload)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Get all active Industries (to be applied to an account)
|
135
|
+
def find_industries(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
136
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
137
|
+
payload = build_payload params
|
138
|
+
exec_request(payload)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get all possible outcomes for a closed lead.
|
142
|
+
def find_lead_outcomes(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
143
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
144
|
+
payload = build_payload params, 'findLead_Outcomes'
|
145
|
+
exec_request(payload)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Find leads matching a specified query.
|
149
|
+
def find_leads(query, order_by = nil, order_direction = nil, limit = nil, page = nil, stub_responses = nil)
|
150
|
+
params = {:query => query, :orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page, :stubResponses => stub_responses}
|
151
|
+
payload = build_payload params
|
152
|
+
exec_request(payload)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Get all active markets.
|
156
|
+
def find_markets(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
157
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
158
|
+
payload = build_payload params
|
159
|
+
exec_request(payload)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Get all active milestones.
|
163
|
+
def find_milestones(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
164
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
165
|
+
payload = build_payload params
|
166
|
+
exec_request(payload)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Get all active Origins.
|
170
|
+
def find_origins(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
171
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
172
|
+
payload = build_payload params
|
173
|
+
exec_request(payload)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Get all active products.
|
177
|
+
def find_products(order_by = nil, order_direction = nil, limit = nil, page = nil, stub_responses = nil)
|
178
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page, :stubResponses => stub_responses}
|
179
|
+
payload = build_payload params
|
180
|
+
exec_request(payload)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Return all publicly-visible settings.
|
184
|
+
def find_settings(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
185
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
186
|
+
payload = build_payload params
|
187
|
+
exec_request(payload)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Get all active Sources.
|
191
|
+
def find_sources(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
192
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
193
|
+
payload = build_payload params
|
194
|
+
exec_request(payload)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Get all active tags.
|
198
|
+
def find_tags
|
199
|
+
exec_request build_payload
|
200
|
+
end
|
201
|
+
|
202
|
+
# Returns an array containing tasks for the given query.
|
203
|
+
def find_tasks(query)
|
204
|
+
params = {:query => query}
|
205
|
+
payload = build_payload params
|
206
|
+
exec_request(payload)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Get all active Teams.
|
210
|
+
def find_teams(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
211
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
212
|
+
payload = build_payload params
|
213
|
+
exec_request(payload)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Get all territories.
|
217
|
+
def find_territories(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
218
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
219
|
+
payload = build_payload params
|
220
|
+
exec_request(payload)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Find timeline events (Activities, Emails and Notes) for an Entity.
|
224
|
+
def find_timeline(query, order_by = nil, order_direction = nil, limit = nil, page = nil, stub_responses = nil)
|
225
|
+
params = {:query => query, :orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page, :stubResponses => stub_responses}
|
226
|
+
payload = build_payload params
|
227
|
+
exec_request(payload)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Get all active Users.
|
231
|
+
def find_users(order_by = nil, order_direction = nil, limit = nil, page = nil)
|
232
|
+
params = {:orderBy => order_by, :orderDirection => order_direction, :limit => limit, :page => page}
|
233
|
+
payload = build_payload params
|
234
|
+
exec_request(payload)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Get the specified Account.
|
238
|
+
def get_account(account_id, rev = nil)
|
239
|
+
params = {:accountId => account_id, :rev => rev}
|
240
|
+
exec_request build_payload(params)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Get the specified Activity.
|
244
|
+
def get_activity(activity_id, rev = nil)
|
245
|
+
params = {:activityId => activity_id, :rev => rev}
|
246
|
+
exec_request build_payload(params)
|
247
|
+
end
|
248
|
+
|
249
|
+
# Returns graph data and overview information for various sales analytics reports.
|
250
|
+
def getAnalyticsReport(report_type, period, filter_entity = nil, options = nil)
|
251
|
+
params = {:reportType => report_type, :period => period, :filter => filter_entity, :options => options}
|
252
|
+
exec_request build_payload(params)
|
253
|
+
end
|
254
|
+
|
255
|
+
# Get the specified Contact.
|
256
|
+
def get_contact(contact_id, rev = nil)
|
257
|
+
params = {:contactId => contact_id, :rev => rev}
|
258
|
+
exec_request build_payload(params)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Get the specified Email.
|
262
|
+
def get_email(email_id, rev = nil)
|
263
|
+
params = {:emailId => email_id, :rev => rev}
|
264
|
+
exec_request build_payload(params)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Get the specified lead.
|
268
|
+
def get_lead(lead_id, rev = nil)
|
269
|
+
params = {:leadId => lead_id, :rev => rev}
|
270
|
+
exec_request build_payload(params)
|
271
|
+
end
|
272
|
+
|
273
|
+
# Return all mobile-related settings in a simple key-value array.
|
274
|
+
def get_mobile_settings
|
275
|
+
exec_request build_payload
|
276
|
+
end
|
277
|
+
|
278
|
+
# Get the specified Note.
|
279
|
+
def get_note(note_id, rev = nil)
|
280
|
+
params = {:noteId => note_id, :rev => rev}
|
281
|
+
exec_request build_payload(params)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Get all information for a product (including full price list).
|
285
|
+
def get_product(product_id, rev = nil)
|
286
|
+
params = {:productId => product_id, :rev => rev}
|
287
|
+
exec_request build_payload(params)
|
288
|
+
end
|
289
|
+
|
290
|
+
def get_task(task_id, rev = nil)
|
291
|
+
params = {:taskId => task_id, :rev => rev}
|
292
|
+
exec_request build_payload(params)
|
293
|
+
end
|
294
|
+
|
295
|
+
# Gets the last-updated times of each of the provisioning bins.
|
296
|
+
def get_update_times
|
297
|
+
exec_request build_payload
|
298
|
+
end
|
299
|
+
|
300
|
+
# Get all info about a user.
|
301
|
+
def get_user(user_id = nil, rev = nil)
|
302
|
+
params = {:userId => user_id, :rev => rev}
|
303
|
+
exec_request build_payload(params)
|
304
|
+
end
|
305
|
+
|
306
|
+
# Create a new account.
|
307
|
+
def new_account(account)
|
308
|
+
exec_request build_payload({:account => account})
|
309
|
+
end
|
310
|
+
|
311
|
+
# Create a new activity.
|
312
|
+
def new_activity(activity)
|
313
|
+
exec_request build_payload({:activity => activity})
|
314
|
+
end
|
315
|
+
|
316
|
+
# Create a new contact.
|
317
|
+
def new_contact(contact)
|
318
|
+
exec_request build_payload({:contact => contact})
|
319
|
+
end
|
320
|
+
|
321
|
+
# Create a new Lead.
|
322
|
+
def new_lead(lead)
|
323
|
+
exec_request build_payload({:lead => lead})
|
324
|
+
end
|
325
|
+
|
326
|
+
# Create a new Lead.
|
327
|
+
def new_note(entity, note)
|
328
|
+
exec_request build_payload({:entity => entity, :note => note})
|
329
|
+
end
|
330
|
+
|
331
|
+
# Create a new tag.
|
332
|
+
#
|
333
|
+
# @param [Hash] tag
|
334
|
+
# See {Nut_Api_Render_Model_Tag}[http://www.nutshell.com/api/detail/class_nut___api___render___model___tag.html]
|
335
|
+
def new_tag(tag)
|
336
|
+
exec_request build_payload({:tag => tag})
|
337
|
+
end
|
338
|
+
|
339
|
+
# Create a new Task.
|
340
|
+
def new_task(task)
|
341
|
+
exec_request build_payload({:task => task})
|
342
|
+
end
|
343
|
+
|
344
|
+
# Return a list of Account stubs matching a given search string.
|
345
|
+
def search_accounts(query, limit = nil)
|
346
|
+
exec_request build_payload({:string => query, :limit => limit})
|
347
|
+
end
|
348
|
+
|
349
|
+
# Works just like searchUniversal, but only searches by email address.
|
350
|
+
def search_by_email(email_address)
|
351
|
+
exec_request build_payload({:emailAddressString => email_address})
|
352
|
+
end
|
353
|
+
|
354
|
+
# Return a list of Competitor stubs matching a given search string.
|
355
|
+
def search_competitors(query, limit = nil)
|
356
|
+
exec_request build_payload({:string => query, :limit => limit})
|
357
|
+
end
|
358
|
+
|
359
|
+
# Return a list of Contact stubs matching a given search string.
|
360
|
+
def search_contacts(query, limit = nil)
|
361
|
+
exec_request build_payload({:string => query, :limit => limit})
|
362
|
+
end
|
363
|
+
|
364
|
+
# Return a list of Contact and User stubs matching a given search string.
|
365
|
+
def search_contacts_and_users(query, limit = nil)
|
366
|
+
exec_request build_payload({:string => query, :limit => limit})
|
367
|
+
end
|
368
|
+
|
369
|
+
# Return a list of Lead stubs matching a given search string.
|
370
|
+
def search_leads(query, limit = nil)
|
371
|
+
exec_request build_payload({:string => query, :limit => limit})
|
372
|
+
end
|
373
|
+
|
374
|
+
# Return a list of Product stubs matching a given search string.
|
375
|
+
def search_products(query, limit = nil)
|
376
|
+
exec_request build_payload({:string => query, :limit => limit})
|
377
|
+
end
|
378
|
+
|
379
|
+
# Return a list of Source stubs matching a given search string.
|
380
|
+
def search_sources(query, limit = nil)
|
381
|
+
exec_request build_payload({:string => query, :limit => limit})
|
382
|
+
end
|
383
|
+
|
384
|
+
# Return a list of Contact, Lead, and Account stubs matching a given search string.
|
385
|
+
def search_universal(query)
|
386
|
+
exec_request build_payload({:string => query})
|
387
|
+
end
|
388
|
+
|
389
|
+
# Return a list of User and Team stubs matching a given search string.
|
390
|
+
def search_users_and_teams(query, limit = nil)
|
391
|
+
exec_request build_payload({:string => query, :limit => limit})
|
392
|
+
end
|
393
|
+
|
394
|
+
# Delete an Activity
|
395
|
+
def delete_activity(activity_id, rev)
|
396
|
+
params = {:activityId => activity_id, :rev => rev}
|
397
|
+
payload = build_payload params
|
398
|
+
exec_request(payload)
|
399
|
+
end
|
400
|
+
|
401
|
+
def delete_task(task_id, rev)
|
402
|
+
params = {:taskId => task_id, :rev => rev}
|
403
|
+
payload = build_payload params
|
404
|
+
exec_request(payload)
|
405
|
+
end
|
406
|
+
|
407
|
+
|
408
|
+
private
|
409
|
+
|
410
|
+
# Builds the payload for a request.
|
411
|
+
#
|
412
|
+
# @param [Hash] params
|
413
|
+
# @param [String] override_method
|
414
|
+
# needed if the Nutshell API method cannot be determined from the class method name
|
415
|
+
# @return [String] the payload in JSON format
|
416
|
+
def build_payload(params = nil, override_method = nil)
|
417
|
+
# Calculate the Nutshell API method name based on the Ruby method name (with a few exceptions)
|
418
|
+
if override_method.nil?
|
419
|
+
method = caller[0][/`.*'/][1..-2]
|
420
|
+
method = 'getApiForUsername' if method == 'initialize'
|
421
|
+
else
|
422
|
+
method = override_method
|
423
|
+
end
|
424
|
+
|
425
|
+
if (not params.nil?) && params.has_key?(:stubResponses) && (not @stub_responses.nil?)
|
426
|
+
params[:stubResponses] = @stub_responses
|
427
|
+
end
|
428
|
+
|
429
|
+
# Create the payload
|
430
|
+
payload = {:method => camelcase(method), :id => generate_request_id}
|
431
|
+
|
432
|
+
# Filter out keys with nil values.
|
433
|
+
payload[:params] = params.reject {|k,v| v.nil?} unless params.nil?
|
434
|
+
|
435
|
+
# Return as JSON
|
436
|
+
payload.to_json
|
437
|
+
end
|
438
|
+
|
439
|
+
|
440
|
+
# All Nutshell API requests need a request id.
|
441
|
+
#
|
442
|
+
# @return [String] request id
|
443
|
+
def generate_request_id
|
444
|
+
Digest::MD5.hexdigest(rand.to_s).slice(0..8)
|
445
|
+
end
|
446
|
+
|
447
|
+
# Executes an arbitrary request.
|
448
|
+
def exec_request(payload, override_url = nil)
|
449
|
+
response = HTTParty.post(override_url.nil? ? @api_url : override_url,
|
450
|
+
:basic_auth => {:username => @username, :password => @api_key},
|
451
|
+
:body => payload,
|
452
|
+
:query => {:output => :json}
|
453
|
+
)
|
454
|
+
|
455
|
+
unless response['error'].nil?
|
456
|
+
error = response['error']
|
457
|
+
error_code = error['code']
|
458
|
+
error_msg = error['message']
|
459
|
+
raise "Nutshell API Error: #{error_msg} (#{error_code})"
|
460
|
+
end
|
461
|
+
|
462
|
+
response['result']
|
463
|
+
end
|
464
|
+
|
465
|
+
def camelcase(method_name)
|
466
|
+
parts = []
|
467
|
+
method_name.split('_').each_with_index {|str, idx| parts << (idx == 0 ? str : str.capitalize)}
|
468
|
+
parts.join ''
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "nutshell-crm-api/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "nutshell-crm-api"
|
7
|
+
s.version = NutshellCrm::VERSION
|
8
|
+
s.authors = ["Christian Juth"]
|
9
|
+
s.email = ["cjuth2@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/Christianjuth/nutshell-crm-api"
|
11
|
+
s.summary = "A Ruby wrapper for Nutshell CRM's API"
|
12
|
+
s.description = "Nutshell CRM's API"
|
13
|
+
s.license = "MIT"
|
14
|
+
|
15
|
+
s.add_development_dependency 'rake'
|
16
|
+
s.add_development_dependency 'yard'
|
17
|
+
s.add_development_dependency 'rspec'
|
18
|
+
|
19
|
+
s.add_runtime_dependency 'json'
|
20
|
+
s.add_runtime_dependency 'httparty'
|
21
|
+
|
22
|
+
|
23
|
+
s.rubyforge_project = "nutshell-crm-api"
|
24
|
+
|
25
|
+
s.files = `git ls-files`.split("\n")
|
26
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
27
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
28
|
+
s.require_paths = ["lib"]
|
29
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NutshellCrm::Client do
|
4
|
+
before :all do
|
5
|
+
@api_username = ENV['NUTSHELL_USERNAME']
|
6
|
+
@api_key = ENV['NUTSHELL_APIKEY']
|
7
|
+
@nutshell = NutshellCrm::Client.new @api_username, @api_key
|
8
|
+
@categories = ['Contacts', 'Accounts', 'Leads']
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'client authentication errors' do
|
12
|
+
it 'should set up a new client instance with an invalid username and raise an error' do
|
13
|
+
lambda { NutshellCrm::Client.new('invalid@example.com', 'APIKEY123456') }.should raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should set up a new client instance with a valid username but invalid API key and raise an error' do
|
17
|
+
nutshell = NutshellCrm::Client.new(@api_username, 'APIKEY123456')
|
18
|
+
lambda { nutshell.find_leads({:status => 0}) }.should raise_error
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
subject { @nutshell }
|
23
|
+
|
24
|
+
context 'after a new Nutshell client has been instantiated' do
|
25
|
+
it 'should get a valid API service url that starts with https://' do
|
26
|
+
@nutshell.api_url.should match 'https://'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should consider global stub_response property settings' do
|
30
|
+
@nutshell.stub_responses = false
|
31
|
+
@nutshell.find_leads({:status => 0}).first['stub'].should_not be true
|
32
|
+
@nutshell.stub_responses = true
|
33
|
+
@nutshell.find_leads({:status => 0}).first['stub'].should be true
|
34
|
+
@nutshell.stub_responses = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should find open leads' do
|
38
|
+
@nutshell.find_leads({:status => 0}).should_not be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should describe custom fields' do
|
42
|
+
custom_fields = @nutshell.describe_custom_fields
|
43
|
+
(custom_fields.all? {|k,v| @categories.include? k}).should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should find tags' do
|
47
|
+
tags = @nutshell.find_tags
|
48
|
+
(tags.all? {|k,v| @categories.include? k}).should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should get update times for each provisioning bin' do
|
52
|
+
@nutshell.get_update_times.should_not be_empty
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should return universal search results' do
|
56
|
+
@nutshell.search_universal('A').should_not be_empty
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should create a new tag and find it' do
|
60
|
+
lambda {
|
61
|
+
@nutshell.new_tag({:name => 'FOO2', :entityType => 'Leads'})
|
62
|
+
@nutshell.new_tag({:name => 'FOO2', :entityType => 'Leads'})
|
63
|
+
}.should raise_error
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should return product info' do
|
67
|
+
product = @nutshell.get_product(1)
|
68
|
+
product.should_not be_empty
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should return mobile settings' do
|
72
|
+
mobile_settings = @nutshell.get_mobile_settings
|
73
|
+
mobile_settings.should_not be_empty
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return the logged in user' do
|
77
|
+
user = @nutshell.get_user
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should get and edit a lead' do
|
81
|
+
lead_id = 1001
|
82
|
+
lead = @nutshell.get_lead(lead_id)
|
83
|
+
rev = lead['rev']
|
84
|
+
@nutshell.edit_lead(lead_id, rev, {:description => 'Testing edit.'})
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should return the sources' do
|
88
|
+
@nutshell.search_sources('Cold')
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should update a process step' do
|
92
|
+
step = @nutshell.get_lead(1001)['processes'][0]['steps'][0]
|
93
|
+
current_status = step['status'].to_i
|
94
|
+
|
95
|
+
if current_status < 2
|
96
|
+
@nutshell.edit_step(step['id'], step['rev'], {:status => 2})
|
97
|
+
else
|
98
|
+
lambda { @nutshell.edit_step(step['id'], step['rev'], {:status => 2}) }.should raise_error
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nutshell-crm-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christian Juth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-07-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: yard
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: httparty
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Nutshell CRM's API
|
84
|
+
email:
|
85
|
+
- cjuth2@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rbenv-version"
|
92
|
+
- ".rspec"
|
93
|
+
- ".travis.yml"
|
94
|
+
- CHANGELOG.md
|
95
|
+
- Gemfile
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- lib/nutshell-crm-api.rb
|
99
|
+
- lib/nutshell-crm-api/version.rb
|
100
|
+
- nutshell-crm-api.gemspec
|
101
|
+
- spec/nutshell-crm_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
homepage: https://github.com/Christianjuth/nutshell-crm-api
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project: nutshell-crm-api
|
123
|
+
rubygems_version: 2.4.6
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: A Ruby wrapper for Nutshell CRM's API
|
127
|
+
test_files:
|
128
|
+
- spec/nutshell-crm_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
has_rdoc:
|