Implemented issue #1825 - Auto assignment of unassigned tickets at first open time.

This commit is contained in:
Martin Edenhofer 2018-02-12 17:31:02 +01:00
parent 3fd1c2de7a
commit 2432b852b2
10 changed files with 316 additions and 13 deletions

View file

@ -4,10 +4,11 @@ class Ticket extends App.ControllerTabs
constructor: -> constructor: ->
super super
@title 'Ticket', true @title('Ticket', true)
@tabs = [ @tabs = [
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } } { name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } }
{ name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } } { name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } }
{ name: 'Auto Assignment', 'target': 'auto_assignment', controller: App.SettingTicketAutoAssignment }
] ]
@render() @render()

View file

@ -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)

View file

@ -332,10 +332,10 @@ class App.TicketCreate extends App.Controller
App.Ticket.configure_attributes.pop() App.Ticket.configure_attributes.pop()
# set type selector # set type selector
@setFormTypeInUi( params['formSenderType'] ) @setFormTypeInUi(params['formSenderType'])
# remember form params of init load # remember form params of init load
@formDefault = @formParam( @$('.ticket-create') ) @formDefault = @formParam(@$('.ticket-create'))
# show text module UI # show text module UI
@textModule = new App.WidgetTextModule( @textModule = new App.WidgetTextModule(
@ -510,11 +510,9 @@ class App.TicketCreate extends App.Controller
ui.sidebarWidget.commit(ticket_id: @id) ui.sidebarWidget.commit(ticket_id: @id)
# access to group # access to group
for group_id, access of App.Session.get('group_ids') if @editable('change')
if @group_id.toString() is group_id.toString() ui.navigate "#ticket/zoom/#{@id}"
if _.contains(access, 'read') || _.contains(access, 'full') return
ui.navigate "#ticket/zoom/#{@id}"
return
# if not, show start screen # if not, show start screen
ui.navigate '#' ui.navigate '#'

View file

@ -483,6 +483,16 @@ class App.TicketZoom extends App.Controller
links: @links 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 # render init content
if elLocal if elLocal
@html elLocal @html elLocal

View file

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

View file

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

View file

@ -1713,6 +1713,51 @@ Setting.create_if_not_exists(
}, },
frontend: false 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( Setting.create_if_not_exists(
title: 'Ticket Number ignore system_id', title: 'Ticket Number ignore system_id',
name: 'ticket_number_ignore_system_id', name: 'ticket_number_ignore_system_id',

View file

@ -20,6 +20,7 @@ if [ "$LEVEL" == '1' ]; then
rm test/browser/admin_role_test.rb rm test/browser/admin_role_test.rb
# test/browser/agent_navigation_and_title_test.rb # test/browser/agent_navigation_and_title_test.rb
rm test/browser/agent_ticket_attachment_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_create_reset_customer_selection_test.rb
rm test/browser/agent_ticket_email_reply_keep_body_test.rb rm test/browser/agent_ticket_email_reply_keep_body_test.rb
rm test/browser/agent_ticket_email_signature_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_navigation_and_title_test.rb
rm test/browser/agent_organization_profile_test.rb rm test/browser/agent_organization_profile_test.rb
rm test/browser/agent_ticket_attachment_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_create_reset_customer_selection_test.rb
rm test/browser/agent_ticket_email_reply_keep_body_test.rb rm test/browser/agent_ticket_email_reply_keep_body_test.rb
rm test/browser/agent_ticket_email_signature_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_navigation_and_title_test.rb
rm test/browser/agent_organization_profile_test.rb rm test/browser/agent_organization_profile_test.rb
# test/browser/agent_ticket_attachment_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_create_reset_customer_selection_test.rb
# test/browser/agent_ticket_email_reply_keep_body_test.rb # test/browser/agent_ticket_email_reply_keep_body_test.rb
# test/browser/agent_ticket_email_signature_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_navigation_and_title_test.rb
rm test/browser/agent_organization_profile_test.rb rm test/browser/agent_organization_profile_test.rb
rm test/browser/agent_ticket_attachment_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_create_reset_customer_selection_test.rb
rm test/browser/agent_ticket_email_reply_keep_body_test.rb rm test/browser/agent_ticket_email_reply_keep_body_test.rb
rm test/browser/agent_ticket_email_signature_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 rm test/browser/agent_navigation_and_title_test.rb
# test/browser/agent_organization_profile_test.rb # test/browser/agent_organization_profile_test.rb
rm test/browser/agent_ticket_attachment_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_create_reset_customer_selection_test.rb
rm test/browser/agent_ticket_email_reply_keep_body_test.rb rm test/browser/agent_ticket_email_reply_keep_body_test.rb
rm test/browser/agent_ticket_email_signature_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_navigation_and_title_test.rb
rm test/browser/agent_organization_profile_test.rb rm test/browser/agent_organization_profile_test.rb
rm test/browser/agent_ticket_attachment_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_create_reset_customer_selection_test.rb
rm test/browser/agent_ticket_email_reply_keep_body_test.rb rm test/browser/agent_ticket_email_reply_keep_body_test.rb
rm test/browser/agent_ticket_email_signature_test.rb rm test/browser/agent_ticket_email_signature_test.rb

View 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

View file

@ -31,8 +31,8 @@ class AgentTicketTextModuleTest < TestCase
) )
# try to use them # try to use them
click( css: 'a[href="#new"]' ) click(css: 'a[href="#new"]')
click( css: 'a[href="#ticket/create"]' ) click(css: 'a[href="#ticket/create"]')
sleep 2 sleep 2
set( set(
@ -47,7 +47,7 @@ class AgentTicketTextModuleTest < TestCase
value: :arrow_down, value: :arrow_down,
slow: true, slow: true,
) )
click( css: '.active .shortcut > ul> li' ) click(css: '.active .shortcut > ul> li')
watch_for( watch_for(
css: '.active div[data-name=body]', css: '.active div[data-name=body]',