KayakoClient 0.0.1b

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.
Files changed (39) hide show
  1. data/lib/kayako_client.rb +36 -0
  2. data/lib/kayako_client/base.rb +98 -0
  3. data/lib/kayako_client/department.rb +31 -0
  4. data/lib/kayako_client/http/http.rb +217 -0
  5. data/lib/kayako_client/http/http_backend.rb +31 -0
  6. data/lib/kayako_client/http/http_client.rb +87 -0
  7. data/lib/kayako_client/http/http_response.rb +61 -0
  8. data/lib/kayako_client/http/net_http.rb +109 -0
  9. data/lib/kayako_client/mixins/api.rb +299 -0
  10. data/lib/kayako_client/mixins/attachment.rb +69 -0
  11. data/lib/kayako_client/mixins/authentication.rb +34 -0
  12. data/lib/kayako_client/mixins/client.rb +308 -0
  13. data/lib/kayako_client/mixins/logger.rb +29 -0
  14. data/lib/kayako_client/mixins/object.rb +456 -0
  15. data/lib/kayako_client/mixins/post_client.rb +42 -0
  16. data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
  17. data/lib/kayako_client/mixins/ticket_api.rb +55 -0
  18. data/lib/kayako_client/mixins/ticket_client.rb +135 -0
  19. data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
  20. data/lib/kayako_client/staff.rb +25 -0
  21. data/lib/kayako_client/staff_group.rb +9 -0
  22. data/lib/kayako_client/ticket.rb +241 -0
  23. data/lib/kayako_client/ticket_attachment.rb +42 -0
  24. data/lib/kayako_client/ticket_count.rb +135 -0
  25. data/lib/kayako_client/ticket_custom_field.rb +110 -0
  26. data/lib/kayako_client/ticket_note.rb +105 -0
  27. data/lib/kayako_client/ticket_post.rb +61 -0
  28. data/lib/kayako_client/ticket_priority.rb +24 -0
  29. data/lib/kayako_client/ticket_status.rb +31 -0
  30. data/lib/kayako_client/ticket_time_track.rb +27 -0
  31. data/lib/kayako_client/ticket_type.rb +26 -0
  32. data/lib/kayako_client/user.rb +61 -0
  33. data/lib/kayako_client/user_group.rb +12 -0
  34. data/lib/kayako_client/user_organization.rb +23 -0
  35. data/lib/kayako_client/xml/lib_xml.rb +86 -0
  36. data/lib/kayako_client/xml/rexml_document.rb +77 -0
  37. data/lib/kayako_client/xml/xml.rb +63 -0
  38. data/lib/kayako_client/xml/xml_backend.rb +42 -0
  39. metadata +105 -0
