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.
- 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
|