diff --git a/app/models/observer/ticket/article_changes.rb b/app/models/observer/ticket/article_changes.rb index a62ad9e88..c0184f6fa 100644 --- a/app/models/observer/ticket/article_changes.rb +++ b/app/models/observer/ticket/article_changes.rb @@ -110,6 +110,18 @@ class Observer::Ticket::ArticleChanges < ActiveRecord::Observer ticket = record.ticket if sender.name == 'Customer' + # in case, update last_contact_customer_at on any customer follow up + if Setting.get('ticket_last_contact_behaviour') == 'based_on_customer_reaction' + + # set last_contact_at customer + record.ticket.last_contact_customer_at = record.created_at + + # set last_contact + record.ticket.last_contact_at = record.created_at + + return true + end + # if customer is sending agains, ignore update of last contact (usecase of update escalation) return false if ticket.last_contact_customer_at && ticket.last_contact_at && @@ -125,7 +137,6 @@ class Observer::Ticket::ArticleChanges < ActiveRecord::Observer # set last_contact record.ticket.last_contact_at = record.created_at - end return true end diff --git a/db/migrate/20180521141004_ticket_last_contact_behavior.rb b/db/migrate/20180521141004_ticket_last_contact_behavior.rb new file mode 100644 index 000000000..30d3828e7 --- /dev/null +++ b/db/migrate/20180521141004_ticket_last_contact_behavior.rb @@ -0,0 +1,33 @@ +class TicketLastContactBehavior < 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: 'Ticket Last Contact Behaviour', + name: 'ticket_last_contact_behaviour', + area: 'Ticket::Base', + description: 'Sets the last customer contact based on the last contact of a customer or on the last contact of a customer to whom an agent has not yet responded.', + options: { + form: [ + { + display: '', + null: true, + name: 'ticket_last_contact_behaviour', + tag: 'select', + translate: true, + options: { + 'based_on_customer_reaction' => 'Last customer contact (without consideration an agent has replied to it)', + 'check_if_agent_already_replied' => 'Last customer contact (with consideration an agent has replied to it)', + }, + }, + ], + }, + state: 'check_if_agent_already_replied', + preferences: { + permission: ['admin.ticket'], + }, + frontend: false + ) + end +end diff --git a/db/seeds/settings.rb b/db/seeds/settings.rb index b7275a8b1..91708b2ca 100644 --- a/db/seeds/settings.rb +++ b/db/seeds/settings.rb @@ -1789,6 +1789,32 @@ Setting.create_if_not_exists( }, frontend: false ) +Setting.create_if_not_exists( + title: 'Ticket Last Contact Behaviour', + name: 'ticket_last_contact_behaviour', + area: 'Ticket::Base', + description: 'Sets the last customer contact based on the last contact of a customer or on the last contact of a customer to whom an agent has not yet responded.', + options: { + form: [ + { + display: '', + null: true, + name: 'ticket_last_contact_behaviour', + tag: 'select', + translate: true, + options: { + 'based_on_customer_reaction' => 'Last customer contact (without consideration an agent has replied to it)', + 'check_if_agent_already_replied' => 'Last customer contact (with consideration an agent has replied to it)', + }, + }, + ], + }, + state: 'check_if_agent_already_replied', + preferences: { + permission: ['admin.ticket'], + }, + frontend: false +) Setting.create_if_not_exists( title: 'Ticket Number Format', name: 'ticket_number', diff --git a/test/unit/ticket_sla_test.rb b/test/unit/ticket_sla_test.rb index 83f15a403..dd226aba3 100644 --- a/test/unit/ticket_sla_test.rb +++ b/test/unit/ticket_sla_test.rb @@ -4,11 +4,6 @@ require 'test_helper' class TicketSlaTest < ActiveSupport::TestCase test 'ticket sla' do - - # cleanup - delete = Ticket.destroy_all - assert(delete, 'ticket destroy_all') - ticket = Ticket.create!( title: 'some title äöüß', group: Group.lookup(name: 'Users'), @@ -502,11 +497,6 @@ class TicketSlaTest < ActiveSupport::TestCase end test 'ticket sla + selector' do - - # cleanup - delete = Ticket.destroy_all - assert(delete, 'ticket destroy_all') - calendar1 = Calendar.create_or_update( name: 'EU 1', timezone: 'Europe/Berlin', @@ -611,13 +601,6 @@ class TicketSlaTest < ActiveSupport::TestCase end test 'ticket sla + timezone + holiday' do - - # cleanup - delete = Sla.destroy_all - assert(delete, 'sla destroy_all') - delete = Ticket.destroy_all - assert(delete, 'ticket destroy_all') - ticket = Ticket.create!( title: 'some title äöüß', group: Group.lookup(name: 'Users'), @@ -862,13 +845,6 @@ class TicketSlaTest < ActiveSupport::TestCase end test 'ticket escalation suspend close reopen bug' do - - # cleanup - delete = Sla.destroy_all - assert(delete, 'sla destroy_all') - delete = Ticket.destroy_all - assert(delete, 'ticket destroy_all') - ticket1 = Ticket.create!( title: 'some title äöüß3', group: Group.lookup(name: 'Users'), @@ -1568,7 +1544,6 @@ class TicketSlaTest < ActiveSupport::TestCase end test 'ticket ticket.title and article.subject' do - ticket = Ticket.create!( title: 'some title SLATEST1 for you', group: Group.lookup(name: 'Users'), @@ -1735,13 +1710,6 @@ class TicketSlaTest < ActiveSupport::TestCase end test 'ticket sla + holiday 222' do - - # cleanup - delete = Sla.destroy_all - assert(delete, 'sla destroy_all') - delete = Ticket.destroy_all - assert(delete, 'ticket destroy_all') - ticket = Ticket.create!( title: 'some title 222', group: Group.lookup(name: 'Users'), @@ -1961,13 +1929,6 @@ class TicketSlaTest < ActiveSupport::TestCase end test 'ticket sla + observer check' do - - # cleanup - delete = Sla.destroy_all - assert(delete, 'sla destroy_all') - delete = Ticket.destroy_all - assert(delete, 'ticket destroy_all') - ticket = Ticket.create!( title: 'some title observer#1', group: Group.lookup(name: 'Users'), @@ -2143,4 +2104,114 @@ class TicketSlaTest < ActiveSupport::TestCase calendar.destroy! end + test 'update last_customer_contact_at when the agent does not reply' do + + Setting.set('ticket_last_contact_behaviour', 'based_on_customer_reaction') + + ticket = Ticket.create!( + title: 'test #1 last_contact_customer_at', + group: Group.lookup(name: 'Users'), + customer_id: 2, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + created_at: '2018-05-01 13:56:21 UTC', + updated_at: '2018-05-01 13:56:21 UTC', + updated_by_id: 1, + created_by_id: 1, + ) + assert(ticket, 'ticket created') + + article1 = Ticket::Article.create!( + ticket_id: ticket.id, + from: 'some_sender@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'phone').first, + updated_by_id: 1, + created_by_id: 1, + created_at: '2018-05-01 13:56:21 UTC', + updated_at: '2018-05-01 13:56:21 UTC', + ) + + ticket.reload + assert_equal(ticket.article_count, 1) + assert_equal(ticket.last_contact_at.to_s, article1.created_at.to_s) + assert_equal(ticket.last_contact_customer_at.to_s, article1.created_at.to_s) + assert_nil(ticket.last_contact_agent_at) + assert_nil(ticket.first_response_at) + assert_nil(ticket.close_at) + + article2 = Ticket::Article.create!( + ticket_id: ticket.id, + from: 'some_sender@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'phone').first, + updated_by_id: 1, + created_by_id: 1, + created_at: '2018-05-01 14:56:21 UTC', + updated_at: '2018-05-01 14:56:21 UTC', + ) + + ticket = Ticket.find(ticket.id) + assert_equal(ticket.article_count, 2) + assert_equal(ticket.last_contact_at.to_s, article2.created_at.to_s) + assert_equal(ticket.last_contact_customer_at.to_s, article2.created_at.to_s) + assert_nil(ticket.last_contact_agent_at) + assert_nil(ticket.first_response_at) + assert_nil(ticket.close_at) + + article3 = Ticket::Article.create!( + ticket_id: ticket.id, + from: 'some_sender@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'phone').first, + updated_by_id: 1, + created_by_id: 1, + created_at: '2018-05-01 15:56:21 UTC', + updated_at: '2018-05-01 15:56:21 UTC', + ) + + ticket.reload + assert_equal(ticket.article_count, 3) + assert_equal(ticket.last_contact_at.to_s, article3.created_at.to_s) + assert_equal(ticket.last_contact_customer_at.to_s, article3.created_at.to_s) + assert_nil(ticket.last_contact_agent_at) + assert_nil(ticket.first_response_at) + assert_nil(ticket.close_at) + + article4 = Ticket::Article.create!( + ticket_id: ticket.id, + from: 'some_sender@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Agent').first, + type: Ticket::Article::Type.where(name: 'phone').first, + updated_by_id: 1, + created_by_id: 1, + created_at: '2018-05-01 16:56:21 UTC', + updated_at: '2018-05-01 16:56:21 UTC', + ) + + ticket.reload + assert_equal(ticket.article_count, 4) + assert_equal(ticket.last_contact_at.to_s, article4.created_at.to_s) + assert_equal(ticket.last_contact_customer_at.to_s, article3.created_at.to_s) + assert_equal(ticket.last_contact_agent_at.to_s, article4.created_at.to_s) + assert_equal(ticket.first_response_at.to_s, article4.created_at.to_s) + assert_nil(ticket.close_at) + end + end