KayakoClient 0.0.1b
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/kayako_client.rb +36 -0
- data/lib/kayako_client/base.rb +98 -0
- data/lib/kayako_client/department.rb +31 -0
- data/lib/kayako_client/http/http.rb +217 -0
- data/lib/kayako_client/http/http_backend.rb +31 -0
- data/lib/kayako_client/http/http_client.rb +87 -0
- data/lib/kayako_client/http/http_response.rb +61 -0
- data/lib/kayako_client/http/net_http.rb +109 -0
- data/lib/kayako_client/mixins/api.rb +299 -0
- data/lib/kayako_client/mixins/attachment.rb +69 -0
- data/lib/kayako_client/mixins/authentication.rb +34 -0
- data/lib/kayako_client/mixins/client.rb +308 -0
- data/lib/kayako_client/mixins/logger.rb +29 -0
- data/lib/kayako_client/mixins/object.rb +456 -0
- data/lib/kayako_client/mixins/post_client.rb +42 -0
- data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
- data/lib/kayako_client/mixins/ticket_api.rb +55 -0
- data/lib/kayako_client/mixins/ticket_client.rb +135 -0
- data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
- data/lib/kayako_client/staff.rb +25 -0
- data/lib/kayako_client/staff_group.rb +9 -0
- data/lib/kayako_client/ticket.rb +241 -0
- data/lib/kayako_client/ticket_attachment.rb +42 -0
- data/lib/kayako_client/ticket_count.rb +135 -0
- data/lib/kayako_client/ticket_custom_field.rb +110 -0
- data/lib/kayako_client/ticket_note.rb +105 -0
- data/lib/kayako_client/ticket_post.rb +61 -0
- data/lib/kayako_client/ticket_priority.rb +24 -0
- data/lib/kayako_client/ticket_status.rb +31 -0
- data/lib/kayako_client/ticket_time_track.rb +27 -0
- data/lib/kayako_client/ticket_type.rb +26 -0
- data/lib/kayako_client/user.rb +61 -0
- data/lib/kayako_client/user_group.rb +12 -0
- data/lib/kayako_client/user_organization.rb +23 -0
- data/lib/kayako_client/xml/lib_xml.rb +86 -0
- data/lib/kayako_client/xml/rexml_document.rb +77 -0
- data/lib/kayako_client/xml/xml.rb +63 -0
- data/lib/kayako_client/xml/xml_backend.rb +42 -0
- metadata +105 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'kayako_client/mixins/ticket_api'
|
2
|
+
require 'kayako_client/mixins/attachment'
|
3
|
+
|
4
|
+
require 'kayako_client/ticket'
|
5
|
+
require 'kayako_client/ticket_post'
|
6
|
+
|
7
|
+
module KayakoClient
|
8
|
+
class TicketAttachment < KayakoClient::Tickets
|
9
|
+
include KayakoClient::TicketAPI
|
10
|
+
include KayakoClient::Attachment
|
11
|
+
|
12
|
+
supports :all, :get, :post, :delete
|
13
|
+
|
14
|
+
property :id, :integer, :readonly => true
|
15
|
+
property :ticket_id, :integer, :required => :post
|
16
|
+
property :ticket_post_id, :integer, :required => :post
|
17
|
+
property :file_name, :string, :required => :post
|
18
|
+
property :file_size, :integer, :readonly => true
|
19
|
+
property :file_type, :string, :readonly => true
|
20
|
+
property :date_line, :date, :readonly => true
|
21
|
+
property :contents, :binary, :required => :post, :new => true
|
22
|
+
|
23
|
+
associate :ticket, :ticket_id, Ticket
|
24
|
+
associate :ticket_post, :ticket_post_id, TicketPost
|
25
|
+
|
26
|
+
def contents
|
27
|
+
if instance_variable_defined?(:@contents)
|
28
|
+
instance_variable_get(:@contents)
|
29
|
+
elsif !new? && id && ticket_id && id > 0 && ticket_id > 0
|
30
|
+
logger.debug "contents are missing - trying to reload" if logger
|
31
|
+
if reload!(:e => "#{self.class.path}/#{ticket_id.to_i}/#{id.to_i}") && instance_variable_defined?(:@contents)
|
32
|
+
instance_variable_get(:@contents)
|
33
|
+
else
|
34
|
+
instance_variable_set(:@contents, nil)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'kayako_client/ticket_status'
|
2
|
+
require 'kayako_client/ticket_type'
|
3
|
+
require 'kayako_client/staff'
|
4
|
+
require 'kayako_client/department'
|
5
|
+
|
6
|
+
module KayakoClient
|
7
|
+
|
8
|
+
class TicketCountStatus < KayakoClient::Tickets
|
9
|
+
embedded
|
10
|
+
|
11
|
+
property :id, :integer
|
12
|
+
property :last_activity, :date
|
13
|
+
property :total_items, :integer
|
14
|
+
|
15
|
+
associate :ticket_status, :id, TicketStatus
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class TicketCountType < KayakoClient::Tickets
|
20
|
+
embedded
|
21
|
+
|
22
|
+
property :id, :integer
|
23
|
+
property :last_activity, :date
|
24
|
+
property :total_items, :integer
|
25
|
+
property :total_unresolved_items, :integer
|
26
|
+
|
27
|
+
associate :ticket_type, :id, TicketType
|
28
|
+
|
29
|
+
def has_ticket_type?
|
30
|
+
!id.nil? && id > 0
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class TicketCountOwner < KayakoClient::Tickets
|
36
|
+
embedded
|
37
|
+
|
38
|
+
property :id, :integer
|
39
|
+
property :last_activity, :date
|
40
|
+
property :total_items, :integer
|
41
|
+
property :total_unresolved_items, :integer
|
42
|
+
|
43
|
+
associate :owner_staff, :id, Staff
|
44
|
+
|
45
|
+
def has_owner_staff?
|
46
|
+
!id.nil? && id > 0
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class TicketCountDepartment < KayakoClient::Tickets
|
52
|
+
embedded
|
53
|
+
|
54
|
+
property :id, :integer
|
55
|
+
property :total_items, :integer
|
56
|
+
property :last_activity, :date
|
57
|
+
property :total_unresolved_items, :integer
|
58
|
+
property :statuses, [ :object ], :class => TicketCountStatus, :get => :ticketstatus
|
59
|
+
property :types, [ :object ], :class => TicketCountType, :get => :tickettype
|
60
|
+
property :owners, [ :object ], :class => TicketCountOwner, :get => :ownerstaff
|
61
|
+
|
62
|
+
associate :department, :id, Department
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class TicketCountUnassigned < KayakoClient::Tickets
|
67
|
+
embedded
|
68
|
+
|
69
|
+
property :id, :integer
|
70
|
+
property :last_activity, :date
|
71
|
+
property :total_items, :integer
|
72
|
+
property :total_unresolved_items, :integer
|
73
|
+
|
74
|
+
# NOTE: :id is not a department id
|
75
|
+
#associate :department, :id, Department
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
class TicketCount < KayakoClient::Tickets
|
80
|
+
supports :get
|
81
|
+
|
82
|
+
property :departments, [ :object ], :class => TicketCountDepartment
|
83
|
+
property :statuses, [ :object ], :class => TicketCountStatus
|
84
|
+
property :owners, [ :object ], :class => TicketCountOwner
|
85
|
+
property :unassigned, [ :object ], :class => TicketCountUnassigned
|
86
|
+
|
87
|
+
def initialize(*args)
|
88
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
89
|
+
super(*args)
|
90
|
+
if !caller[1].match(%r{/ticket_count\.rb:[0-9]+:in `[^']+'}) &&
|
91
|
+
!options[:departments] && !options[:statuses] && !options[:owners] && !options[:unassigned]
|
92
|
+
raise RuntimeError, "client not configured" unless configured?
|
93
|
+
response = self.class.get_request(options.merge(inherited_options))
|
94
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
95
|
+
if logger
|
96
|
+
logger.debug "Response:"
|
97
|
+
logger.debug response.body
|
98
|
+
end
|
99
|
+
payload = xml_backend.new(response.body, { :logger => logger })
|
100
|
+
clean
|
101
|
+
import(payload.to_hash)
|
102
|
+
loaded!
|
103
|
+
logger.info ":get) successful" if logger
|
104
|
+
else
|
105
|
+
logger.error "Response: #{response.status} #{response.body}" if logger
|
106
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.get(options = {})
|
112
|
+
unless configured? || (options[:api_url] && options[:api_key] && options[:secret_key])
|
113
|
+
raise RuntimeError, "client not configured"
|
114
|
+
end
|
115
|
+
log = options[:logger] || logger
|
116
|
+
response = get_request(options)
|
117
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
118
|
+
if log
|
119
|
+
log.debug "Response:"
|
120
|
+
log.debug response.body
|
121
|
+
end
|
122
|
+
payload = xml_backend.new(response.body, { :logger => log })
|
123
|
+
object = new(payload.to_hash.merge(inherited_options(options)))
|
124
|
+
object.loaded!
|
125
|
+
log.info ":get successful" if log
|
126
|
+
object
|
127
|
+
else
|
128
|
+
log.error "Response: #{response.status} #{response.body}" if log
|
129
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module KayakoClient
|
5
|
+
|
6
|
+
class TicketCustomFieldValue < KayakoClient::Tickets
|
7
|
+
embedded
|
8
|
+
|
9
|
+
property :id, :integer
|
10
|
+
property :type, :integer, :range => 1..11
|
11
|
+
property :title, :string
|
12
|
+
property :file_name, :string
|
13
|
+
property :contents, :string
|
14
|
+
|
15
|
+
def initialize(*args)
|
16
|
+
super(*args)
|
17
|
+
if defined?(@type)
|
18
|
+
if @type == KayakoClient::TicketCustomField::TYPE_FILE
|
19
|
+
self.class.send(:include, KayakoClient::Attachment)
|
20
|
+
if defined?(@contents)
|
21
|
+
logger.debug "decoding base64 :contents" if logger
|
22
|
+
@contents = Base64.decode64(@contents)
|
23
|
+
@contents = Base64.decode64(@contents)
|
24
|
+
end
|
25
|
+
elsif @type == KayakoClient::TicketCustomField::TYPE_DATE
|
26
|
+
@contents = Time.parse(@contents) if defined?(@contents)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class TicketCustomFieldGroup < KayakoClient::Tickets
|
34
|
+
embedded
|
35
|
+
|
36
|
+
property :id, :integer
|
37
|
+
property :title, :string
|
38
|
+
property :fields, [ :object ], :class => TicketCustomFieldValue, :get => :field
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class TicketCustomField < KayakoClient::Tickets
|
43
|
+
supports :get
|
44
|
+
|
45
|
+
TYPE_TEXT = 1
|
46
|
+
TYPE_TEXT_AREA = 2
|
47
|
+
TYPE_PASSWORD = 3
|
48
|
+
TYPE_CHECKBOX = 4
|
49
|
+
TYPE_RADIO = 5
|
50
|
+
TYPE_SELECT = 6
|
51
|
+
TYPE_MULTI_SELECT = 7
|
52
|
+
TYPE_CUSTOM = 8
|
53
|
+
TYPE_LINKED_SELECT = 9
|
54
|
+
TYPE_DATE = 10
|
55
|
+
TYPE_FILE = 11
|
56
|
+
|
57
|
+
property :groups, [ :object ], :class => TicketCustomFieldGroup, :get => :group
|
58
|
+
|
59
|
+
# NOTE: when a new field is added returns (for old tickets):
|
60
|
+
# [Notice]: Undefined offset: 11 (api/class.Controller_TicketCustomField.php:279)
|
61
|
+
|
62
|
+
def empty?
|
63
|
+
!(groups && groups.size > 0)
|
64
|
+
end
|
65
|
+
|
66
|
+
def custom_field(name)
|
67
|
+
if defined?(@groups) && @groups.size > 0
|
68
|
+
if name.is_a?(Numeric)
|
69
|
+
if name.to_i > 0
|
70
|
+
@groups.each do |group|
|
71
|
+
next unless group.fields && !group.fields.empty?
|
72
|
+
group.fields.each do |field|
|
73
|
+
if field.id == name.to_i
|
74
|
+
return field.contents
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
elsif name.is_a?(String)
|
80
|
+
@groups.each do |group|
|
81
|
+
next unless group.fields && !group.fields.empty?
|
82
|
+
group.fields.each do |field|
|
83
|
+
if field.title == name
|
84
|
+
return field.contents
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def [](name)
|
94
|
+
value = custom_field(name) unless name.is_a?(Symbol)
|
95
|
+
value || super
|
96
|
+
end
|
97
|
+
|
98
|
+
def each(&block)
|
99
|
+
if defined?(@groups) && @groups.size > 0
|
100
|
+
@custom_fields ||= @groups.inject([]) do |array, group|
|
101
|
+
array.concat(group.fields) if group.fields && group.fields.size > 0
|
102
|
+
array
|
103
|
+
end
|
104
|
+
@custom_fields.each(&block) unless @custom_fields.empty?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'kayako_client/mixins/ticket_api'
|
2
|
+
|
3
|
+
require 'kayako_client/staff'
|
4
|
+
require 'kayako_client/ticket'
|
5
|
+
require 'kayako_client/user'
|
6
|
+
require 'kayako_client/user_organization'
|
7
|
+
|
8
|
+
module KayakoClient
|
9
|
+
|
10
|
+
class Ticket < KayakoClient::Tickets
|
11
|
+
end
|
12
|
+
|
13
|
+
class TicketNote < KayakoClient::Tickets
|
14
|
+
include KayakoClient::TicketAPI
|
15
|
+
|
16
|
+
supports :all, :get, :post, :delete
|
17
|
+
|
18
|
+
NOTE_TYPES = [ :ticket, :user, :userorganization, :timetrack ].freeze
|
19
|
+
|
20
|
+
COLOR_YELLOW = 1
|
21
|
+
COLOR_PURPLE = 2
|
22
|
+
COLOR_BLUE = 3
|
23
|
+
COLOR_GREEN = 4
|
24
|
+
COLOR_RED = 5
|
25
|
+
|
26
|
+
property :id, :integer, :readonly => true
|
27
|
+
property :type, :symbol, :readonly => true, :in => NOTE_TYPES
|
28
|
+
property :ticket_id, :integer, :new => true, :required => :post
|
29
|
+
property :note_color, :integer, :new => true, :range => 1..5
|
30
|
+
property :creator_staff_id, :integer, :readonly => true
|
31
|
+
property :creator_staff_name, :string, :readonly => true
|
32
|
+
property :for_staff_id, :integer, :new => true
|
33
|
+
property :creation_date, :date, :readonly => true
|
34
|
+
property :contents, :string, :new => true, :required => :post
|
35
|
+
property :user_id, :integer, :readonly => true # :type = :user
|
36
|
+
property :user_organization_id, :integer, :readonly => true # :type = :userorganization
|
37
|
+
property :time_worked, :integer, :readonly => true # :type = :timetrack
|
38
|
+
property :time_billable, :integer, :readonly => true # :type = :timetrack
|
39
|
+
property :bill_date, :date, :readonly => true # :type = :timetrack
|
40
|
+
property :work_date, :date, :readonly => true # :type = :timetrack
|
41
|
+
property :worker_staff_id, :integer, :readonly => true # :type = :timetrack
|
42
|
+
property :worker_staff_name, :string, :readonly => true # :type = :timetrack
|
43
|
+
property :staff_id, :integer, :new => true
|
44
|
+
property :full_name, :string, :new => true
|
45
|
+
|
46
|
+
associate :ticket, :ticket_id, Ticket
|
47
|
+
associate :creator_staff, :creator_staff_id, Staff
|
48
|
+
associate :for_staff, :for_staff_id, Staff
|
49
|
+
associate :user, :user_id, User
|
50
|
+
associate :user_organization, :user_organization_id, UserOrganization
|
51
|
+
associate :worker_staff, :worker_staff_id, Staff
|
52
|
+
|
53
|
+
# NOTE: :all returns only notes of :ticket type
|
54
|
+
|
55
|
+
def is_ticket_note?
|
56
|
+
!type.nil? && type == :ticket
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_user_note?
|
60
|
+
!type.nil? && type == :user
|
61
|
+
end
|
62
|
+
|
63
|
+
def is_user_organization_note?
|
64
|
+
!type.nil? && type == :userorganization
|
65
|
+
end
|
66
|
+
|
67
|
+
def is_time_track_note?
|
68
|
+
!type.nil? && type == :timetrack
|
69
|
+
end
|
70
|
+
|
71
|
+
def has_creator_staff?
|
72
|
+
!creator_staff_id.nil? && creator_staff_id > 0
|
73
|
+
end
|
74
|
+
|
75
|
+
def has_for_staff?
|
76
|
+
!for_staff_id.nil? && for_staff_id > 0
|
77
|
+
end
|
78
|
+
|
79
|
+
def created_by_user?
|
80
|
+
!user_id.nil? && user_id > 0
|
81
|
+
end
|
82
|
+
|
83
|
+
alias_method :has_user?, :created_by_user?
|
84
|
+
|
85
|
+
def has_user_organization?
|
86
|
+
!user_organization_id.nil? && user_organization_id > 0
|
87
|
+
end
|
88
|
+
|
89
|
+
def has_worker_staff?
|
90
|
+
!worker_staff_id.nil? && worker_staff_id > 0
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def validate(method, params)
|
96
|
+
if method == :post
|
97
|
+
unless params[:staff_id] || params[:full_name]
|
98
|
+
raise ArgumentError, ":staff_id or :full_name is required"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'kayako_client/mixins/ticket_api'
|
2
|
+
|
3
|
+
require 'kayako_client/staff'
|
4
|
+
require 'kayako_client/user'
|
5
|
+
|
6
|
+
module KayakoClient
|
7
|
+
class TicketPost < KayakoClient::Tickets
|
8
|
+
include KayakoClient::TicketAPI
|
9
|
+
include KayakoClient::PostClient
|
10
|
+
|
11
|
+
supports :all, :get, :post, :delete
|
12
|
+
|
13
|
+
CREATOR_STAFF = 1
|
14
|
+
CREATOR_USER = 2
|
15
|
+
|
16
|
+
property :id, :integer, :readonly => true
|
17
|
+
property :date_line, :date, :readonly => true
|
18
|
+
property :user_id, :integer, :new => true
|
19
|
+
property :full_name, :string, :readonly => true
|
20
|
+
property :email, :string, :readonly => true
|
21
|
+
property :email_to, :string, :readonly => true
|
22
|
+
property :ip_address, :string, :readonly => true
|
23
|
+
property :has_attachments, :boolean, :readonly => true
|
24
|
+
property :creator, :integer, :readonly => true, :range => 1..2
|
25
|
+
property :is_third_party, :boolean, :readonly => true
|
26
|
+
property :is_html, :boolean, :readonly => true
|
27
|
+
property :is_emailed, :boolean, :readonly => true
|
28
|
+
property :staff_id, :integer, :new => true
|
29
|
+
property :is_survey_comment, :boolean, :readonly => true
|
30
|
+
property :contents, :string, :new => true, :required => :post
|
31
|
+
property :ticket_id, :integer, :new => true, :required => :post
|
32
|
+
property :subject, :string, :new => true, :required => :post
|
33
|
+
property :ticket_post_id, :integer, :readonly => true
|
34
|
+
|
35
|
+
associate :user, :user_id, User
|
36
|
+
associate :staff, :staff_id, Staff
|
37
|
+
|
38
|
+
def created_by_staff?
|
39
|
+
!creator.nil? && creator == CREATOR_STAFF
|
40
|
+
end
|
41
|
+
|
42
|
+
alias_method :has_staff?, :created_by_staff?
|
43
|
+
|
44
|
+
def created_by_user?
|
45
|
+
!creator.nil? && creator == CREATOR_USER
|
46
|
+
end
|
47
|
+
|
48
|
+
alias_method :has_user?, :created_by_user?
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def validate(method, params)
|
53
|
+
if method == :post
|
54
|
+
unless params[:user_id] || params[:staff_id]
|
55
|
+
raise ArgumentError, ":user_id or :staff_id is required"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|