Implemented issue #1825 - Auto assignment of unassigned tickets at first open time.
This commit is contained in:
parent
3fd1c2de7a
commit
2432b852b2
10 changed files with 316 additions and 13 deletions
|
@ -4,10 +4,11 @@ class Ticket extends App.ControllerTabs
|
|||
constructor: ->
|
||||
super
|
||||
|
||||
@title 'Ticket', true
|
||||
@title('Ticket', true)
|
||||
@tabs = [
|
||||
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } }
|
||||
{ name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } }
|
||||
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } }
|
||||
{ name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } }
|
||||
{ name: 'Auto Assignment', 'target': 'auto_assignment', controller: App.SettingTicketAutoAssignment }
|
||||
]
|
||||
@render()
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
class App.SettingTicketAutoAssignment extends App.ControllerSubContent
|
||||
requiredPermission: 'admin.ticket_auto_assignment'
|
||||
events:
|
||||
'change .js-ticketAutoAssignment input': 'setTicketAutoAssignment'
|
||||
'click .js-timeAccountingFilter': 'setFilter'
|
||||
'click .js-timeAccountingFilterReset': 'resetFilter'
|
||||
|
||||
elements:
|
||||
'.js-ticketAutoAssignment input': 'ticketAutoAssignment'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@subscribeId = App.Setting.subscribe(@render, initFetch: true, clear: false)
|
||||
|
||||
release: =>
|
||||
App.Setting.unsubscribe(@subscribeId)
|
||||
|
||||
render: =>
|
||||
currentNewTagSetting = @Config.get('ticket_auto_assignment') || false
|
||||
@lastNewTagSetting = currentNewTagSetting
|
||||
|
||||
@html(App.view('settings/ticket_auto_assignment')())
|
||||
|
||||
configure_attributes = [
|
||||
{ name: 'condition', display: 'Conditions for effected objects', tag: 'ticket_selector', null: false, preview: false, action: false, hasChanged: false },
|
||||
]
|
||||
|
||||
filter_params = App.Setting.get('ticket_auto_assignment_selector')
|
||||
@filter = new App.ControllerForm(
|
||||
el: @$('.js-selector')
|
||||
model:
|
||||
configure_attributes: configure_attributes,
|
||||
params: filter_params
|
||||
autofocus: true
|
||||
)
|
||||
|
||||
|
||||
setFilter: (e) =>
|
||||
e.preventDefault()
|
||||
|
||||
# get form data
|
||||
params = @formParam(@filter.form)
|
||||
|
||||
# save filter settings
|
||||
App.Setting.set('ticket_auto_assignment_selector', params, notify: true)
|
||||
|
||||
resetFilter: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
# save filter settings
|
||||
App.Setting.set('ticket_auto_assignment_selector', {}, notify: true)
|
||||
|
||||
setTicketAutoAssignment: (e) =>
|
||||
value = @ticketAutoAssignment.prop('checked')
|
||||
App.Setting.set('ticket_auto_assignment', value)
|
|
@ -332,10 +332,10 @@ class App.TicketCreate extends App.Controller
|
|||
App.Ticket.configure_attributes.pop()
|
||||
|
||||
# set type selector
|
||||
@setFormTypeInUi( params['formSenderType'] )
|
||||
@setFormTypeInUi(params['formSenderType'])
|
||||
|
||||
# remember form params of init load
|
||||
@formDefault = @formParam( @$('.ticket-create') )
|
||||
@formDefault = @formParam(@$('.ticket-create'))
|
||||
|
||||
# show text module UI
|
||||
@textModule = new App.WidgetTextModule(
|
||||
|
@ -510,11 +510,9 @@ class App.TicketCreate extends App.Controller
|
|||
ui.sidebarWidget.commit(ticket_id: @id)
|
||||
|
||||
# access to group
|
||||
for group_id, access of App.Session.get('group_ids')
|
||||
if @group_id.toString() is group_id.toString()
|
||||
if _.contains(access, 'read') || _.contains(access, 'full')
|
||||
ui.navigate "#ticket/zoom/#{@id}"
|
||||
return
|
||||
if @editable('change')
|
||||
ui.navigate "#ticket/zoom/#{@id}"
|
||||
return
|
||||
|
||||
# if not, show start screen
|
||||
ui.navigate '#'
|
||||
|
|
|
@ -483,6 +483,16 @@ class App.TicketZoom extends App.Controller
|
|||
links: @links
|
||||
)
|
||||
|
||||
# check if autolock is needed
|
||||
if @Config.get('ticket_auto_assignment') is true
|
||||
if @ticket.owner_id is 1 && @permissionCheck('ticket.agent') && @ticket.editable('full')
|
||||
ticket_auto_assignment_selector = @Config.get('ticket_auto_assignment_selector')
|
||||
if App.Ticket.selector(@ticket, ticket_auto_assignment_selector['condition'])
|
||||
assign = =>
|
||||
@ticket.owner_id = App.Session.get('id')
|
||||
@ticket.save()
|
||||
@delay(assign, 800, "ticket-auto-assign-#{@ticket.id}")
|
||||
|
||||
# render init content
|
||||
if elLocal
|
||||
@html elLocal
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<div class="page-header">
|
||||
<div class="page-header-title">
|
||||
<div class="zammad-switch zammad-switch--small js-ticketAutoAssignment">
|
||||
<input name="ticket_auto_assignment" type="checkbox" id="ticket_auto_assignment" <% if @C('ticket_auto_assignment'): %>checked<% end %>>
|
||||
<label for="ticket_auto_assignment"></label>
|
||||
</div>
|
||||
<h1><%- @T('Auto Assignment') %><small></small></h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-content">
|
||||
<div class="settings-entry">
|
||||
<p><%- @T('Enable automatic assignment the first time an agent opens a ticket.') %></p>
|
||||
<p><%- @T('Tickets are only assigned automatically if they do not already have an owner.') %></p>
|
||||
<div class="js-selector"></div>
|
||||
<button type="submit" class="btn btn--primary js-timeAccountingFilter"><%- @T('Save') %></button>
|
||||
<button type="submit" class="btn btn--danger js-timeAccountingFilterReset"><%- @T('Reset') %></button>
|
||||
</div>
|
||||
<div class="settings-entry">
|
||||
</div>
|
|
@ -0,0 +1,51 @@
|
|||
class SettingAddTicketAutoAssignment < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
|
||||
# return if it's a new setup
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Auto Assigment',
|
||||
name: 'ticket_auto_assignment',
|
||||
area: 'Web::Base',
|
||||
description: 'Enable ticket auto assignment.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
display: '',
|
||||
null: true,
|
||||
name: 'ticket_auto_assignment',
|
||||
tag: 'boolean',
|
||||
options: {
|
||||
true => 'yes',
|
||||
false => 'no',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
preferences: {
|
||||
authentication: true,
|
||||
permission: ['admin.ticket_auto_assignment'],
|
||||
},
|
||||
state: false,
|
||||
frontend: true
|
||||
)
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Time Accounting Selector',
|
||||
name: 'ticket_auto_assignment_selector',
|
||||
area: 'Web::Base',
|
||||
description: 'Enable auto assignment for following matching tickets.',
|
||||
options: {
|
||||
form: [
|
||||
{},
|
||||
],
|
||||
},
|
||||
preferences: {
|
||||
authentication: true,
|
||||
permission: ['admin.ticket_auto_assignment'],
|
||||
},
|
||||
state: { condition: { 'ticket.state_id' => { operator: 'is', value: Ticket::State.by_category(:work_on).pluck(:id) } } },
|
||||
frontend: true
|
||||
)
|
||||
end
|
||||
end
|
|
@ -1713,6 +1713,51 @@ Setting.create_if_not_exists(
|
|||
},
|
||||
frontend: false
|
||||
)
|
||||
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Auto Assigment',
|
||||
name: 'ticket_auto_assignment',
|
||||
area: 'Web::Base',
|
||||
description: 'Enable ticket auto assignment.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
display: '',
|
||||
null: true,
|
||||
name: 'ticket_auto_assignment',
|
||||
tag: 'boolean',
|
||||
options: {
|
||||
true => 'yes',
|
||||
false => 'no',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
preferences: {
|
||||
authentication: true,
|
||||
permission: ['admin.ticket_auto_assignment'],
|
||||
},
|
||||
state: false,
|
||||
frontend: true
|
||||
)
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Time Accounting Selector',
|
||||
name: 'ticket_auto_assignment_selector',
|
||||
area: 'Web::Base',
|
||||
description: 'Enable auto assignment for following matching tickets.',
|
||||
options: {
|
||||
form: [
|
||||
{},
|
||||
],
|
||||
},
|
||||
preferences: {
|
||||
authentication: true,
|
||||
permission: ['admin.ticket_auto_assignment'],
|
||||
},
|
||||
state: { condition: { 'ticket.state_id' => { operator: 'is', value: Ticket::State.by_category(:work_on).pluck(:id) } } },
|
||||
frontend: true
|
||||
)
|
||||
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Ticket Number ignore system_id',
|
||||
name: 'ticket_number_ignore_system_id',
|
||||
|
|
|
@ -20,6 +20,7 @@ if [ "$LEVEL" == '1' ]; then
|
|||
rm test/browser/admin_role_test.rb
|
||||
# test/browser/agent_navigation_and_title_test.rb
|
||||
rm test/browser/agent_ticket_attachment_test.rb
|
||||
rm test/browser/agent_ticket_auto_assignment_test.rb
|
||||
rm test/browser/agent_ticket_create_reset_customer_selection_test.rb
|
||||
rm test/browser/agent_ticket_email_reply_keep_body_test.rb
|
||||
rm test/browser/agent_ticket_email_signature_test.rb
|
||||
|
@ -79,6 +80,7 @@ elif [ "$LEVEL" == '2' ]; then
|
|||
rm test/browser/agent_navigation_and_title_test.rb
|
||||
rm test/browser/agent_organization_profile_test.rb
|
||||
rm test/browser/agent_ticket_attachment_test.rb
|
||||
rm test/browser/agent_ticket_auto_assignment_test.rb
|
||||
rm test/browser/agent_ticket_create_reset_customer_selection_test.rb
|
||||
rm test/browser/agent_ticket_email_reply_keep_body_test.rb
|
||||
rm test/browser/agent_ticket_email_signature_test.rb
|
||||
|
@ -138,6 +140,7 @@ elif [ "$LEVEL" == '3' ]; then
|
|||
rm test/browser/agent_navigation_and_title_test.rb
|
||||
rm test/browser/agent_organization_profile_test.rb
|
||||
# test/browser/agent_ticket_attachment_test.rb
|
||||
# test/browser/agent_ticket_auto_assignment_test.rb
|
||||
# test/browser/agent_ticket_create_reset_customer_selection_test.rb
|
||||
# test/browser/agent_ticket_email_reply_keep_body_test.rb
|
||||
# test/browser/agent_ticket_email_signature_test.rb
|
||||
|
@ -197,6 +200,7 @@ elif [ "$LEVEL" == '4' ]; then
|
|||
rm test/browser/agent_navigation_and_title_test.rb
|
||||
rm test/browser/agent_organization_profile_test.rb
|
||||
rm test/browser/agent_ticket_attachment_test.rb
|
||||
rm test/browser/agent_ticket_auto_assignment_test.rb
|
||||
rm test/browser/agent_ticket_create_reset_customer_selection_test.rb
|
||||
rm test/browser/agent_ticket_email_reply_keep_body_test.rb
|
||||
rm test/browser/agent_ticket_email_signature_test.rb
|
||||
|
@ -255,6 +259,7 @@ elif [ "$LEVEL" == '5' ]; then
|
|||
rm test/browser/agent_navigation_and_title_test.rb
|
||||
# test/browser/agent_organization_profile_test.rb
|
||||
rm test/browser/agent_ticket_attachment_test.rb
|
||||
rm test/browser/agent_ticket_auto_assignment_test.rb
|
||||
rm test/browser/agent_ticket_create_reset_customer_selection_test.rb
|
||||
rm test/browser/agent_ticket_email_reply_keep_body_test.rb
|
||||
rm test/browser/agent_ticket_email_signature_test.rb
|
||||
|
@ -316,6 +321,7 @@ elif [ "$LEVEL" == '6' ]; then
|
|||
rm test/browser/agent_navigation_and_title_test.rb
|
||||
rm test/browser/agent_organization_profile_test.rb
|
||||
rm test/browser/agent_ticket_attachment_test.rb
|
||||
rm test/browser/agent_ticket_auto_assignment_test.rb
|
||||
rm test/browser/agent_ticket_create_reset_customer_selection_test.rb
|
||||
rm test/browser/agent_ticket_email_reply_keep_body_test.rb
|
||||
rm test/browser/agent_ticket_email_signature_test.rb
|
||||
|
|
118
test/browser/agent_ticket_auto_assignment_test.rb
Normal file
118
test/browser/agent_ticket_auto_assignment_test.rb
Normal file
|
@ -0,0 +1,118 @@
|
|||
|
||||
require 'browser_test_helper'
|
||||
|
||||
class AgentTicketAutoAssignmentTest < TestCase
|
||||
def test_ticket
|
||||
|
||||
@browser = browser_instance
|
||||
login(
|
||||
username: 'agent1@example.com',
|
||||
password: 'test',
|
||||
url: browser_url,
|
||||
)
|
||||
tasks_close_all()
|
||||
|
||||
#
|
||||
# attachment checks - new ticket
|
||||
#
|
||||
|
||||
# create new ticket with no attachment, attachment check should pop up
|
||||
ticket1 = ticket_create(
|
||||
data: {
|
||||
customer: 'nico',
|
||||
group: 'Users',
|
||||
title: 'test_auto_assignment_1 - ticket 1',
|
||||
body: 'test_auto_assignment_1 - ticket 1 - no auto assignment',
|
||||
},
|
||||
)
|
||||
|
||||
ticket2 = ticket_create(
|
||||
data: {
|
||||
customer: 'nico',
|
||||
group: 'Users',
|
||||
title: 'test_auto_assignment_2 - ticket 2',
|
||||
body: 'test_auto_assignment_2 - ticket 2 - no auto assignment',
|
||||
},
|
||||
)
|
||||
|
||||
tasks_close_all()
|
||||
|
||||
logout()
|
||||
|
||||
login(
|
||||
username: 'master@example.com',
|
||||
password: 'test',
|
||||
url: browser_url,
|
||||
)
|
||||
tasks_close_all()
|
||||
|
||||
# open ticket#1
|
||||
ticket_open_by_search(
|
||||
number: ticket1[:number],
|
||||
)
|
||||
|
||||
# verify if owner is set
|
||||
match(
|
||||
css: '.content.active .sidebar select[name="owner_id"]',
|
||||
value: '-',
|
||||
)
|
||||
|
||||
# open ticket#2
|
||||
ticket_open_by_search(
|
||||
number: ticket2[:number],
|
||||
)
|
||||
|
||||
# verify if owner is set
|
||||
match(
|
||||
css: '.content.active .sidebar select[name="owner_id"]',
|
||||
value: '-',
|
||||
)
|
||||
|
||||
tasks_close_all()
|
||||
|
||||
# enable auto assignment
|
||||
click(css: 'a[href="#manage"]')
|
||||
click(css: '.content.active a[href="#settings/ticket"]')
|
||||
click(css: '.content.active a[href="#auto_assignment"]')
|
||||
switch(
|
||||
css: '.content.active .js-ticketAutoAssignment',
|
||||
type: 'on',
|
||||
)
|
||||
|
||||
# open ticket#1
|
||||
ticket_open_by_search(
|
||||
number: ticket1[:number],
|
||||
)
|
||||
|
||||
# verify if owner is set
|
||||
watch_for(
|
||||
css: '.content.active .sidebar select[name="owner_id"]',
|
||||
value: 'Test Master',
|
||||
timeout: 2,
|
||||
)
|
||||
|
||||
# open ticket#2
|
||||
ticket_open_by_search(
|
||||
number: ticket2[:number],
|
||||
)
|
||||
|
||||
# verify if owner is set
|
||||
watch_for(
|
||||
css: '.content.active .sidebar select[name="owner_id"]',
|
||||
value: 'Test Master',
|
||||
timeout: 2,
|
||||
)
|
||||
|
||||
tasks_close_all()
|
||||
|
||||
# disable auto assignment
|
||||
click(css: 'a[href="#manage"]')
|
||||
click(css: '.content.active a[href="#settings/ticket"]')
|
||||
click(css: '.content.active a[href="#auto_assignment"]')
|
||||
switch(
|
||||
css: '.content.active .js-ticketAutoAssignment',
|
||||
type: 'off',
|
||||
)
|
||||
|
||||
end
|
||||
end
|
|
@ -31,8 +31,8 @@ class AgentTicketTextModuleTest < TestCase
|
|||
)
|
||||
|
||||
# try to use them
|
||||
click( css: 'a[href="#new"]' )
|
||||
click( css: 'a[href="#ticket/create"]' )
|
||||
click(css: 'a[href="#new"]')
|
||||
click(css: 'a[href="#ticket/create"]')
|
||||
sleep 2
|
||||
|
||||
set(
|
||||
|
@ -47,7 +47,7 @@ class AgentTicketTextModuleTest < TestCase
|
|||
value: :arrow_down,
|
||||
slow: true,
|
||||
)
|
||||
click( css: '.active .shortcut > ul> li' )
|
||||
click(css: '.active .shortcut > ul> li')
|
||||
|
||||
watch_for(
|
||||
css: '.active div[data-name=body]',
|
||||
|
|
Loading…
Reference in a new issue