zoho_service 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +98 -0
- data/Rakefile +6 -0
- data/bin/zoho_service +122 -0
- data/lib/zoho_service.rb +49 -0
- data/lib/zoho_service/Hash.rb +9 -0
- data/lib/zoho_service/api_collection.rb +108 -0
- data/lib/zoho_service/api_connector.rb +90 -0
- data/lib/zoho_service/base.rb +125 -0
- data/lib/zoho_service/version.rb +3 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/zoho_service_spec.rb +9 -0
- data/zoho_service.gemspec +54 -0
- metadata +159 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7f5ff3ce5a4d2491f6b4c9cabeb677e976e1470370388bddc5d3195481f877fd
|
4
|
+
data.tar.gz: de8ce4a34eb71e3dba3efc4bc5f59e1db867e4ff181d52499e0e218b21f45e14
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6144f70309bbb7954691626e78016b6d5a661f1a4801bd5b01563699441e65ecd756481f916536556b18d76ff9f733bf69dd11ff85da396f44efcce6a68b1213
|
7
|
+
data.tar.gz: 987c837dee3efc38ca99fd40d33e88d1d5a879b57667cf0478f8a200332b317473da806db4bf67305e608806b1c346986df9ac73a6a8718bd651ac2b8d4d21c2
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2017 chaky222
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
zoho_service gem
|
2
|
+
=============================
|
3
|
+
|
4
|
+
zoho_service gem is a library to read, update and delete data in Zoho Service Desk.
|
5
|
+
|
6
|
+
https://desk.zoho.com/DeskAPIDocument#Introduction
|
7
|
+
|
8
|
+
## Support Modules (see and onn/off at lib/zoho_service.rb)
|
9
|
+
- [x] organizations
|
10
|
+
- [x] tickets [comments threads attachments timeEntries]
|
11
|
+
- [x] contacts
|
12
|
+
- [x] tasks
|
13
|
+
- [x] accounts
|
14
|
+
- [x] tasks
|
15
|
+
- [x] agents
|
16
|
+
- [x] departments
|
17
|
+
### Not ready yet:
|
18
|
+
- [ ] uploads
|
19
|
+
- [ ] search [searchStr sortBy]
|
20
|
+
- [ ] mailReplyAddress
|
21
|
+
- [ ] from & limit
|
22
|
+
- [ ] sortBy
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Add this line to your application's Gemfile:
|
27
|
+
|
28
|
+
|
29
|
+
And then execute:
|
30
|
+
|
31
|
+
$ bundle install
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
$ gem install zoho_service
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
### Get the token
|
40
|
+
|
41
|
+
You can get the token read "Zoho Service Desk API documentation" available here:
|
42
|
+
|
43
|
+
https://desk.zoho.com/DeskAPIDocument
|
44
|
+
|
45
|
+
### Setup Token and Host
|
46
|
+
|
47
|
+
Before accessing ZohoService, you must first configure the connector with token.
|
48
|
+
|
49
|
+
require "zoho_service"
|
50
|
+
zoho_service_connector = ZohoService::ApiConnector.new('224d6ade955bbb18f82ebd00f5c6642e')
|
51
|
+
puts zoho_service_connector.organizations.to_json
|
52
|
+
puts zoho_service_connector.tickets.to_json
|
53
|
+
puts zoho_service_connector.tickets.first.comments.to_json
|
54
|
+
|
55
|
+
Example how to use this gem you can find in file 'bin/zoho_service'. Here some lines from it:
|
56
|
+
```ruby
|
57
|
+
require 'zoho_service'
|
58
|
+
zoho_conn = ZohoService::ApiConnector.new('224d6ade955bbb18f82ebd00f5c6642e', {}, true)
|
59
|
+
|
60
|
+
# ticket = c.tickets.first.update(subject: 'zzzz Вот ваш первый талон.')
|
61
|
+
# ticket = c.tickets.first
|
62
|
+
|
63
|
+
ticket = zoho_conn.tickets.new({
|
64
|
+
"subCategory": "Sub General",
|
65
|
+
"contactId": zoho_conn.contacts.first.id,
|
66
|
+
"subject": "100500 started",
|
67
|
+
"dueDate": (Time.now + 300.days).utc,
|
68
|
+
"departmentId": zoho_conn.departments.first.id,
|
69
|
+
"channel": "Email",
|
70
|
+
"description": "Hai This is Description",
|
71
|
+
"assigneeId": zoho_conn.agents.first.id,
|
72
|
+
"phone": "1 888 900 9646",
|
73
|
+
"email": "example@example.com",
|
74
|
+
"status": "Open"
|
75
|
+
}).save!
|
76
|
+
|
77
|
+
puts "\n\n ticket=[#{ticket.to_json}] \n\n"
|
78
|
+
|
79
|
+
comm = ticket.comments.create({
|
80
|
+
"isPublic": "true",
|
81
|
+
"content": "comm 1005002"
|
82
|
+
})
|
83
|
+
|
84
|
+
comm = ticket.comments.new({
|
85
|
+
"isPublic": "true",
|
86
|
+
"content": "comm 1005003"
|
87
|
+
}).save!
|
88
|
+
|
89
|
+
comm = ticket.comments.first
|
90
|
+
comm.delete!
|
91
|
+
|
92
|
+
puts "\n\n comm=[#{comm.to_json}] \n\n"
|
93
|
+
|
94
|
+
ticket.update(description: ticket.description + ' bla-bla-bla ')
|
95
|
+
|
96
|
+
```
|
97
|
+
|
98
|
+
My mail=chaky22222222@gmail.com.
|
data/Rakefile
ADDED
data/bin/zoho_service
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'zoho_service'
|
3
|
+
|
4
|
+
@zoho_conn = ZohoService::ApiConnector.new('80aea8029f7c4648f1a9d118e0e5df8a', { api_url: 'https://desk.zoho.eu/api/v1' }, true)
|
5
|
+
# ticket = zoho_conn.tickets.first
|
6
|
+
|
7
|
+
# puts "\n\n tickets=[#{zoho_conn.tickets.to_json}] \n\n"
|
8
|
+
# puts "\n\n contacts=[#{zoho_conn.contacts.to_json}] \n\n"
|
9
|
+
# puts "\n\n agents=[#{zoho_conn.agents.to_json}] \n\n"
|
10
|
+
|
11
|
+
# contacts = @zoho_conn.contacts
|
12
|
+
|
13
|
+
# puts "\n\n contacts=[#{contacts.to_json}] \n\n"
|
14
|
+
|
15
|
+
phone = '+380681765911'
|
16
|
+
# contact = zoho_conn.contacts.find_or_initialize_by({ phone: phone }, { lastName: 'Client_'+phone })
|
17
|
+
# @zoho_conn.contacts.create(lastName: name, phone: attrs[:phone], ownerId: crm_id)
|
18
|
+
|
19
|
+
# # # arr1 = zoho_conn.tickets.map { |x| x.id }.sort
|
20
|
+
|
21
|
+
|
22
|
+
def get_agent
|
23
|
+
@zoho_conn.agents&.select { |x| x.id == '258000000002-5005' }.first&.id ||
|
24
|
+
@zoho_conn.agents&.select { |x| x.id == 12312 }.first&.id ||
|
25
|
+
@zoho_conn.agents&.first&.id
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_contact(lead_type, attrs)
|
29
|
+
name = attrs[:name] || "#{lead_type} #{attrs[:phone]}"
|
30
|
+
@zoho_conn.contacts.create(lastName: name, phone: attrs[:phone], ownerId: get_agent() )
|
31
|
+
end
|
32
|
+
|
33
|
+
lead_type = 'входящий лид'
|
34
|
+
target_phone = '+380666679921'
|
35
|
+
|
36
|
+
contact = create_contact(lead_type, phone: target_phone)
|
37
|
+
puts "\n\n contact=[#{contact.to_json}] \n\n"
|
38
|
+
# ticket = zoho_conn.tickets.new({
|
39
|
+
# "subCategory": "Sub General",
|
40
|
+
# "contactId": contact.id,
|
41
|
+
# "subject": "100500 started",
|
42
|
+
# # "dueDate": (Time.now + 300.days).utc,
|
43
|
+
# # "departmentId": zoho_conn.departments.first.id,
|
44
|
+
# "channel": "Phone",
|
45
|
+
# "description": "Hai This is Description",
|
46
|
+
# "assigneeId": zoho_conn.agents.first.id,
|
47
|
+
# "phone": phone,
|
48
|
+
# "email": "example@example.com",
|
49
|
+
# "status": "Open"
|
50
|
+
# }).save!
|
51
|
+
|
52
|
+
# # # ticket = zoho_conn.tickets.find({ phone: '1 888 900 9646' })
|
53
|
+
# # # zoho_conn.tickets
|
54
|
+
# # # ticket = zoho_conn.tickets.find({ phone: '1 888 900 9646' })
|
55
|
+
# # # ticket = zoho_conn.tickets.find_or_initialize_by({ productId: '123123', phone: '80681765917' })
|
56
|
+
# puts "\n\n ticket[#{ticket.count}]=[#{ticket.to_json}] \n\n"
|
57
|
+
|
58
|
+
# # # contact = zoho_conn.contacts.find({ phone: '80681765917' })
|
59
|
+
|
60
|
+
|
61
|
+
# # # contact = zoho_conn.contacts.find({ customFields: { custom_id: 123 } })
|
62
|
+
# # # puts "\n\n contact[#{contact.count}]=[#{contact.to_json}] \n\n"
|
63
|
+
|
64
|
+
# task = zoho_conn.tasks.create({
|
65
|
+
# ticketId: ticket.id,
|
66
|
+
# subject: "New Testing Task #{ticket.id}",
|
67
|
+
# # status: "Open",
|
68
|
+
# category: 'Call',
|
69
|
+
# ownerId: zoho_conn.agents.second.id,
|
70
|
+
# creatorId: zoho_conn.agents.second.id,
|
71
|
+
# # ownerId: ticket.assigneeId
|
72
|
+
# status: "In Progress"
|
73
|
+
# })
|
74
|
+
|
75
|
+
# # task = zoho_conn.tasks.by_id("217087000000142001")
|
76
|
+
# # task = zoho_conn.tasks
|
77
|
+
# puts "\n\n task[#{task.count}]=[#{task.to_json}] \n\n"
|
78
|
+
|
79
|
+
# puts "\n\n search client =[#{zoho_conn.tickets.search('eeee').to_json}] \n\n"
|
80
|
+
# puts "\n\n arr1[#{arr1.count}]=[#{arr1.to_json}] \n\n "
|
81
|
+
|
82
|
+
# arr2 = zoho_conn.tickets.all.map { |x| x.id }.sort
|
83
|
+
# puts "\n\n arr1[#{arr2.count}]=[#{arr2.to_json}] \n\n "
|
84
|
+
|
85
|
+
# puts "\n\n ticket1=[#{zoho_conn.tickets.map { |x| x.id }.sort.to_json}] \n\n ticket2=[#{zoho_conn.tickets.all.map { |x| x.id }.sort.to_json}] \n\n"
|
86
|
+
|
87
|
+
# ticket = c.tickets.first.update(subject: 'zzzz Вот ваш первый талон.')
|
88
|
+
# ticket = zoho_conn.tickets.first
|
89
|
+
# comm = ticket.comments
|
90
|
+
|
91
|
+
# ticket = zoho_conn.tickets.new({
|
92
|
+
# "subCategory": "Sub General",
|
93
|
+
# "contactId": zoho_conn.contacts.first.id,
|
94
|
+
# "subject": "100500 started",
|
95
|
+
# "dueDate": (Time.now + 300.days).utc,
|
96
|
+
# "departmentId": zoho_conn.departments.first.id,
|
97
|
+
# "channel": "Email",
|
98
|
+
# "description": "Hai This is Description",
|
99
|
+
# "assigneeId": zoho_conn.agents.first.id,
|
100
|
+
# "phone": "1 888 900 9646",
|
101
|
+
# "email": "example@example.com",
|
102
|
+
# "status": "Open"
|
103
|
+
# }).save!
|
104
|
+
|
105
|
+
|
106
|
+
# puts "\n\n ticketNumber=[#{ticket['ticketNumber']}] ticket=[#{ticket.to_json}] \n\n"
|
107
|
+
# comm = ticket.comments.create({
|
108
|
+
# "isPublic": "true",
|
109
|
+
# "content": "comm 1005002"
|
110
|
+
# })
|
111
|
+
|
112
|
+
# comm = ticket.comments.new({
|
113
|
+
# "isPublic": "true",
|
114
|
+
# "content": "comm 1005003"
|
115
|
+
# }).save!
|
116
|
+
|
117
|
+
# comm = ticket.comments.first
|
118
|
+
# comm.delete!
|
119
|
+
|
120
|
+
# puts "\n\n comm=[#{comm.to_json}] \n\n"
|
121
|
+
|
122
|
+
# ticket.update(description: ticket.description + ' bla-bla-bla ')
|
data/lib/zoho_service.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "zoho_service/version"
|
2
|
+
require "zoho_service/Hash"
|
3
|
+
require "active_support"
|
4
|
+
require "active_support/core_ext"
|
5
|
+
require "zoho_service/base"
|
6
|
+
require "zoho_service/api_connector"
|
7
|
+
require "zoho_service/api_collection"
|
8
|
+
|
9
|
+
module ZohoService
|
10
|
+
def self.name_to_many(model_name)
|
11
|
+
model_name.to_s.pluralize.underscore
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.many_to_name(models_name)
|
15
|
+
models_name.to_s.singularize.camelize
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.init_models_recursion(recursion, tree, parent_class)
|
19
|
+
raise("Too deep recursion in init_models_recursion in ZohoService gem") unless recursion && recursion > 0
|
20
|
+
raise("Need parent class in init_models_recursion in ZohoService gem") unless parent_class
|
21
|
+
parent_name = parent_class.name.demodulize.underscore
|
22
|
+
models = tree.map { |m| m.kind_of?(Array) ? { name: m.first, childs: m.second, params: m.third } : { name: m } }
|
23
|
+
models.each do |model|
|
24
|
+
# puts "\n try init parent_name2=[#{parent_name}] recursion=[#{recursion}] mod=[#{model.to_json}] \n"
|
25
|
+
current_class = nil
|
26
|
+
if const_defined?(model[:name])
|
27
|
+
current_class = const_get(model[:name])
|
28
|
+
else
|
29
|
+
current_class = Class.new(Base)
|
30
|
+
const_set(model[:name], current_class)
|
31
|
+
current_class.model_params = model[:params]
|
32
|
+
current_class.default_parent_name = parent_name
|
33
|
+
end
|
34
|
+
current_class.send(:define_method, parent_name) { |params = {}| get_parent(__method__, params) }
|
35
|
+
parent_class.send(:define_method, ZohoService::name_to_many(model[:name])) do
|
36
|
+
get_childs(__method__.to_sym, current_class)
|
37
|
+
end
|
38
|
+
init_models_recursion(recursion - 1, model[:childs], current_class) if model[:childs]
|
39
|
+
end
|
40
|
+
parent_class.class.send(:define_method, 'childs_list') { models.map { |x| x[:name] }.sort }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
ZohoService::init_models_recursion(5, ([
|
45
|
+
#[model_name, [childs_array], {params}]
|
46
|
+
['Ticket', %w[Comment Thread Attachment TimeEntry], { queries: %w[from limit departmentId sortBy include] }],
|
47
|
+
['Contact', %w[Ticket], { queries: %w[from limit sortBy include] }],
|
48
|
+
['Task', nil, { queries: %w[from limit departmentId sortBy include] }]
|
49
|
+
] + %w[Organization Account Agent Department]), ZohoService::ApiConnector)
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module ZohoService
|
2
|
+
class ApiCollection < Array
|
3
|
+
attr_reader :parent, :request_params, :loaded
|
4
|
+
|
5
|
+
def initialize(parent, attrs = {})
|
6
|
+
@loaded = false
|
7
|
+
@parent = parent
|
8
|
+
@request_params = attrs # request_params writing only in init proc!
|
9
|
+
super()
|
10
|
+
if accepted_queries.include?('departmentId')
|
11
|
+
@request_params[:query] ||= {}
|
12
|
+
@request_params[:query][:departmentId] ||= parent.connector.client_params[:departmentId]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_request(eval_method)
|
17
|
+
return self if @loaded
|
18
|
+
@loaded = true
|
19
|
+
req_query = @request_params[:query] || {}
|
20
|
+
if accepted_queries.include?('limit') && !(req_query[:from] || req_query[:limit] || request_params[:skip_pages])
|
21
|
+
items_per_page = 50
|
22
|
+
(0..100).each do |page|
|
23
|
+
query = req_query.merge(from: 0 + (items_per_page * page), limit: items_per_page)
|
24
|
+
query[:from] += 1 if query[:from] > 0 # WTF bug with from-limit on zoho server!
|
25
|
+
query.merge!(sortBy: 'createdTime') if accepted_queries.include?('sortBy') && !query[:sortBy]
|
26
|
+
arr = new_collection(query: query).run_request(__method__)
|
27
|
+
arr.each { |x| self.push(x) }
|
28
|
+
break unless arr.count == items_per_page
|
29
|
+
end
|
30
|
+
else
|
31
|
+
parent.connector.load_by_api(collection_url, req_query)&.each do |item_data|
|
32
|
+
raise("ERROR in ZohoService gem. item_data=[#{item_data}]") unless item_data.is_a?(Hash)
|
33
|
+
self.push(request_params[:items_class].new(parent, item_data))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def new(item_params)
|
40
|
+
if accepted_queries.include?('departmentId')
|
41
|
+
item_params[:departmentId] ||= parent.connector.client_params[:departmentId]
|
42
|
+
end
|
43
|
+
request_params[:items_class].new(parent, item_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def create(item_params)
|
47
|
+
new(item_params).save!
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_or_initialize_by(params, create_params = {})
|
51
|
+
find(params).first || create(params.deep_merge(create_params))
|
52
|
+
end
|
53
|
+
|
54
|
+
def find(params)
|
55
|
+
# this method not normal! It is temporary! Search method not working normal on the desk.zoho.com.
|
56
|
+
# use "search" method if you want search only in texts of a model.
|
57
|
+
params = params ? params.deep_symbolize : {}
|
58
|
+
select { |x| x.to_h.deep_symbolize.deep_include?(params) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_with_str(searchStr, params = {})
|
62
|
+
search(searchStr).find(params)
|
63
|
+
end
|
64
|
+
|
65
|
+
def by_id(id)
|
66
|
+
request_params[:items_class].new_by_id(parent, id)
|
67
|
+
end
|
68
|
+
|
69
|
+
def search(searchStr) # Search method can search only searchStr in texts of a model :( . it`s not good practice :(.
|
70
|
+
new_collection(query: { searchStr: searchStr, 'module': request_params[:items_class].models_name,
|
71
|
+
sortBy: 'relevance' })
|
72
|
+
end
|
73
|
+
|
74
|
+
def all
|
75
|
+
run_request(__method__)
|
76
|
+
end
|
77
|
+
|
78
|
+
def accepted_queries
|
79
|
+
if request_params[:query] && request_params[:searchStr]
|
80
|
+
['from', 'limit', 'sortBy', 'departmentId']
|
81
|
+
else
|
82
|
+
mod = request_params[:items_class]
|
83
|
+
mod.model_params && mod.model_params[:queries] ? mod.model_params[:queries] : []
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def first(*args, &block)
|
88
|
+
if !@loaded && accepted_queries.include?('limit')
|
89
|
+
return new_collection({ query: { limit: 1 } }).run_request(__method__).first(*args, &block)
|
90
|
+
end
|
91
|
+
run_request(__method__)
|
92
|
+
super(*args, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
def new_collection(more_params)
|
96
|
+
self.class.new(parent, request_params.deep_merge(more_params))
|
97
|
+
end
|
98
|
+
|
99
|
+
def collection_url
|
100
|
+
parent.resource_path + request_params[:items_class].class_path
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
redefine_methods = Array.instance_methods(false) - %i[inspect push] - ApiCollection.instance_methods(false)
|
105
|
+
redefine_methods.sort.each do |method|
|
106
|
+
ApiCollection.send(:define_method, method ) { |*args, &block| run_request(__method__); super(*args, &block) }
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module ZohoService
|
5
|
+
class ApiConnector < Base
|
6
|
+
attr_reader :token, :invalid_token, :client_params, :debug
|
7
|
+
def initialize(token_in = nil, client_params_in = {}, debug_in = false)
|
8
|
+
raise('Need zoho API token in params for ZohoService::ApiConnector.new') unless token_in
|
9
|
+
@token = token_in
|
10
|
+
@debug = debug_in
|
11
|
+
@client_params = client_params_in
|
12
|
+
super()
|
13
|
+
@client_params[:api_url] = 'https://desk.zoho.com/api/v1'.freeze unless @client_params[:api_url]
|
14
|
+
@client_params[:orgId] = organizations.first&.id unless @client_params[:orgId]
|
15
|
+
@client_params[:departmentId] = departments.first&.id unless @client_params[:departmentId]
|
16
|
+
@client_params[:timeout] = @client_params[:timeout] ? @client_params[:timeout].to_i : 5
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_path
|
20
|
+
@client_params[:api_url]
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_headers(params = {})
|
24
|
+
client_headers = { 'Authorization': 'Zoho-authtoken ' + @token }
|
25
|
+
client_headers[:orgId] = @client_params[:orgId].to_s if @client_params[:orgId]
|
26
|
+
self.class.headers.merge(client_headers)
|
27
|
+
end
|
28
|
+
|
29
|
+
def load_by_api(url, query = nil, params = {})
|
30
|
+
url = resource_path + '/search' if query && query[:searchStr]
|
31
|
+
url = URI.encode(url)
|
32
|
+
raise "Invalid CRMCSRFToken. Check your token in ApiConnector in ZohoService gem!\n" if @invalid_token
|
33
|
+
|
34
|
+
request_params = { headers: get_headers(params), timeout: @client_params[:timeout], no_follow: true, limit: 1,
|
35
|
+
follow_redirects: false, read_timeout: @client_params[:timeout] }
|
36
|
+
response = nil
|
37
|
+
begin
|
38
|
+
response = if params[:method] == :post
|
39
|
+
HTTParty.post(url, request_params.merge(body: query.to_json))
|
40
|
+
elsif params[:method] == :patch
|
41
|
+
HTTParty.patch(url, request_params.merge(body: query.to_json))
|
42
|
+
elsif params[:method] == :delete
|
43
|
+
HTTParty.delete(url, request_params)
|
44
|
+
else
|
45
|
+
url = url + '?' + query.to_query if query
|
46
|
+
HTTParty.get(url, request_params)
|
47
|
+
end
|
48
|
+
rescue HTTParty::RedirectionTooDeep => e
|
49
|
+
raise("Can`t Connect to zohoDesk server. RedirectionTooDeep. Check https or maybe your account blocked.\nurl=[#{url}]\nerror=[#{e}]")
|
50
|
+
rescue => e
|
51
|
+
raise("Can`t Connect to zohoDesk server. Unknown error. Maybe your account blocked.\nurl=[#{url}]\nerror=[#{e}]")
|
52
|
+
end
|
53
|
+
if response
|
54
|
+
$stderr.puts "#{params[:method]} url=[#{url}] length=[#{response.to_json.length}] cnt=[#{response['data']&.count}]\n" if @debug
|
55
|
+
if response.code == 200
|
56
|
+
raise "Error message in ZohoService gem: \n[#{ response['message'] }]\n" if response['message']
|
57
|
+
return response['data'] ? response['data'] : response
|
58
|
+
elsif response.code == 204 # 204 - no content found or from-limit out of range
|
59
|
+
return []
|
60
|
+
elsif response.code == 400 # 400 - Invalid CRMCSRFToken
|
61
|
+
invalid_CRMCSRFToken()
|
62
|
+
else
|
63
|
+
invalid_CRMCSRFToken() if response.body&.include?('Invalid CRMCSRFToken')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
bad_response(response, url, query, get_headers(params), params)
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def invalid_CRMCSRFToken
|
71
|
+
@invalid_token = true
|
72
|
+
raise('Invalid CRMCSRFToken. Check your token in ApiConnector in ZohoService gem!')
|
73
|
+
end
|
74
|
+
|
75
|
+
def bad_response(response, url, query, headers, params)
|
76
|
+
error_str = "ZohoService API bad_response url=[#{url}], query=[#{query&.to_json}]\nparams=[#{params.to_json}]\n"
|
77
|
+
error_str += response ? "code=[#{response.code}] body=[#{response.body}]\n" : "Unknown error in load_by_api.\n"
|
78
|
+
raise error_str
|
79
|
+
end
|
80
|
+
|
81
|
+
class << self
|
82
|
+
def headers
|
83
|
+
{ 'User-Agent' => 'ZohoService-Ruby-On-Rails-gem-by-chaky222/' + ZohoService::VERSION,
|
84
|
+
'Accept' => 'application/json',
|
85
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
86
|
+
'Accept-Charset'=> 'UTF-8' }.freeze
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module ZohoService
|
4
|
+
class Base < OpenStruct
|
5
|
+
attr_reader :parents, :item_id, :table, :full_data, :errors, :childs, :saved
|
6
|
+
|
7
|
+
def initialize(parent = nil, data = nil, params = {})
|
8
|
+
@childs = {}
|
9
|
+
@errors = []
|
10
|
+
@parents = parent ? { parent.class.name.demodulize.underscore.to_sym => parent } : {}
|
11
|
+
@item_id = params[:item_id] || ((data && data['id']) ? data['id'] : nil)
|
12
|
+
super(data)
|
13
|
+
@full_data = params[:full_data]
|
14
|
+
end
|
15
|
+
|
16
|
+
def connector
|
17
|
+
parent ? parent.connector : self
|
18
|
+
end
|
19
|
+
|
20
|
+
def parent
|
21
|
+
@parents[self.class.default_parent_name] || @parents.values.first
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_parent(model, params = {})
|
25
|
+
@parents[model.to_sym]
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_childs(child_model, childs_class)
|
29
|
+
@childs[child_model] ||= ApiCollection.new(self, { items_class: childs_class})
|
30
|
+
@childs[child_model]
|
31
|
+
end
|
32
|
+
|
33
|
+
def full
|
34
|
+
load_full unless @full_data
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_full(data = nil)
|
39
|
+
raise('You must save model before take full data in ZohoService gem.') unless @item_id
|
40
|
+
init_data(data || connector.load_by_api(resource_path))
|
41
|
+
@full_data = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def init_data(data)
|
45
|
+
data.each{ |k, v| @table[k.to_sym] = v; new_ostruct_member(k); }
|
46
|
+
@item_id = id if id && !@item_id
|
47
|
+
end
|
48
|
+
|
49
|
+
def update(params)
|
50
|
+
url = @item_id ? resource_path : parent.resource_path + self.class.class_path
|
51
|
+
response = connector.load_by_api(url, params.to_hash, { method: @item_id ? :patch : :post })
|
52
|
+
if response
|
53
|
+
if response.kind_of?(Array)
|
54
|
+
raise("ERROR! create item response is Array[#{response.count}]. Try change http to https in api_url :)!")
|
55
|
+
elsif response['message']
|
56
|
+
@errors << response['message']
|
57
|
+
else
|
58
|
+
init_data(response.to_hash)
|
59
|
+
@full_data = nil
|
60
|
+
end
|
61
|
+
else
|
62
|
+
@errors << "Error while try update[#{@item_id}] url=[#{url}] params=[#{params&.to_json}]"
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete
|
68
|
+
return unless @item_id
|
69
|
+
response = connector.load_by_api(resource_path, nil, { method: :delete })
|
70
|
+
if response && response['message']
|
71
|
+
@errors << response['message']
|
72
|
+
elsif response
|
73
|
+
@item_id = nil
|
74
|
+
@id = nil
|
75
|
+
@full_data = nil
|
76
|
+
else
|
77
|
+
@errors << 'Error while try delete'
|
78
|
+
end
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def delete!
|
83
|
+
delete
|
84
|
+
raise("#{@errors.join("\n")}") if @errors.any?
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def save
|
89
|
+
update(to_hash)
|
90
|
+
@saved = @errors.any?
|
91
|
+
end
|
92
|
+
|
93
|
+
def save!
|
94
|
+
save
|
95
|
+
raise("#{@errors.join("\n")}") if @errors.any?
|
96
|
+
self
|
97
|
+
end
|
98
|
+
|
99
|
+
def resource_path
|
100
|
+
raise('Cant take resource_path for not saved item in ZohoService gem.') unless @item_id
|
101
|
+
parent.resource_path + self.class.class_path(@item_id)
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_hash
|
105
|
+
@table.to_hash(*args, &block)
|
106
|
+
end
|
107
|
+
|
108
|
+
class << self
|
109
|
+
attr_accessor :model_params, :default_parent_name
|
110
|
+
def class_path(id = nil)
|
111
|
+
"/#{models_name}" + (id ? '/'+id : '')
|
112
|
+
end
|
113
|
+
|
114
|
+
def models_name
|
115
|
+
self.name.demodulize.pluralize.underscore
|
116
|
+
end
|
117
|
+
|
118
|
+
def new_by_id(parent, id)
|
119
|
+
raise('Need id in Base::new_by_id of ZohoService gem.') unless id
|
120
|
+
data = parent.connector.load_by_api(parent.resource_path + class_path(id))
|
121
|
+
new(parent, data, { full_data: true })
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
+
SimpleCov::Formatter::HTMLFormatter,
|
6
|
+
Coveralls::SimpleCov::Formatter,
|
7
|
+
]
|
8
|
+
SimpleCov.start do
|
9
|
+
add_filter './.bundle'
|
10
|
+
end
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
13
|
+
require 'zoho_service'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# stub: zoho_service 0.0.1 ruby lib
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'zoho_service/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "zoho_service".freeze
|
9
|
+
s.version = ZohoService::VERSION
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib".freeze]
|
13
|
+
s.authors = ["chaky222".freeze]
|
14
|
+
s.date = "2017-09-13"
|
15
|
+
s.description = "Working with data in Zoho Service Desk by using API.".freeze
|
16
|
+
s.email = ["emersoncostin@gmail.com".freeze]
|
17
|
+
s.executables = ["zoho_service".freeze]
|
18
|
+
s.files = [ "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "bin/zoho_service".freeze, "lib/zoho_service.rb".freeze, "lib/zoho_service/Hash.rb".freeze, "lib/zoho_service/base.rb".freeze, "lib/zoho_service/api_connector.rb".freeze, "lib/zoho_service/api_collection.rb".freeze, "lib/zoho_service/version.rb".freeze, "spec/spec_helper.rb".freeze, "spec/zoho_service_spec.rb".freeze, "zoho_service.gemspec".freeze]
|
19
|
+
s.homepage = "".freeze
|
20
|
+
s.licenses = ["MIT".freeze]
|
21
|
+
s.rubygems_version = "2.5.2".freeze
|
22
|
+
s.summary = "Zoho Service Desk gem".freeze
|
23
|
+
s.test_files = ["spec/spec_helper.rb".freeze, "spec/zoho_service_spec.rb".freeze]
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
s.specification_version = 4
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
29
|
+
s.add_runtime_dependency(%q<httparty>.freeze, ["> 0.16"])
|
30
|
+
s.add_runtime_dependency(%q<activesupport>.freeze, ["> 4.2.7.1"])
|
31
|
+
s.add_development_dependency(%q<bundler>.freeze, ["~> 1.5"])
|
32
|
+
s.add_development_dependency(%q<rake>.freeze, ["< 11.0"])
|
33
|
+
s.add_development_dependency(%q<rspec>.freeze, ["~> 2.14.1"])
|
34
|
+
s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.7.1"])
|
35
|
+
s.add_development_dependency(%q<coveralls>.freeze, ["~> 0.7.0"])
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<httparty>.freeze, ["> 0.16"])
|
38
|
+
s.add_dependency(%q<activesupport>.freeze, ["> 4.2.7.1"])
|
39
|
+
s.add_dependency(%q<bundler>.freeze, ["~> 1.5"])
|
40
|
+
s.add_dependency(%q<rake>.freeze, ["< 11.0"])
|
41
|
+
s.add_dependency(%q<rspec>.freeze, ["~> 2.14.1"])
|
42
|
+
s.add_dependency(%q<simplecov>.freeze, ["~> 0.7.1"])
|
43
|
+
s.add_dependency(%q<coveralls>.freeze, ["~> 0.7.0"])
|
44
|
+
end
|
45
|
+
else
|
46
|
+
s.add_dependency(%q<httparty>.freeze, ["> 0.16.2"])
|
47
|
+
s.add_dependency(%q<activesupport>.freeze, ["> 4.2.7.1"])
|
48
|
+
s.add_dependency(%q<bundler>.freeze, ["~> 1.5"])
|
49
|
+
s.add_dependency(%q<rake>.freeze, ["< 11.0"])
|
50
|
+
s.add_dependency(%q<rspec>.freeze, ["~> 2.14.1"])
|
51
|
+
s.add_dependency(%q<simplecov>.freeze, ["~> 0.7.1"])
|
52
|
+
s.add_dependency(%q<coveralls>.freeze, ["~> 0.7.0"])
|
53
|
+
end
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zoho_service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- chaky222
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.16'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.2.7.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.2.7.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "<"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '11.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "<"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '11.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.14.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.14.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.7.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.7.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.7.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.7.0
|
111
|
+
description: Working with data in Zoho Service Desk by using API.
|
112
|
+
email:
|
113
|
+
- emersoncostin@gmail.com
|
114
|
+
executables:
|
115
|
+
- zoho_service
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- bin/zoho_service
|
124
|
+
- lib/zoho_service.rb
|
125
|
+
- lib/zoho_service/Hash.rb
|
126
|
+
- lib/zoho_service/api_collection.rb
|
127
|
+
- lib/zoho_service/api_connector.rb
|
128
|
+
- lib/zoho_service/base.rb
|
129
|
+
- lib/zoho_service/version.rb
|
130
|
+
- spec/spec_helper.rb
|
131
|
+
- spec/zoho_service_spec.rb
|
132
|
+
- zoho_service.gemspec
|
133
|
+
homepage: ''
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
metadata: {}
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 2.7.6.2
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: Zoho Service Desk gem
|
157
|
+
test_files:
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
- spec/zoho_service_spec.rb
|