ctm 0.4.4 → 0.5.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.
- data/README.md +347 -78
- data/ctm.gemspec +2 -3
- data/examples/example.rb +362 -20
- data/examples/record_sale.rb +1 -1
- data/lib/ctm/account.rb +1 -1
- data/lib/ctm/auth.rb +1 -1
- data/lib/ctm/base.rb +13 -8
- data/lib/ctm/call.rb +26 -13
- data/lib/ctm/error.rb +2 -0
- data/lib/ctm/list.rb +40 -15
- data/lib/ctm/number_list.rb +5 -5
- data/lib/ctm/sale.rb +48 -2
- metadata +3 -2
data/README.md
CHANGED
@@ -11,115 +11,384 @@ Usage
|
|
11
11
|
-----
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
|
15
14
|
require 'ctm'
|
16
15
|
|
17
|
-
#
|
16
|
+
# Authentication
|
17
|
+
|
18
18
|
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
account = access_token.accounts.first
|
21
|
+
number = account.numbers.first
|
22
|
+
|
23
|
+
# Accounts
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
puts "Accounts you have access to (#{access_token.accounts.total_entries}):"
|
26
|
+
access_token.accounts.each do|a|
|
27
|
+
puts " #{a.name} -> #{a.status}, #{a.balance}"
|
28
|
+
end
|
29
|
+
|
30
|
+
puts
|
31
|
+
puts "Select an account:"
|
32
|
+
account = access_token.accounts.first
|
33
|
+
puts " First account: #{account.name}"
|
25
34
|
|
26
|
-
|
27
|
-
|
35
|
+
account = access_token.accounts.find('name' => 'CallTrackingMetrics').first
|
36
|
+
puts " Found by name: #{account.name}"
|
28
37
|
|
29
|
-
#
|
30
|
-
account = CTM::Account.find("name" => "My Account Name")
|
38
|
+
# Tracking Numbers
|
31
39
|
|
32
|
-
|
40
|
+
puts
|
33
41
|
numbers = account.numbers
|
34
|
-
puts numbers.
|
35
|
-
|
36
|
-
puts
|
37
|
-
|
38
|
-
|
39
|
-
puts number.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
numbers =
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
puts "
|
55
|
-
|
56
|
-
|
42
|
+
puts "Tracking Numbers within the Account (#{numbers.total_entries}):"
|
43
|
+
|
44
|
+
puts " Page %-67s %-14s Formatted" % ["ID", "Number"]
|
45
|
+
numbers.each_with_index do|n, i|
|
46
|
+
break if i > 4
|
47
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
48
|
+
end
|
49
|
+
|
50
|
+
puts ' ...'
|
51
|
+
|
52
|
+
numbers.page = numbers.total_pages
|
53
|
+
numbers.entries.reverse.each_with_index do|n, i|
|
54
|
+
break if i > 4
|
55
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
56
|
+
end
|
57
|
+
|
58
|
+
puts
|
59
|
+
puts "Modify routing preferences"
|
60
|
+
[:round_robin, :least_connected, :simultaneous].each do |routing|
|
61
|
+
number.routing = routing
|
62
|
+
puts " #{number.formatted} currently uses #{number.routing} routing"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Receiving Numbers
|
66
|
+
|
67
|
+
numbers = account.receiving_numbers
|
68
|
+
puts
|
69
|
+
puts "Receiving Numbers within the Account (#{numbers.total_entries}):"
|
70
|
+
|
71
|
+
puts " Page %-67s %-14s Formatted" % ["ID", "Number"]
|
72
|
+
numbers.each_with_index do|n, i|
|
73
|
+
break if i > 4
|
74
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
75
|
+
end
|
76
|
+
|
77
|
+
puts ' ...'
|
78
|
+
|
79
|
+
numbers.page = numbers.total_pages
|
80
|
+
numbers.entries.reverse.each_with_index do|n, i|
|
81
|
+
break if i > 4
|
82
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
57
83
|
end
|
58
84
|
|
59
|
-
|
60
|
-
number
|
85
|
+
receiving_number = account.receiving_numbers.create(
|
86
|
+
name: 'demo number', number: '+18008675309'
|
87
|
+
)
|
61
88
|
|
62
|
-
|
63
|
-
|
89
|
+
puts
|
90
|
+
puts "Adding #{receiving_number.formatted}"
|
91
|
+
number.receiving_numbers.add receiving_number
|
64
92
|
|
65
|
-
|
66
|
-
|
93
|
+
puts "Receiving Numbers for #{number.formatted}"
|
94
|
+
number.receiving_numbers.each_page do |page|
|
95
|
+
page.each.map {|n| puts " #{n.formatted}"}
|
96
|
+
end
|
97
|
+
|
98
|
+
puts
|
99
|
+
puts "Removing #{receiving_number.formatted}"
|
100
|
+
number.receiving_numbers.rem receiving_number
|
101
|
+
|
102
|
+
puts "Receiving Numbers for #{number.formatted}"
|
103
|
+
number.receiving_numbers.each_page do |page|
|
104
|
+
page.each {|n| puts " #{n.formatted}"}
|
105
|
+
end
|
106
|
+
|
107
|
+
puts "Releasing #{number.formatted}"
|
108
|
+
receiving_number.release!
|
67
109
|
|
68
|
-
#
|
69
|
-
source = account.sources.find(:name => "Google Adwords")
|
70
|
-
source.landing_url = "utm_campaign=MyCampaign"
|
71
|
-
source.save
|
110
|
+
# Purchasing Numbers
|
72
111
|
|
73
|
-
|
74
|
-
|
112
|
+
puts
|
113
|
+
puts "Search for numbers to buy:"
|
75
114
|
|
76
|
-
|
77
|
-
|
115
|
+
puts " Country Region PostalCode TollFree Number"
|
116
|
+
matches = account.numbers.search("US", searchby: 'tollfree')
|
78
117
|
|
79
|
-
|
80
|
-
receiving_number = account.receiving_numbers.create(name: "my number", number:"+15555555555")
|
118
|
+
total_tollfree = matches.total_entries
|
81
119
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
120
|
+
matches.each_with_index do |n, i|
|
121
|
+
break if i > 10
|
122
|
+
puts " %-7s %-6s %-10s %-8s %s" % [n.iso_country,
|
123
|
+
n.region, n.postal_code,
|
124
|
+
'Yes', n.friendly_name]
|
125
|
+
end
|
126
|
+
puts ' ...'
|
87
127
|
|
88
|
-
|
89
|
-
|
90
|
-
|
128
|
+
matches = account.numbers.search("US",
|
129
|
+
region: 'SC',
|
130
|
+
areacode: 910,
|
131
|
+
pattern: '802'
|
132
|
+
)
|
91
133
|
|
92
|
-
|
93
|
-
|
134
|
+
total_local = matches.total_entries
|
135
|
+
|
136
|
+
matches.each_with_index do |n,i|
|
137
|
+
break if i > 10
|
138
|
+
puts " %-7s %-6s %-10s %-8s %s" % [n.iso_country,
|
139
|
+
n.region, n.postal_code,
|
140
|
+
'No', n.friendly_name]
|
141
|
+
end
|
142
|
+
puts ' ...'
|
143
|
+
|
144
|
+
puts
|
145
|
+
puts "Found #{total_local} local numbers."
|
146
|
+
puts "Found #{total_tollfree} toll-free numbers."
|
147
|
+
|
148
|
+
puts
|
149
|
+
puts "Purchase a number"
|
150
|
+
begin
|
151
|
+
number = account.numbers.buy matches.first.phone_number
|
152
|
+
puts "Successfully purchased the number: #{number.number}"
|
153
|
+
|
154
|
+
similar_numbers = account.numbers('number' => number.number)
|
155
|
+
puts " Search for active numbers matching %s gives %d results:" % [
|
156
|
+
number.number, similar_numbers.total_entries
|
157
|
+
]
|
158
|
+
similar_numbers.each_page do |p| p.each {|n| puts " #{n.number}" }
|
159
|
+
end
|
160
|
+
|
161
|
+
number.release!
|
162
|
+
puts "Released number: #{number.number}"
|
163
|
+
|
164
|
+
similar_numbers = account.numbers('number' => number.number)
|
165
|
+
puts " Search for active numbers matching %s gives %d results:" % [
|
166
|
+
number.number, similar_numbers.total_entries
|
167
|
+
]
|
168
|
+
similar_numbers.each_page do |p| p.each {|n| puts " #{n.number}" }
|
169
|
+
end
|
170
|
+
|
171
|
+
rescue CTM::Error::Buy => e
|
172
|
+
puts "Failed to purchase number (#{number.number}): #{e.message}"
|
173
|
+
end
|
174
|
+
|
175
|
+
# Tracking Sources
|
176
|
+
|
177
|
+
sources = account.sources
|
178
|
+
|
179
|
+
puts
|
180
|
+
puts "Tracking Sources within the Account (#{sources.total_entries})"
|
181
|
+
puts " Page %-5s %-30s Referring URL -> Landing URL" % ["ID","Name"]
|
182
|
+
1.upto(sources.total_pages) do |page|
|
183
|
+
sources.page = page
|
184
|
+
sources.each do|source|
|
185
|
+
puts " %-4d %-5d %-30s '%s' -> '%s'" % [
|
186
|
+
sources.page, source.id,
|
187
|
+
source.name,
|
188
|
+
source.referring_url, source.landing_url]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
src = account.sources.find(name: 'Direct').first
|
193
|
+
id = src.id
|
194
|
+
|
195
|
+
puts
|
196
|
+
puts "Customizing a source #{sources.filters.inspect}"
|
197
|
+
|
198
|
+
puts " Step %-5s %-30s Referring URL -> Landing URL" % ["ID","Name"]
|
199
|
+
puts " Find %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
200
|
+
|
201
|
+
src.landing_url = "utm_campaign=DemoCampain"
|
202
|
+
src.referring_url = "some_search_engine.com"
|
203
|
+
src.name = "Demo Source"
|
204
|
+
puts " Change %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
205
|
+
|
206
|
+
src.save
|
207
|
+
src = sources.get(id)
|
208
|
+
puts " Save %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
209
|
+
|
210
|
+
src.landing_url = ""
|
211
|
+
src.referring_url = ""
|
212
|
+
src.name = "Direct"
|
213
|
+
src.save
|
214
|
+
|
215
|
+
puts " Revert %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
216
|
+
|
217
|
+
# Users
|
94
218
|
|
95
|
-
# list the users
|
96
219
|
users = account.users
|
97
220
|
|
98
|
-
|
99
|
-
|
221
|
+
puts
|
222
|
+
puts "Creating User with email: the.brave.johnny@example.com"
|
223
|
+
jbravo = users.create(
|
224
|
+
first_name: 'Johnny',
|
225
|
+
last_name: 'Bravo',
|
226
|
+
email: 'the.brave.johnny@example.com',
|
227
|
+
role: 'admin',
|
228
|
+
notify: false
|
229
|
+
).id
|
230
|
+
|
231
|
+
puts
|
232
|
+
puts "Users within the Account (#{users.total_entries})"
|
233
|
+
puts " %-40s %-20s %-20s %s" % %w(ID Name Role Email)
|
234
|
+
|
235
|
+
users.each_page do |page|
|
236
|
+
page.each do|user|
|
237
|
+
puts " %-40s %-20s %-20s %s" % [user.id, user.name, user.role, user.email]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
puts
|
242
|
+
puts "Removing User: %s" % [ account.users.get(jbravo).release!['status'] ]
|
100
243
|
|
101
|
-
#
|
102
|
-
account.webhooks.create(weburl: "http://myhost.com/new_calls", position: 'end')
|
244
|
+
# Webhooks
|
103
245
|
|
104
|
-
|
105
|
-
account.webhooks
|
246
|
+
ids = []
|
106
247
|
|
107
|
-
|
108
|
-
|
248
|
+
puts
|
249
|
+
puts "Creating webhook at start and end"
|
250
|
+
ids << account.webhooks.create(
|
251
|
+
weburl: "http://example.com/new_call/start",
|
252
|
+
position: 'start'
|
253
|
+
).id
|
254
|
+
|
255
|
+
ids << account.webhooks.create(
|
256
|
+
weburl: "http://example.com/new_call/end",
|
257
|
+
position: 'end'
|
258
|
+
).id
|
259
|
+
|
260
|
+
puts "Webhooks in account (#{account.webhooks.total_entries}):"
|
261
|
+
puts " %-5s Position WebURL" % ["ID"]
|
262
|
+
account.webhooks.each_page do |page|
|
263
|
+
page.each do |hook|
|
264
|
+
puts " %-5s %-8s %s" % [hook.id, hook.position, hook.weburl]
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
puts "Releasing webhooks"
|
269
|
+
ids.each do |i|
|
270
|
+
res = account.webhooks.get(i).release!
|
271
|
+
|
272
|
+
puts " %s: %s" % [ i, res['status'] == 'deleted' ? res['status'] : res.inspect ]
|
273
|
+
end
|
274
|
+
|
275
|
+
# Calls
|
109
276
|
|
110
277
|
call = account.calls.first
|
278
|
+
call_fmt_str = " %-8s %-20s %-15s %-10s %-10s %-20s %-12s %-20s %-20s %s"
|
279
|
+
|
280
|
+
puts
|
281
|
+
puts "Call Information:"
|
282
|
+
|
283
|
+
puts call_fmt_str % %w(ID Source Likelihood TalkTime RingTime CalledAt DialStatus CallerNumber CallerName Notes)
|
284
|
+
puts call_fmt_str % [
|
285
|
+
call.id,
|
286
|
+
call.source, call.likelihood,
|
287
|
+
call.talk_time, call.ring_time,
|
288
|
+
call.called_at.split(' ')[0..1].join(' '), call.dial_status,
|
289
|
+
call.caller_number_format, call.name,
|
290
|
+
call.notes
|
291
|
+
]
|
292
|
+
|
293
|
+
puts
|
294
|
+
puts "Adding note to call:"
|
295
|
+
old_note = call.notes
|
296
|
+
id = call.id
|
297
|
+
call.notes = "Test Note!"
|
298
|
+
|
299
|
+
puts call_fmt_str % %w(ID Source Likelihood TalkTime RingTime CalledAt
|
300
|
+
DialStatus CallerNumber CallerName Notes)
|
301
|
+
puts call_fmt_str % [
|
302
|
+
call.id,
|
303
|
+
call.source, call.likelihood,
|
304
|
+
call.talk_time, call.ring_time,
|
305
|
+
call.called_at.split(' ')[0..1].join(' '), call.dial_status,
|
306
|
+
call.caller_number_format, call.name,
|
307
|
+
call.notes
|
308
|
+
]
|
111
309
|
|
112
|
-
call.notes = "some notes to attach to the call"
|
113
310
|
call.save
|
114
311
|
|
115
|
-
|
116
|
-
|
312
|
+
call = account.calls.get id
|
313
|
+
puts
|
314
|
+
puts "Deleting note from call:"
|
315
|
+
puts call_fmt_str % %w(ID Source Likelihood TalkTime RingTime CalledAt
|
316
|
+
DialStatus CallerNumber CallerName Notes)
|
317
|
+
puts call_fmt_str % [
|
318
|
+
call.id,
|
319
|
+
call.source, call.likelihood,
|
320
|
+
call.talk_time, call.ring_time,
|
321
|
+
call.called_at.split(' ')[0..1].join(' '), call.dial_status,
|
322
|
+
call.caller_number_format, call.name,
|
323
|
+
call.notes
|
324
|
+
]
|
325
|
+
|
326
|
+
call.notes = old_note
|
327
|
+
call.save
|
117
328
|
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
329
|
+
# Call Sale Record
|
330
|
+
|
331
|
+
old_sale = call.sale
|
332
|
+
|
333
|
+
sale_fmt_str = " %-10s %-10s %-15s %-5s %-5s %-10s"
|
334
|
+
|
335
|
+
puts
|
336
|
+
puts "Editing Sale on Call #{old_sale.call_id}"
|
337
|
+
|
338
|
+
puts sale_fmt_str % ['', *%w(Date CSR Score Value Converted?)]
|
339
|
+
puts sale_fmt_str % ['Existing',
|
340
|
+
old_sale.sale_date,
|
341
|
+
old_sale.name,
|
342
|
+
old_sale.score,
|
343
|
+
old_sale.value,
|
344
|
+
old_sale.conversion,
|
345
|
+
]
|
346
|
+
call.sale.release!
|
347
|
+
|
348
|
+
new_sale = call.sale
|
349
|
+
puts sale_fmt_str % ['Deleted',
|
350
|
+
new_sale.sale_date,
|
351
|
+
new_sale.name,
|
352
|
+
new_sale.score,
|
353
|
+
new_sale.value,
|
354
|
+
new_sale.conversion,
|
355
|
+
]
|
356
|
+
|
357
|
+
new_sale = call.sale
|
358
|
+
new_sale.name = 'The Doctor'
|
359
|
+
new_sale.score = 5
|
360
|
+
new_sale.conversion = true
|
361
|
+
new_sale.value = 12
|
362
|
+
new_sale.sale_date = Date.today.to_s
|
363
|
+
|
364
|
+
puts sale_fmt_str % ['Unsaved',
|
365
|
+
new_sale.sale_date,
|
366
|
+
new_sale.name,
|
367
|
+
new_sale.score,
|
368
|
+
new_sale.value,
|
369
|
+
new_sale.conversion,
|
370
|
+
]
|
371
|
+
|
372
|
+
new_sale.save
|
373
|
+
|
374
|
+
new_sale = call.sale
|
375
|
+
puts sale_fmt_str % ['Refresh',
|
376
|
+
new_sale.sale_date,
|
377
|
+
new_sale.name,
|
378
|
+
new_sale.score,
|
379
|
+
new_sale.value,
|
380
|
+
new_sale.conversion,
|
381
|
+
]
|
382
|
+
|
383
|
+
old_sale.save
|
384
|
+
new_sale = call.sale
|
385
|
+
|
386
|
+
puts sale_fmt_str % ['Restore',
|
387
|
+
new_sale.sale_date,
|
388
|
+
new_sale.name,
|
389
|
+
new_sale.score,
|
390
|
+
new_sale.value,
|
391
|
+
new_sale.conversion,
|
392
|
+
]
|
124
393
|
|
125
394
|
```
|
data/ctm.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "ctm"
|
3
|
-
s.version = "0.
|
4
|
-
s.authors = ["CallTrackingMetrics", "Todd Fisher"]
|
3
|
+
s.version = "0.5.0"
|
4
|
+
s.authors = ["CallTrackingMetrics", "Todd Fisher", "Morgen Peschke"]
|
5
5
|
s.email = "info@calltrackingmetrics.com"
|
6
6
|
s.files = `git ls-files`.split("\n")
|
7
7
|
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
@@ -17,4 +17,3 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_development_dependency 'fakeweb', '~> 1.3.0'
|
18
18
|
s.add_development_dependency "rake"
|
19
19
|
end
|
20
|
-
|
data/examples/example.rb
CHANGED
@@ -1,38 +1,380 @@
|
|
1
1
|
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..", "lib")))
|
2
2
|
require 'ctm'
|
3
3
|
|
4
|
+
# Authentication
|
5
|
+
|
4
6
|
access_token = CTM::Auth.authenticate(ENV['CTM_TOKEN'], ENV['CTM_SECRET'])
|
5
|
-
|
6
|
-
access_token.accounts.
|
7
|
-
|
7
|
+
|
8
|
+
account = access_token.accounts.first
|
9
|
+
number = account.numbers.first
|
10
|
+
|
11
|
+
# Accounts
|
12
|
+
|
13
|
+
puts "Accounts you have access to (#{access_token.accounts.total_entries}):"
|
14
|
+
access_token.accounts.each do|a|
|
15
|
+
puts " #{a.name} -> #{a.status}, #{a.balance}"
|
8
16
|
end
|
17
|
+
|
18
|
+
puts
|
19
|
+
puts "Select an account:"
|
9
20
|
account = access_token.accounts.first
|
21
|
+
puts " First account: #{account.name}"
|
10
22
|
|
23
|
+
account = access_token.accounts.find('name' => 'CallTrackingMetrics').first
|
24
|
+
puts " Found by name: #{account.name}"
|
25
|
+
|
26
|
+
# Tracking Numbers
|
27
|
+
|
28
|
+
puts
|
11
29
|
numbers = account.numbers
|
12
|
-
puts "Tracking Numbers #{numbers.total_entries}
|
13
|
-
|
14
|
-
|
30
|
+
puts "Tracking Numbers within the Account (#{numbers.total_entries}):"
|
31
|
+
|
32
|
+
puts " Page %-67s %-14s Formatted" % ["ID", "Number"]
|
33
|
+
numbers.each_with_index do|n, i|
|
34
|
+
break if i > 4
|
35
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
36
|
+
end
|
37
|
+
|
38
|
+
puts ' ...'
|
39
|
+
|
40
|
+
numbers.page = numbers.total_pages
|
41
|
+
numbers.entries.reverse.each_with_index do|n, i|
|
42
|
+
break if i > 4
|
43
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
44
|
+
end
|
45
|
+
|
46
|
+
puts
|
47
|
+
puts "Modify routing preferences"
|
48
|
+
[:round_robin, :least_connected, :simultaneous].each do |routing|
|
49
|
+
number.routing = routing
|
50
|
+
puts " #{number.formatted} currently uses #{number.routing} routing"
|
51
|
+
end
|
52
|
+
|
53
|
+
# Receiving Numbers
|
54
|
+
|
55
|
+
numbers = account.receiving_numbers
|
56
|
+
puts
|
57
|
+
puts "Receiving Numbers within the Account (#{numbers.total_entries}):"
|
58
|
+
|
59
|
+
puts " Page %-67s %-14s Formatted" % ["ID", "Number"]
|
60
|
+
numbers.each_with_index do|n, i|
|
61
|
+
break if i > 4
|
62
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
63
|
+
end
|
64
|
+
|
65
|
+
puts ' ...'
|
66
|
+
|
67
|
+
numbers.page = numbers.total_pages
|
68
|
+
numbers.entries.reverse.each_with_index do|n, i|
|
69
|
+
break if i > 4
|
70
|
+
puts " %-4d %s %-14s %s" % [numbers.page, n.id, n.number, n.formatted]
|
71
|
+
end
|
72
|
+
|
73
|
+
receiving_number = account.receiving_numbers.create(
|
74
|
+
name: 'demo number', number: '+18008675309'
|
75
|
+
)
|
76
|
+
|
77
|
+
puts
|
78
|
+
puts "Adding #{receiving_number.formatted}"
|
79
|
+
number.receiving_numbers.add receiving_number
|
80
|
+
|
81
|
+
puts "Receiving Numbers for #{number.formatted}"
|
82
|
+
number.receiving_numbers.each_page do |page|
|
83
|
+
page.each.map {|n| puts " #{n.formatted}"}
|
84
|
+
end
|
85
|
+
|
86
|
+
puts
|
87
|
+
puts "Removing #{receiving_number.formatted}"
|
88
|
+
number.receiving_numbers.rem receiving_number
|
89
|
+
|
90
|
+
puts "Receiving Numbers for #{number.formatted}"
|
91
|
+
number.receiving_numbers.each_page do |page|
|
92
|
+
page.each {|n| puts " #{n.formatted}"}
|
93
|
+
end
|
94
|
+
|
95
|
+
puts "Releasing #{number.formatted}"
|
96
|
+
receiving_number.release!
|
97
|
+
|
98
|
+
# Purchasing Numbers
|
99
|
+
|
100
|
+
puts
|
101
|
+
puts "Search for numbers to buy:"
|
102
|
+
|
103
|
+
puts " Country Region PostalCode TollFree Number"
|
104
|
+
matches = account.numbers.search("US", searchby: 'tollfree')
|
105
|
+
|
106
|
+
total_tollfree = matches.total_entries
|
107
|
+
|
108
|
+
matches.each_with_index do |n, i|
|
109
|
+
break if i > 10
|
110
|
+
puts " %-7s %-6s %-10s %-8s %s" % [n.iso_country,
|
111
|
+
n.region, n.postal_code,
|
112
|
+
'Yes', n.friendly_name]
|
15
113
|
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
114
|
+
puts ' ...'
|
115
|
+
|
116
|
+
matches = account.numbers.search("US",
|
117
|
+
region: 'SC',
|
118
|
+
areacode: 910,
|
119
|
+
pattern: '802'
|
120
|
+
)
|
121
|
+
|
122
|
+
total_local = matches.total_entries
|
123
|
+
|
124
|
+
matches.each_with_index do |n,i|
|
125
|
+
break if i > 10
|
126
|
+
puts " %-7s %-6s %-10s %-8s %s" % [n.iso_country,
|
127
|
+
n.region, n.postal_code,
|
128
|
+
'No', n.friendly_name]
|
20
129
|
end
|
130
|
+
puts ' ...'
|
131
|
+
|
132
|
+
puts
|
133
|
+
puts "Found #{total_local} local numbers."
|
134
|
+
puts "Found #{total_tollfree} toll-free numbers."
|
135
|
+
|
136
|
+
puts
|
137
|
+
puts "Purchase a number"
|
138
|
+
begin
|
139
|
+
number = account.numbers.buy matches.first.phone_number
|
140
|
+
puts "Successfully purchased the number: #{number.number}"
|
141
|
+
|
142
|
+
similar_numbers = account.numbers('number' => number.number)
|
143
|
+
puts " Search for active numbers matching %s gives %d results:" % [
|
144
|
+
number.number, similar_numbers.total_entries
|
145
|
+
]
|
146
|
+
similar_numbers.each_page do |p| p.each {|n| puts " #{n.number}" }
|
147
|
+
end
|
148
|
+
|
149
|
+
number.release!
|
150
|
+
puts "Released number: #{number.number}"
|
151
|
+
|
152
|
+
similar_numbers = account.numbers('number' => number.number)
|
153
|
+
puts " Search for active numbers matching %s gives %d results:" % [
|
154
|
+
number.number, similar_numbers.total_entries
|
155
|
+
]
|
156
|
+
similar_numbers.each_page do |p| p.each {|n| puts " #{n.number}" }
|
157
|
+
end
|
158
|
+
|
159
|
+
rescue CTM::Error::Buy => e
|
160
|
+
puts "Failed to purchase number (#{number.number}): #{e.message}"
|
161
|
+
end
|
162
|
+
|
163
|
+
# Tracking Sources
|
21
164
|
|
22
165
|
sources = account.sources
|
23
|
-
|
24
|
-
|
25
|
-
|
166
|
+
|
167
|
+
puts
|
168
|
+
puts "Tracking Sources within the Account (#{sources.total_entries})"
|
169
|
+
puts " Page %-5s %-30s Referring URL -> Landing URL" % ["ID","Name"]
|
170
|
+
1.upto(sources.total_pages) do |page|
|
171
|
+
sources.page = page
|
172
|
+
sources.each do|source|
|
173
|
+
puts " %-4d %-5d %-30s '%s' -> '%s'" % [
|
174
|
+
sources.page, source.id,
|
175
|
+
source.name,
|
176
|
+
source.referring_url, source.landing_url]
|
177
|
+
end
|
26
178
|
end
|
27
179
|
|
180
|
+
src = account.sources.find(name: 'Direct').first
|
181
|
+
id = src.id
|
182
|
+
|
183
|
+
puts
|
184
|
+
puts "Customizing a source #{sources.filters.inspect}"
|
185
|
+
|
186
|
+
puts " Step %-5s %-30s Referring URL -> Landing URL" % ["ID","Name"]
|
187
|
+
puts " Find %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
188
|
+
|
189
|
+
src.landing_url = "utm_campaign=DemoCampain"
|
190
|
+
src.referring_url = "some_search_engine.com"
|
191
|
+
src.name = "Demo Source"
|
192
|
+
puts " Change %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
193
|
+
|
194
|
+
src.save
|
195
|
+
src = sources.get(id)
|
196
|
+
puts " Save %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
197
|
+
|
198
|
+
src.landing_url = ""
|
199
|
+
src.referring_url = ""
|
200
|
+
src.name = "Direct"
|
201
|
+
src.save
|
202
|
+
|
203
|
+
puts " Revert %-5d %-30s '%s' -> '%s'" % [src.id, src.name, src.referring_url, src.landing_url]
|
204
|
+
|
205
|
+
# Users
|
206
|
+
|
28
207
|
users = account.users
|
29
|
-
|
30
|
-
|
31
|
-
|
208
|
+
|
209
|
+
puts
|
210
|
+
puts "Creating User with email: the.brave.johnny@example.com"
|
211
|
+
jbravo = users.create(
|
212
|
+
first_name: 'Johnny',
|
213
|
+
last_name: 'Bravo',
|
214
|
+
email: 'the.brave.johnny@example.com',
|
215
|
+
role: 'admin',
|
216
|
+
notify: false
|
217
|
+
).id
|
218
|
+
|
219
|
+
puts
|
220
|
+
puts "Users within the Account (#{users.total_entries})"
|
221
|
+
puts " %-40s %-20s %-20s %s" % %w(ID Name Role Email)
|
222
|
+
|
223
|
+
users.each_page do |page|
|
224
|
+
page.each do|user|
|
225
|
+
puts " %-40s %-20s %-20s %s" % [user.id, user.name, user.role, user.email]
|
226
|
+
end
|
32
227
|
end
|
33
228
|
|
34
|
-
|
35
|
-
puts "
|
36
|
-
|
37
|
-
|
229
|
+
puts
|
230
|
+
puts "Removing User: %s" % [ account.users.get(jbravo).release!['status'] ]
|
231
|
+
|
232
|
+
# Webhooks
|
233
|
+
|
234
|
+
ids = []
|
235
|
+
|
236
|
+
puts
|
237
|
+
puts "Creating webhook at start and end"
|
238
|
+
ids << account.webhooks.create(
|
239
|
+
weburl: "http://example.com/new_call/start",
|
240
|
+
position: 'start'
|
241
|
+
).id
|
242
|
+
|
243
|
+
ids << account.webhooks.create(
|
244
|
+
weburl: "http://example.com/new_call/end",
|
245
|
+
position: 'end'
|
246
|
+
).id
|
247
|
+
|
248
|
+
puts "Webhooks in account (#{account.webhooks.total_entries}):"
|
249
|
+
puts " %-5s Position WebURL" % ["ID"]
|
250
|
+
account.webhooks.each_page do |page|
|
251
|
+
page.each do |hook|
|
252
|
+
puts " %-5s %-8s %s" % [hook.id, hook.position, hook.weburl]
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
puts "Releasing webhooks"
|
257
|
+
ids.each do |i|
|
258
|
+
res = account.webhooks.get(i).release!
|
259
|
+
|
260
|
+
puts " %s: %s" % [ i, res['status'] == 'deleted' ? res['status'] : res.inspect ]
|
38
261
|
end
|
262
|
+
|
263
|
+
# Calls
|
264
|
+
|
265
|
+
call = account.calls.first
|
266
|
+
call_fmt_str = " %-8s %-20s %-15s %-10s %-10s %-20s %-12s %-20s %-20s %s"
|
267
|
+
|
268
|
+
puts
|
269
|
+
puts "Call Information:"
|
270
|
+
|
271
|
+
puts call_fmt_str % %w(ID Source Likelihood TalkTime RingTime CalledAt DialStatus CallerNumber CallerName Notes)
|
272
|
+
puts call_fmt_str % [
|
273
|
+
call.id,
|
274
|
+
call.source, call.likelihood,
|
275
|
+
call.talk_time, call.ring_time,
|
276
|
+
call.called_at.split(' ')[0..1].join(' '), call.dial_status,
|
277
|
+
call.caller_number_format, call.name,
|
278
|
+
call.notes
|
279
|
+
]
|
280
|
+
|
281
|
+
puts
|
282
|
+
puts "Adding note to call:"
|
283
|
+
old_note = call.notes
|
284
|
+
id = call.id
|
285
|
+
call.notes = "Test Note!"
|
286
|
+
|
287
|
+
puts call_fmt_str % %w(ID Source Likelihood TalkTime RingTime CalledAt
|
288
|
+
DialStatus CallerNumber CallerName Notes)
|
289
|
+
puts call_fmt_str % [
|
290
|
+
call.id,
|
291
|
+
call.source, call.likelihood,
|
292
|
+
call.talk_time, call.ring_time,
|
293
|
+
call.called_at.split(' ')[0..1].join(' '), call.dial_status,
|
294
|
+
call.caller_number_format, call.name,
|
295
|
+
call.notes
|
296
|
+
]
|
297
|
+
|
298
|
+
call.save
|
299
|
+
|
300
|
+
call = account.calls.get id
|
301
|
+
puts
|
302
|
+
puts "Deleting note from call:"
|
303
|
+
puts call_fmt_str % %w(ID Source Likelihood TalkTime RingTime CalledAt
|
304
|
+
DialStatus CallerNumber CallerName Notes)
|
305
|
+
puts call_fmt_str % [
|
306
|
+
call.id,
|
307
|
+
call.source, call.likelihood,
|
308
|
+
call.talk_time, call.ring_time,
|
309
|
+
call.called_at.split(' ')[0..1].join(' '), call.dial_status,
|
310
|
+
call.caller_number_format, call.name,
|
311
|
+
call.notes
|
312
|
+
]
|
313
|
+
|
314
|
+
call.notes = old_note
|
315
|
+
call.save
|
316
|
+
|
317
|
+
# Call Sale Record
|
318
|
+
|
319
|
+
old_sale = call.sale
|
320
|
+
|
321
|
+
sale_fmt_str = " %-10s %-10s %-15s %-5s %-5s %-10s"
|
322
|
+
|
323
|
+
puts
|
324
|
+
puts "Editing Sale on Call #{old_sale.call_id}"
|
325
|
+
|
326
|
+
puts sale_fmt_str % ['', *%w(Date CSR Score Value Converted?)]
|
327
|
+
puts sale_fmt_str % ['Existing',
|
328
|
+
old_sale.sale_date,
|
329
|
+
old_sale.name,
|
330
|
+
old_sale.score,
|
331
|
+
old_sale.value,
|
332
|
+
old_sale.conversion,
|
333
|
+
]
|
334
|
+
call.sale.release!
|
335
|
+
|
336
|
+
new_sale = call.sale
|
337
|
+
puts sale_fmt_str % ['Deleted',
|
338
|
+
new_sale.sale_date,
|
339
|
+
new_sale.name,
|
340
|
+
new_sale.score,
|
341
|
+
new_sale.value,
|
342
|
+
new_sale.conversion,
|
343
|
+
]
|
344
|
+
|
345
|
+
new_sale = call.sale
|
346
|
+
new_sale.name = 'The Doctor'
|
347
|
+
new_sale.score = 5
|
348
|
+
new_sale.conversion = true
|
349
|
+
new_sale.value = 12
|
350
|
+
new_sale.sale_date = Date.today.to_s
|
351
|
+
|
352
|
+
puts sale_fmt_str % ['Unsaved',
|
353
|
+
new_sale.sale_date,
|
354
|
+
new_sale.name,
|
355
|
+
new_sale.score,
|
356
|
+
new_sale.value,
|
357
|
+
new_sale.conversion,
|
358
|
+
]
|
359
|
+
|
360
|
+
new_sale.save
|
361
|
+
|
362
|
+
new_sale = call.sale
|
363
|
+
puts sale_fmt_str % ['Refresh',
|
364
|
+
new_sale.sale_date,
|
365
|
+
new_sale.name,
|
366
|
+
new_sale.score,
|
367
|
+
new_sale.value,
|
368
|
+
new_sale.conversion,
|
369
|
+
]
|
370
|
+
|
371
|
+
old_sale.save
|
372
|
+
new_sale = call.sale
|
373
|
+
|
374
|
+
puts sale_fmt_str % ['Restore',
|
375
|
+
new_sale.sale_date,
|
376
|
+
new_sale.name,
|
377
|
+
new_sale.score,
|
378
|
+
new_sale.value,
|
379
|
+
new_sale.conversion,
|
380
|
+
]
|
data/examples/record_sale.rb
CHANGED
data/lib/ctm/account.rb
CHANGED
data/lib/ctm/auth.rb
CHANGED
data/lib/ctm/base.rb
CHANGED
@@ -12,7 +12,7 @@ module CTM
|
|
12
12
|
end
|
13
13
|
|
14
14
|
include HTTParty
|
15
|
-
base_uri ENV["CTM_URL"] || "api.calltrackingmetrics.com"
|
15
|
+
base_uri "https://#{(ENV["CTM_URL"] || "api.calltrackingmetrics.com")}"
|
16
16
|
|
17
17
|
attr_reader :token, :account_id
|
18
18
|
|
@@ -20,7 +20,11 @@ module CTM
|
|
20
20
|
def initialize(data, token=nil)
|
21
21
|
@token = token || CTM::Auth.token
|
22
22
|
@account_id = data['account_id']
|
23
|
-
@list_token_type = self.class.to_s
|
23
|
+
@list_token_type = case self.class.to_s
|
24
|
+
when 'CTM::Sale' then 'calls'
|
25
|
+
else
|
26
|
+
self.class.to_s.sub(/CTM::/,'').underscore.pluralize
|
27
|
+
end
|
24
28
|
if @account_id
|
25
29
|
@list_type_path = "accounts/#{@account_id}/#{@list_token_type}"
|
26
30
|
else
|
@@ -29,15 +33,16 @@ module CTM
|
|
29
33
|
end
|
30
34
|
|
31
35
|
def save(options={})
|
32
|
-
puts "save: #{options.inspect}"
|
36
|
+
#puts "save: #{options.inspect}"
|
33
37
|
path_str = "/api/v1/#{@list_type_path}/#{@id}.json"
|
34
|
-
puts path_str
|
35
|
-
|
38
|
+
#puts path_str
|
39
|
+
self.class.put(path_str, :body => options.merge(:auth_token => @token))
|
36
40
|
end
|
37
41
|
|
38
42
|
def release!
|
39
43
|
path_str = "/api/v1/#{@list_type_path}/#{@id}.json"
|
40
44
|
res = self.class.delete(path_str, :body => {:auth_token => @token})
|
45
|
+
res.parsed_response
|
41
46
|
end
|
42
47
|
|
43
48
|
def self.create(options)
|
@@ -46,10 +51,10 @@ module CTM
|
|
46
51
|
account_id = options.delete(:account_id)
|
47
52
|
token = options.delete(:token)
|
48
53
|
path_str = "/api/v1/#{list_type_path}.json"
|
49
|
-
puts "create: #{self}(#{path_str}) -> #{options.inspect}"
|
54
|
+
#puts "create: #{self}(#{path_str}) -> #{options.inspect}"
|
50
55
|
res = self.post(path_str, :body => options.merge(:auth_token => token))
|
51
|
-
puts "result: #{res.parsed_response.inspect}"
|
52
|
-
puts "properties: #{list_type_path.inspect} -> #{list_token_type.inspect} -> #{account_id}"
|
56
|
+
#puts "result: #{res.parsed_response.inspect}"
|
57
|
+
#puts "properties: #{list_type_path.inspect} -> #{list_token_type.inspect} -> #{account_id}"
|
53
58
|
if res.parsed_response['status'] == 'error'
|
54
59
|
raise CTM::Error::Create.new(res.parsed_response['reason'])
|
55
60
|
else
|
data/lib/ctm/call.rb
CHANGED
@@ -4,12 +4,12 @@ module CTM
|
|
4
4
|
:id, :account_id, :search, :referrer, :location, :source,
|
5
5
|
:likelihood, :duration, :talk_time, :ring_time, :called_at, :tracking_number, :business_number,
|
6
6
|
:dial_status, :caller_number_split, :excluded, :tracking_number_format, :business_number_format,
|
7
|
-
:caller_number_format, :audio, :tag_list, :latitude, :longitude, :extended_lookup
|
7
|
+
:caller_number_format, :audio, :tag_list, :latitude, :longitude, :extended_lookup
|
8
8
|
]
|
9
9
|
ReadWriteFields = [
|
10
10
|
:name, :email, :street, :city, :state, :country, :postal_code, :notes
|
11
11
|
]
|
12
|
-
attr_reader
|
12
|
+
attr_reader *ReadOnlyFields
|
13
13
|
attr_accessor *ReadWriteFields
|
14
14
|
|
15
15
|
# {"id":729485,"account_id":25,"name":"Escondido Ca","search":null,"referrer":null,"location":null,"source":"Facebook","source_id":36,"likelihood":null,"duration":25,
|
@@ -29,20 +29,33 @@ module CTM
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
post_options[k] = v
|
32
|
+
def save(options={})
|
33
|
+
#puts "save: #{options.inspect}"
|
34
|
+
path_str = "/api/v1/#{@list_type_path}/#{@id}/modify.json"
|
35
|
+
|
36
|
+
save_options = {}
|
37
|
+
ReadWriteFields.each do |field|
|
38
|
+
save_options[field == :notes ? :comments : field] = self.send field
|
40
39
|
end
|
41
|
-
|
42
|
-
|
40
|
+
|
41
|
+
options[:call] = (options[:call] || {}).merge save_options
|
42
|
+
|
43
|
+
#puts path_str
|
44
|
+
self.class.put(path_str, :body => options.merge(:auth_token => @token))
|
43
45
|
end
|
44
46
|
|
45
|
-
def
|
47
|
+
def sale
|
48
|
+
path_str = "/api/v1/#{@list_type_path}/#{self.id}/sale.json"
|
49
|
+
|
50
|
+
res = self.class.get path_str, query: {auth_token: @token}
|
51
|
+
data = res.parsed_response
|
52
|
+
if data["status"] && data["status"] == "error"
|
53
|
+
raise CTM::Error::Sale.new(data["message"] || data ["reason"])
|
54
|
+
end
|
55
|
+
|
56
|
+
data['account_id'] = @account_id
|
57
|
+
data['call_id'] ||= self.id
|
58
|
+
CTM::Sale.new(data, @token)
|
46
59
|
end
|
47
60
|
|
48
61
|
end
|
data/lib/ctm/error.rb
CHANGED
data/lib/ctm/list.rb
CHANGED
@@ -4,9 +4,12 @@ module CTM
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
include HTTParty
|
7
|
-
base_uri ENV["CTM_URL"] || "api.calltrackingmetrics.com"
|
7
|
+
base_uri "https://#{(ENV["CTM_URL"] || "api.calltrackingmetrics.com")}"
|
8
8
|
|
9
|
-
attr_reader :list_type, :token, :
|
9
|
+
attr_reader :list_type, :token, :total_entries, :objects
|
10
|
+
attr_reader :per_page, :page, :total_pages
|
11
|
+
|
12
|
+
attr_reader :filters
|
10
13
|
|
11
14
|
# e.g. Account, token
|
12
15
|
def initialize(list_type, options={}, token=nil, fetched_objects=nil)
|
@@ -23,16 +26,32 @@ module CTM
|
|
23
26
|
|
24
27
|
@fetched_objects = fetched_objects
|
25
28
|
@options = options
|
29
|
+
@filters = {}
|
30
|
+
load_records
|
31
|
+
end
|
32
|
+
|
33
|
+
def page=(num)
|
34
|
+
@options[:page] = num.to_i
|
35
|
+
fetch_page(@options) unless @options[:page] == @page
|
36
|
+
@page
|
26
37
|
end
|
27
38
|
|
28
|
-
def
|
39
|
+
def each_page
|
40
|
+
# Trick to allow .each_page.each_with_index from:
|
41
|
+
# http://stackoverflow.com/a/18089712
|
42
|
+
return to_enum(:each_page) unless block_given?
|
43
|
+
|
44
|
+
1.upto(@total_pages) do |pnum|
|
45
|
+
self.page = pnum
|
46
|
+
yield self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def each
|
51
|
+
return to_enum(:each) unless block_given?
|
29
52
|
load_records
|
30
53
|
@objects.each do |obj|
|
31
|
-
|
32
|
-
block.call obj
|
33
|
-
else
|
34
|
-
yield obj
|
35
|
-
end
|
54
|
+
yield obj
|
36
55
|
end
|
37
56
|
end
|
38
57
|
|
@@ -43,12 +62,16 @@ module CTM
|
|
43
62
|
token: @token))
|
44
63
|
end
|
45
64
|
|
46
|
-
def find(options)
|
65
|
+
def find(options = {})
|
66
|
+
return self unless options.class == Hash
|
67
|
+
|
47
68
|
first_name = options.delete(:first_name)
|
48
69
|
last_name = options.delete(:last_name)
|
49
70
|
options[:filter] = options.delete(:filter) || "#{first_name} #{last_name}".strip if first_name || last_name
|
50
71
|
|
51
|
-
|
72
|
+
@filters = options
|
73
|
+
|
74
|
+
self.page = 1
|
52
75
|
self
|
53
76
|
end
|
54
77
|
|
@@ -56,7 +79,7 @@ module CTM
|
|
56
79
|
path_str = "/api/v1/#{@list_type_path}/#{recordid}.json"
|
57
80
|
res = self.class.get(path_str, query: options.merge(auth_token: @token))
|
58
81
|
data = res.parsed_response
|
59
|
-
@object_klass.new(data, @token)
|
82
|
+
@object_klass.new(data, @token)
|
60
83
|
end
|
61
84
|
|
62
85
|
protected
|
@@ -70,7 +93,7 @@ module CTM
|
|
70
93
|
end
|
71
94
|
|
72
95
|
def fetch_page(options={})
|
73
|
-
options = {per_page: 10, page: 1}.merge(options)
|
96
|
+
options = {per_page: 10, page: 1}.merge(options).merge(@filters)
|
74
97
|
path_str = "/api/v1/#{@list_type_path}.json"
|
75
98
|
res = self.class.get(path_str, query: options.merge(auth_token: @token))
|
76
99
|
data = res.parsed_response
|
@@ -78,15 +101,17 @@ module CTM
|
|
78
101
|
puts data.inspect
|
79
102
|
raise CTM::Error::List.new(data["message"] || data["reason"])
|
80
103
|
end
|
104
|
+
|
105
|
+
@page = options[:page]
|
106
|
+
@per_page = options[:per_page]
|
81
107
|
map_data(data)
|
82
108
|
end
|
83
109
|
|
84
110
|
def map_data(data)
|
85
|
-
@page = data['page']
|
86
|
-
@per_page = data['per_page']
|
87
111
|
@total_entries = data['total_entries']
|
112
|
+
@total_pages = data['total_pages']
|
88
113
|
@objects = data[@list_token_type].map {|obj|
|
89
|
-
@object_klass.new(obj, @token)
|
114
|
+
@object_klass.new(obj, @token)
|
90
115
|
}
|
91
116
|
end
|
92
117
|
|
data/lib/ctm/number_list.rb
CHANGED
@@ -42,7 +42,7 @@ module CTM
|
|
42
42
|
# add trackng number to tracking source
|
43
43
|
def add(number)
|
44
44
|
path_str = "/api/v1/#{@list_type_path}/#{number.id}/add.json"
|
45
|
-
puts "Add to #{@account_id}:#{@source_id} -> #{number.id} -> #{path_str}"
|
45
|
+
#puts "Add to #{@account_id}:#{@source_id} -> #{number.id} -> #{path_str}"
|
46
46
|
# accounts/25 /sources/5012 /numbers
|
47
47
|
# /api/v1/accounts/:account_id/sources/:source_id/numbers/:id/add
|
48
48
|
res = self.class.post(path_str, :body => {}.merge(:auth_token => @token))
|
@@ -54,10 +54,10 @@ module CTM
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def rem
|
58
|
-
|
59
|
-
|
60
|
-
end
|
57
|
+
# def rem(number)
|
58
|
+
# puts "Rem to #{@account_id}:#{@source_id} -> #{number.id} -> #{@list_type_path}"
|
59
|
+
# # /api/v1/accounts/:account_id/sources/:source_id/numbers/:id/rem
|
60
|
+
# end
|
61
61
|
|
62
62
|
end
|
63
63
|
end
|
data/lib/ctm/sale.rb
CHANGED
@@ -1,7 +1,53 @@
|
|
1
1
|
module CTM
|
2
|
-
class Sale
|
2
|
+
class Sale < Base
|
3
|
+
ReadWriteFields = [:conversion,
|
4
|
+
:sale_date, :score,
|
5
|
+
:service_rep_name, :value]
|
3
6
|
|
4
|
-
|
7
|
+
attr_reader :call_id
|
8
|
+
attr_accessor(*ReadWriteFields)
|
9
|
+
|
10
|
+
def initialize(data, token=nil)
|
11
|
+
super(data, token)
|
12
|
+
|
13
|
+
[ :call_id, *ReadWriteFields].each do |k|
|
14
|
+
instance_variable_set "@#{k}", data[k.to_s]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def name
|
19
|
+
@service_rep_name
|
20
|
+
end
|
21
|
+
|
22
|
+
def name=(n)
|
23
|
+
@service_rep_name = n
|
24
|
+
@service_rep_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def release!
|
28
|
+
path_str ="/api/v1/#{@list_type_path}/#{@call_id}/sale.json"
|
29
|
+
res = self.class.delete path_str, body: {auth_token: @token}
|
30
|
+
res.parsed_response
|
31
|
+
end
|
32
|
+
|
33
|
+
def save(options = {})
|
34
|
+
path_str = "/api/v1/#{@list_type_path}/#{@call_id}/sale.json"
|
35
|
+
options = {}
|
36
|
+
ReadWriteFields.each do |k|
|
37
|
+
v = self.send k
|
38
|
+
case k.to_s
|
39
|
+
when 'conversion' then v = v ? 'on' : 'off'
|
40
|
+
when 'service_rep_name' then k = :name
|
41
|
+
end
|
42
|
+
options[k] = v
|
43
|
+
end
|
44
|
+
options[:id] = @call_id
|
45
|
+
|
46
|
+
#self.class.debug_output $stderr
|
47
|
+
res = self.class.post path_str, body: options.merge(auth_token: @token)
|
48
|
+
#self.class.debug_output nil
|
49
|
+
return nil unless res
|
50
|
+
(res['status'] == 'success') ? true : (res['message'] || res['reason'])
|
5
51
|
end
|
6
52
|
|
7
53
|
end
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ctm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- CallTrackingMetrics
|
9
9
|
- Todd Fisher
|
10
|
+
- Morgen Peschke
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date:
|
14
|
+
date: 2014-05-01 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: phony
|