From deeb6d4e3f48ff48080c59276c73beec1f08073b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 22 May 2025 21:20:28 +0530 Subject: [PATCH] fix: Ignore private notes from the last 5 min when determining if an out of office message should be sent (#11552) A while back, we added a UX enhancement that disabled sending the OOO message when an agent had replied to the conversation in the last 5 minutes. https://github.com/chatwoot/chatwoot/pull/11073 This would not send a "we will be back" message even if that reply was a private note. This would break for bots that posted private notes, and even for agents who need to just add a note and not actually reply to the email. --- .../hook_execution_service.rb | 2 +- .../hook_execution_service_spec.rb | 45 ++++++++++++++----- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/app/services/message_templates/hook_execution_service.rb b/app/services/message_templates/hook_execution_service.rb index bc161d885..a8a4c4318 100644 --- a/app/services/message_templates/hook_execution_service.rb +++ b/app/services/message_templates/hook_execution_service.rb @@ -27,7 +27,7 @@ class MessageTemplates::HookExecutionService return false unless message.incoming? # prevents sending out-of-office message if an agent has sent a message in last 5 minutes # ensures better UX by not interrupting active conversations at the end of business hours - return false if conversation.messages.outgoing.exists?(['created_at > ?', 5.minutes.ago]) + return false if conversation.messages.outgoing.where(private: false).exists?(['created_at > ?', 5.minutes.ago]) inbox.out_of_office? && conversation.messages.today.template.empty? && inbox.out_of_office_message.present? end diff --git a/spec/services/message_templates/hook_execution_service_spec.rb b/spec/services/message_templates/hook_execution_service_spec.rb index 9d9d82922..24e40ea8d 100644 --- a/spec/services/message_templates/hook_execution_service_spec.rb +++ b/spec/services/message_templates/hook_execution_service_spec.rb @@ -194,23 +194,44 @@ describe MessageTemplates::HookExecutionService do expect(out_of_office_service).to have_received(:perform) end - it 'does not call ::MessageTemplates::Template::OutOfOffice when there are recent outgoing messages' do - contact = create(:contact) - conversation = create(:conversation, contact: contact) + context 'with recent outgoing messages' do + it 'does not call ::MessageTemplates::Template::OutOfOffice when there are recent outgoing messages' do + contact = create(:contact) + conversation = create(:conversation, contact: contact) - conversation.inbox.update(working_hours_enabled: true, out_of_office_message: 'We are out of office') - conversation.inbox.working_hours.today.update!(closed_all_day: true) + conversation.inbox.update(working_hours_enabled: true, out_of_office_message: 'We are out of office') + conversation.inbox.working_hours.today.update!(closed_all_day: true) - create(:message, conversation: conversation, message_type: :outgoing, created_at: 2.minutes.ago) + create(:message, conversation: conversation, message_type: :outgoing, created_at: 2.minutes.ago) - out_of_office_service = double - allow(MessageTemplates::Template::OutOfOffice).to receive(:new).and_return(out_of_office_service) - allow(out_of_office_service).to receive(:perform).and_return(true) + out_of_office_service = double + allow(MessageTemplates::Template::OutOfOffice).to receive(:new).and_return(out_of_office_service) + allow(out_of_office_service).to receive(:perform).and_return(true) - create(:message, conversation: conversation) + create(:message, conversation: conversation) - expect(MessageTemplates::Template::OutOfOffice).not_to have_received(:new) - expect(out_of_office_service).not_to have_received(:perform) + expect(MessageTemplates::Template::OutOfOffice).not_to have_received(:new) + expect(out_of_office_service).not_to have_received(:perform) + end + + it 'ignores private note and calls ::MessageTemplates::Template::OutOfOffice' do + contact = create(:contact) + conversation = create(:conversation, contact: contact) + + conversation.inbox.update(working_hours_enabled: true, out_of_office_message: 'We are out of office') + conversation.inbox.working_hours.today.update!(closed_all_day: true) + + create(:message, conversation: conversation, private: true, message_type: :outgoing, created_at: 2.minutes.ago) + + out_of_office_service = double + allow(MessageTemplates::Template::OutOfOffice).to receive(:new).and_return(out_of_office_service) + allow(out_of_office_service).to receive(:perform).and_return(true) + + create(:message, conversation: conversation) + + expect(MessageTemplates::Template::OutOfOffice).to have_received(:new).with(conversation: conversation) + expect(out_of_office_service).to have_received(:perform) + end end it 'will not calls ::MessageTemplates::Template::OutOfOffice when outgoing message' do