@@ -0,0 +1,42 @@
1
+ module KayakoClient
2
+ module PostClient
3
+
4
+ def attachments(options = {})
5
+ values = []
6
+ if ticket_id && id
7
+ items = KayakoClient::TicketAttachment.all(ticket_id, options.merge(inherited_options))
8
+ items.each do |item|
9
+ values << item if item.ticket_post_id == id
10
+ end
11
+ end
12
+ values
13
+ end
14
+
15
+ def get_attachment(attachment, options = {})
16
+ KayakoClient::TicketAttachment.get(ticket_id, attachment, options.merge(inherited_options)) if ticket_id
17
+ end
18
+
19
+ alias_method :find_attachment, :get_attachment
20
+
21
+ def post_attachment(options = {})
22
+ if ticket_id && id
23
+ if logger
24
+ logger.warn "overwriting :ticket_id" if options[:ticket_id] && options[:ticket_id].to_i != ticket_id
25
+ logger.warn "overwriting :ticket_post_id" if options[:ticket_post_id] && options[:ticket_post_id].to_i != id
26
+ end
27
+ options[:ticket_id] = ticket_id
28
+ options[:ticket_post_id] = id
29
+ KayakoClient::TicketAttachment.post(options.merge(inherited_options))
30
+ end
31
+ end
32
+
33
+ alias_method :create_attachment, :post_attachment
34
+
35
+ def delete_attachment(attachment, options = {})
36
+ KayakoClient::TicketAttachment.delete(ticket_id, attachment, options.merge(inherited_options)) if ticket_id
37
+ end
38
+
39
+ alias_method :destroy_attachment, :delete_attachment
40
+
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module KayakoClient
2
+ module StaffVisibilityAPI
3
+
4
+ def visible_to_staff_group?(group)
5
+ !staff_visibility_custom || (!staff_group_ids.nil? && staff_group_ids.include?(group.to_i))
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,55 @@
1
+ module KayakoClient
2
+ module TicketAPI
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def delete_request(options = {})
9
+ raise RuntimeError, "undefined ticket ID" unless ticket_id
10
+ raise RuntimeError, "undefined ID" unless id
11
+ super(options.merge(:e => "#{self.class.path}/#{ticket_id}/#{id}"))
12
+ end
13
+
14
+ module ClassMethods
15
+
16
+ def all(ticket, options = {})
17
+ unless ticket.to_i > 0
18
+ logger.error "invalid :ticket_id - #{ticket}" if logger
19
+ raise ArgumentError, "invalid ticket ID"
20
+ end
21
+ super(options.merge(:e => "#{path}/ListAll/#{ticket.to_i}"))
22
+ end
23
+
24
+ def get(ticket, id, options = {})
25
+ unless ticket.to_i > 0
26
+ logger.error "invalid :ticket_id - #{ticket}" if logger
27
+ raise ArgumentError, "invalid ticket ID"
28
+ end
29
+ if id == :all
30
+ all(ticket, options)
31
+ else
32
+ unless id.to_i > 0
33
+ logger.error "invalid :id - #{id}" if logger
34
+ raise ArgumentError, "invalid ID"
35
+ end
36
+ super(id, options.merge(:e => "#{path}/#{ticket.to_i}/#{id.to_i}"))
37
+ end
38
+ end
39
+
40
+ def delete(ticket, id, options = {})
41
+ unless ticket.to_i > 0
42
+ logger.error "invalid :ticket_id - #{ticket}" if logger
43
+ raise ArgumentError, "invalid ticket ID"
44
+ end
45
+ unless id.to_i > 0
46
+ logger.error "invalid :id - #{id}" if logger
47
+ raise ArgumentError, "invalid ID"
48
+ end
49
+ super(id, options.merge(:e => "#{path}/#{ticket.to_i}/#{id.to_i}"))
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,135 @@
1
+ module KayakoClient
2
+ module TicketClient
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+
9
+ def attachments(options = {})
10
+ KayakoClient::TicketAttachment.all(id, options.merge(inherited_options)) if id
11
+ end
12
+
13
+ def get_attachment(attachment, options = {})
14
+ KayakoClient::TicketAttachment.get(id, attachment, options.merge(inherited_options)) if id
15
+ end
16
+
17
+ alias_method :find_attachment, :get_attachment
18
+
19
+ def post_attachment(options = {})
20
+ if id
21
+ if logger && options[:ticket_id] && options[:ticket_id].to_i != id
22
+ logger.warn "overwriting :ticket_id"
23
+ end
24
+ options[:ticket_id] = id
25
+ KayakoClient::TicketAttachment.post(options.merge(inherited_options))
26
+ end
27
+ end
28
+
29
+ alias_method :create_attachment, :post_attachment
30
+
31
+ def delete_attachment(attachment, options = {})
32
+ KayakoClient::TicketAttachment.delete(id, attachment, options.merge(inherited_options)) if id
33
+ end
34
+
35
+ alias_method :destroy_attachment, :delete_attachment
36
+
37
+
38
+ def custom_fields(options = {})
39
+ KayakoClient::TicketCustomField.get(id, options.merge(inherited_options)) if id
40
+ end
41
+
42
+
43
+ def notes(options = {})
44
+ KayakoClient::TicketNote.all(id, options.merge(inherited_options)) if id
45
+ end
46
+
47
+ def get_note(note, options = {})
48
+ KayakoClient::TicketNote.get(id, note, options.merge(inherited_options)) if id
49
+ end
50
+
51
+ alias_method :find_note, :get_note
52
+
53
+ def post_note(options = {})
54
+ if id
55
+ if logger && options[:ticket_id] && options[:ticket_id].to_i != id
56
+ logger.warn "overwriting :ticket_id"
57
+ end
58
+ options[:ticket_id] = id
59
+ KayakoClient::TicketNote.post(options.merge(inherited_options))
60
+ end
61
+ end
62
+
63
+ alias_method :create_note, :post_note
64
+
65
+ def delete_note(note, options = {})
66
+ KayakoClient::TicketNote.delete(id, note, options.merge(inherited_options)) if id
67
+ end
68
+
69
+ alias_method :destroy_note, :delete_note
70
+
71
+
72
+ def get_post(post, options = {})
73
+ KayakoClient::TicketPost.get(id, post, options.merge(inherited_options)) if id
74
+ end
75
+
76
+ alias_method :find_post, :get_post
77
+
78
+ def post_post(options = {})
79
+ if id
80
+ if logger && options[:ticket_id] && options[:ticket_id].to_i != id
81
+ logger.warn "overwriting :ticket_id"
82
+ end
83
+ options[:ticket_id] = id
84
+ KayakoClient::TicketPost.post(options.merge(inherited_options))
85
+ end
86
+ end
87
+
88
+ alias_method :create_post, :post_post
89
+
90
+ def delete_post(post, options = {})
91
+ KayakoClient::TicketPost.delete(id, post, options.merge(inherited_options)) if id
92
+ end
93
+
94
+ alias_method :destroy_post, :delete_post
95
+
96
+
97
+ def time_tracks(options = {})
98
+ KayakoClient::TicketTimeTrack.all(id, options.merge(inherited_options)) if id
99
+ end
100
+
101
+ def get_time_track(track, options = {})
102
+ KayakoClient::TicketTimeTrack.get(id, track, options.merge(inherited_options)) if id
103
+ end
104
+
105
+ alias_method :find_time_track, :get_time_track
106
+
107
+ def post_time_track(options = {})
108
+ if id
109
+ if logger && options[:ticket_id] && options[:ticket_id].to_i != id
110
+ logger.warn "overwriting :ticket_id"
111
+ end
112
+ options[:ticket_id] = id
113
+ KayakoClient::TicketTimeTrack.post(options.merge(inherited_options))
114
+ end
115
+ end
116
+
117
+ alias_method :create_time_track, :post_time_track
118
+
119
+ def delete_time_track(track, options = {})
120
+ KayakoClient::TicketTimeTrack.delete(id, track, options.merge(inherited_options)) if id
121
+ end
122
+
123
+ alias_method :destroy_time_track, :delete_time_track
124
+
125
+
126
+ module ClassMethods
127
+
128
+ def count(options = {})
129
+ KayakoClient::TicketCount.get(options.merge(inherited_options(options)))
130
+ end
131
+
132
+ end
133
+
134
+ end
135
+ end
@@ -0,0 +1,9 @@
1
+ module KayakoClient
2
+ module UserVisibilityAPI
3
+
4
+ def visible_to_user_group?(group)
5
+ !user_visibility_custom || (!user_group_ids.nil? && user_group_ids.include?(group.to_i))
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ require 'kayako_client/staff_group'
2
+
3
+ module KayakoClient
4
+ class Staff < KayakoClient::Base
5
+
6
+ property :id, :integer, :readonly => true
7
+ property :staff_group_id, :integer, :required => [ :put, :post ]
8
+ property :user_name, :string, :required => [ :put, :post ]
9
+ property :password, :string, :required => :post
10
+ property :first_name, :string, :required => [ :put, :post ]
11
+ property :last_name, :string, :required => [ :put, :post ]
12
+ property :full_name, :string, :readonly => true
13
+ property :email, :string, :required => [ :put, :post ]
14
+ property :designation, :string
15
+ property :signature, :string
16
+ property :greeting, :string
17
+ property :mobile_number, :string
18
+ property :is_enabled, :boolean
19
+ property :time_zone, :string
20
+ property :enable_dst, :boolean
21
+
22
+ associate :staff_group, :staff_group_id, StaffGroup
23
+
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module KayakoClient
2
+ class StaffGroup < KayakoClient::Base
3
+
4
+ property :id, :integer, :readonly => true
5
+ property :title, :string, :required => [ :put, :post ]
6
+ property :is_admin, :boolean, :required => :post
7
+
8
+ end
9
+ end
@@ -0,0 +1,241 @@
1
+ require 'kayako_client/department'
2
+
3
+ require 'kayako_client/staff'
4
+
5
+ require 'kayako_client/ticket_note'
6
+ require 'kayako_client/ticket_post'
7
+ require 'kayako_client/ticket_status'
8
+ require 'kayako_client/ticket_priority'
9
+ require 'kayako_client/ticket_type'
10
+
11
+ require 'kayako_client/user'
12
+ require 'kayako_client/user_organization'
13
+
14
+ module KayakoClient
15
+
16
+ class TicketWorkflow < KayakoClient::Tickets
17
+ embedded
18
+
19
+ property :id, :integer
20
+ property :title, :string
21
+
22
+ end
23
+
24
+ class TicketWatcher < KayakoClient::Tickets
25
+ embedded
26
+
27
+ property :staff_id, :integer
28
+ property :name, :string
29
+
30
+ associate :staff, :staff_id, Staff
31
+ end
32
+
33
+ class Ticket < KayakoClient::Tickets
34
+ include KayakoClient::TicketClient
35
+
36
+ # NOTE: department is required to be of :tickets type
37
+
38
+ FLAG_NONE = 0
39
+ FLAG_PURPLE = 1
40
+ FLAG_ORANGE = 2
41
+ FLAG_GREEN = 3
42
+ FLAG_YELLOW = 4
43
+ FLAG_RED = 5
44
+ FLAG_BLUE = 6
45
+
46
+ SEARCH_TICKET_ID = 0x0001
47
+ SEARCH_CONTENTS = 0x0002
48
+ SEARCH_AUTHOR = 0x0004
49
+ SEARCH_EMAIL = 0x0008
50
+ SEARCH_CREATOR_EMAIL = 0x0010
51
+ SEARCH_FULL_NAME = 0x0020
52
+ SEARCH_NOTES = 0x0040
53
+ SEARCH_USER_GROUP = 0x0080
54
+ SEARCH_USER_ORGANIZATION = 0x0100
55
+ SEARCH_USER = 0x0200
56
+ SEARCH_TAGS = 0x0400
57
+
58
+ TICKET_TYPES = [ :default, :phone ].freeze
59
+
60
+ property :id, :integer, :readonly => true
61
+ property :flag_type, :integer, :readonly => true, :range => 0..6
62
+ property :display_id, :string, :readonly => true
63
+ property :department_id, :integer, :required => :post
64
+ property :status_id, :integer, :required => :post, :set => :ticketstatusid
65
+ property :priority_id, :integer, :required => :post, :set => :ticketpriorityid
66
+ property :type_id, :integer, :required => :post, :set => :tickettypeid
67
+ property :user_id, :integer
68
+ property :user_organization, :string, :readonly => true
69
+ property :user_organization_id, :integer, :readonly => true
70
+ property :owner_staff_id, :integer
71
+ property :owner_staff_name, :string, :readonly => true
72
+ property :full_name, :string, :required => :post
73
+ property :email, :string, :required => :post
74
+ property :last_replier, :string, :readonly => true
75
+ property :subject, :string, :required => :post
76
+ property :creation_time, :date, :readonly => true
77
+ property :last_activity, :date, :readonly => true
78
+ property :last_staff_reply, :date, :readonly => true
79
+ property :last_user_reply, :date, :readonly => true
80
+ property :sla_plan_id, :integer, :readonly => true
81
+ property :next_reply_due, :date, :readonly => true
82
+ property :resolution_due, :date, :readonly => true
83
+ property :replies, :integer, :readonly => true
84
+ property :ip_address, :string, :readonly => true
85
+ property :creator, :integer, :readonly => true
86
+ property :creation_mode, :integer, :readonly => true
87
+ property :creation_type, :integer, :readonly => true
88
+ property :is_escalated, :boolean, :readonly => true
89
+ property :escalation_rule_id, :integer, :readonly => true
90
+ property :tags, :string, :readonly => true
91
+ property :contents, :string, :new => true, :required => :post
92
+ property :auto_user_id, :boolean, :new => true
93
+ property :staff_id, :integer, :new => true
94
+ property :type, :symbol, :new => true, :in => TICKET_TYPES
95
+
96
+ property :work_flow, :object, :class => TicketWorkflow
97
+ property :watcher, [ :object ], :class => TicketWatcher
98
+ property :note, [ :object ], :class => TicketNote
99
+ property :posts, [ :object ], :class => TicketPost
100
+
101
+ associate :department, :department_id, Department
102
+ associate :ticket_status, :status_id, TicketStatus
103
+ associate :ticket_priority, :priority_id, TicketPriority
104
+ associate :ticket_type, :type_id, TicketType
105
+ associate :user, :user_id, User
106
+ associate :organization, :user_organization_id, UserOrganization
107
+ associate :owner_staff, :owner_staff_id, Staff
108
+
109
+ def posts
110
+ if instance_variable_defined?(:@posts)
111
+ instance_variable_get(:@posts)
112
+ elsif !new? && id && id > 0
113
+ logger.debug "posts are missing - trying to load" if logger
114
+ post = KayakoClient::TicketPost.all(id, inherited_options)
115
+ if post && !post.empty?
116
+ instance_variable_set(:@posts, post)
117
+ else
118
+ instance_variable_set(:@posts, nil)
119
+ end
120
+ else
121
+ nil
122
+ end
123
+ end
124
+
125
+ def created_by_user?
126
+ !user_id.nil? && user_id > 0
127
+ end
128
+
129
+ alias_method :has_user?, :created_by_user?
130
+
131
+ def has_user_organization?
132
+ !user_organization_id.nil? && user_organization_id > 0
133
+ end
134
+
135
+ def has_owner_staff?
136
+ !owner_staff_id.nil? && owner_staff_id > 0
137
+ end
138
+
139
+ def self.all(*args)
140
+ options = args.last.is_a?(Hash) ? args.pop : {}
141
+
142
+ components = []
143
+ args.each_index do |index|
144
+ break if index > 3
145
+ if args[index]
146
+ components[index] ||= []
147
+ components[index] << args[index]
148
+ end
149
+ end
150
+
151
+ options.keys.each do |option|
152
+ case option.to_s.gsub(%r{_}, '')
153
+ when 'departmentid', 'department'
154
+ index = 0
155
+ when 'ticketstatusid', 'ticketstatus'
156
+ index = 1
157
+ when 'ownerstaffid', 'ownerstaff'
158
+ index = 2
159
+ when 'userid', 'user'
160
+ index = 3
161
+ else
162
+ next
163
+ end
164
+ components[index] ||= []
165
+ components[index] << options.delete(option)
166
+ end
167
+
168
+ raise ArgumentError, "missing :department_id" unless components[0]
169
+
170
+ e = path + '/ListAll' + components.inject('') do |uri, item|
171
+ uri << '/' + (item.nil? ? '-1' : item.flatten.uniq.join(','))
172
+ end
173
+
174
+ super(options.merge(:e => e))
175
+ end
176
+
177
+ def self.get(id = :all, options = {})
178
+ if id == :all
179
+ all(options.delete(:id), options)
180
+ else
181
+ super(options.merge(:id => id))
182
+ end
183
+ end
184
+
185
+ def self.search(query, flags = SEARCH_CONTENTS, options = {})
186
+ unless configured? || (options[:api_url] && options[:api_key] && options[:secret_key])
187
+ raise RuntimeError, "client not configured"
188
+ end
189
+
190
+ params = {
191
+ :e => '/Tickets/TicketSearch',
192
+ :query => query
193
+ }
194
+
195
+ params[:ticketid] = 1 unless flags & SEARCH_TICKET_ID == 0x0000
196
+ params[:contents] = 1 unless flags & SEARCH_CONTENTS == 0x0000
197
+ params[:author] = 1 unless flags & SEARCH_AUTHOR == 0x0000
198
+ params[:email] = 1 unless flags & SEARCH_EMAIL == 0x0000
199
+ params[:creatoremail] = 1 unless flags & SEARCH_CREATOR_EMAIL == 0x0000
200
+ params[:fullname] = 1 unless flags & SEARCH_FULL_NAME == 0x0000
201
+ params[:notes] = 1 unless flags & SEARCH_NOTES == 0x0000
202
+ params[:usergroup] = 1 unless flags & SEARCH_USER_GROUP == 0x0000
203
+ params[:userorganization] = 1 unless flags & SEARCH_USER_ORGANIZATION == 0x0000
204
+ params[:user] = 1 unless flags & SEARCH_USER == 0x0000
205
+ params[:tags] = 1 unless flags & SEARCH_TAGS == 0x0000
206
+
207
+ response = post_request(options.merge(params))
208
+ log = options[:logger] || logger
209
+ if response.is_a?(KayakoClient::HTTPOK)
210
+ objects = []
211
+ if log
212
+ log.debug "Response:"
213
+ log.debug response.body
214
+ end
215
+ payload = xml_backend.new(response.body, { :logger => log })
216
+ payload.each do |element|
217
+ object = new(payload.to_hash(element).merge(inherited_options(options)))
218
+ object.loaded!
219
+ objects << object
220
+ end
221
+ log.info ":post(:search, '#{params[:query]}', #{sprintf("0x%04X", flags)}) successful (#{objects.size} objects)" if log
222
+ objects
223
+ else
224
+ log.error "Response: #{response.status} #{response.body}" if log
225
+ raise StandardError, "server returned #{response.status}: #{response.body}"
226
+ end
227
+ end
228
+
229
+ private
230
+
231
+ def validate(method, params)
232
+ if method == :post
233
+ unless params[:auto_user_id] || params[:user_id] || params[:staff_id]
234
+ raise ArgumentError, ":auto_user_id, :user_id or :staff_id is required"
235
+ end
236
+ end
237
+ end
238
+
239
+ end
240
+
241
+ end