Skip to content

Commit

Permalink
fix: assignee_changed callback not getting triggered during conversat…
Browse files Browse the repository at this point in the history
…ion creation (#9334)

The reload method in our callback was refreshing the object and hence the saved_change_to_assignee_id? Method wasn't working in the following callbacks.

This impacted the listeners subscribing to the event `ASSIGNEE_CHANGE`, `TEAM_CHANGE` etc
  • Loading branch information
sojan-official committed May 6, 2024
1 parent 2af0d58 commit f6d7f3b
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 27 deletions.
5 changes: 3 additions & 2 deletions app/dispatchers/async_dispatcher.rb
Expand Up @@ -10,14 +10,15 @@ def publish_event(event_name, timestamp, data)

def listeners
[
AutomationRuleListener.instance,
CampaignListener.instance,
CsatSurveyListener.instance,
HookListener.instance,
InstallationWebhookListener.instance,
NotificationListener.instance,
ParticipationListener.instance,
ReportingEventListener.instance,
WebhookListener.instance,
AutomationRuleListener.instance
WebhookListener.instance
]
end
end
8 changes: 8 additions & 0 deletions app/listeners/participation_listener.rb
@@ -0,0 +1,8 @@
class ParticipationListener < BaseListener
include Events::Types

def assignee_changed(event)
conversation, _account = extract_conversation_and_account(event)
conversation.conversation_participants.find_or_create_by!(user_id: conversation.assignee_id) if conversation.assignee_id.present?
end
end
7 changes: 0 additions & 7 deletions app/models/concerns/assignment_handler.rb
Expand Up @@ -38,7 +38,6 @@ def notify_assignment_change

def process_assignment_changes
process_assignment_activities
process_participant_assignment
end

def process_assignment_activities
Expand All @@ -49,10 +48,4 @@ def process_assignment_activities
create_assignee_change_activity(user_name)
end
end

def process_participant_assignment
return unless saved_change_to_assignee_id? && assignee_id.present?

conversation_participants.find_or_create_by!(user_id: assignee_id)
end
end
1 change: 0 additions & 1 deletion app/models/concerns/auto_assignment_handler.rb
Expand Up @@ -15,7 +15,6 @@ def run_auto_assignment
return unless should_run_auto_assignment?

::AutoAssignment::AgentAssignmentService.new(conversation: self, allowed_agent_ids: inbox.member_ids_with_assignment_capacity).perform
conversation_participants.find_or_create_by(user_id: assignee_id) if assignee_id.present?
end

def should_run_auto_assignment?
Expand Down
11 changes: 8 additions & 3 deletions app/models/conversation.rb
Expand Up @@ -110,7 +110,7 @@ class Conversation < ApplicationRecord

after_update_commit :execute_after_update_commit_callbacks
after_create_commit :notify_conversation_creation
after_commit :set_display_id, unless: :display_id?
after_create_commit :load_attributes_created_by_db_triggers

delegate :auto_resolve_duration, to: :account

Expand Down Expand Up @@ -257,8 +257,13 @@ def self_assign?(assignee_id)
assignee_id.present? && Current.user&.id == assignee_id
end

def set_display_id
reload
def load_attributes_created_by_db_triggers
# Display id is set via a trigger in the database
# So we need to specifically fetch it after the record is created
# We can't use reload because it will clear the previous changes, which we need for the dispatcher
obj_from_db = self.class.find(id)
self[:display_id] = obj_from_db[:display_id]
self[:uuid] = obj_from_db[:uuid]
end

def notify_status_change
Expand Down
Expand Up @@ -21,7 +21,7 @@

describe '#perform - SLA misses' do
context 'when first response SLA is missed' do
before { sla_policy.update(first_response_time_threshold: 1.hour) }
before { applied_sla.sla_policy.update(first_response_time_threshold: 1.hour) }

it 'updates the SLA status to missed and logs a warning' do
allow(Rails.logger).to receive(:warn)
Expand All @@ -42,7 +42,7 @@

context 'when next response SLA is missed' do
before do
sla_policy.update(next_response_time_threshold: 1.hour)
applied_sla.sla_policy.update(next_response_time_threshold: 1.hour)
conversation.update(first_reply_created_at: 5.hours.ago, waiting_since: 5.hours.ago)
end

Expand All @@ -64,7 +64,7 @@
end

context 'when resolution time SLA is missed' do
before { sla_policy.update(resolution_time_threshold: 1.hour) }
before { applied_sla.sla_policy.update(resolution_time_threshold: 1.hour) }

it 'updates the SLA status to missed and logs a warning' do
allow(Rails.logger).to receive(:warn)
Expand All @@ -89,7 +89,7 @@
context 'when resolved conversation with resolution time SLA is missed' do
before do
conversation.resolved!
sla_policy.update(resolution_time_threshold: 1.hour)
applied_sla.sla_policy.update(resolution_time_threshold: 1.hour)
end

it 'does not update the SLA status to missed' do
Expand All @@ -100,7 +100,7 @@

context 'when multiple SLAs are missed' do
before do
sla_policy.update(first_response_time_threshold: 1.hour, next_response_time_threshold: 1.hour, resolution_time_threshold: 1.hour)
applied_sla.sla_policy.update(first_response_time_threshold: 1.hour, next_response_time_threshold: 1.hour, resolution_time_threshold: 1.hour)
conversation.update(first_reply_created_at: 5.hours.ago, waiting_since: 5.hours.ago)
end

Expand All @@ -119,7 +119,7 @@
describe '#perform - SLA hits' do
context 'when first response SLA is hit' do
before do
sla_policy.update(first_response_time_threshold: 6.hours)
applied_sla.sla_policy.update(first_response_time_threshold: 6.hours)
conversation.update(first_reply_created_at: 30.minutes.ago)
end

Expand All @@ -142,7 +142,7 @@

context 'when next response SLA is hit' do
before do
sla_policy.update(next_response_time_threshold: 6.hours)
applied_sla.sla_policy.update(next_response_time_threshold: 6.hours)
conversation.update(first_reply_created_at: 30.minutes.ago, waiting_since: nil)
end

Expand All @@ -164,7 +164,7 @@

context 'when resolution time SLA is hit' do
before do
sla_policy.update(resolution_time_threshold: 8.hours)
applied_sla.sla_policy.update(resolution_time_threshold: 8.hours)
conversation.resolved!
end

Expand All @@ -182,7 +182,7 @@
describe 'SLA evaluation with frt hit, multiple nrt misses and rt miss' do
before do
# Setup SLA Policy thresholds
sla_policy.update(
applied_sla.sla_policy.update(
first_response_time_threshold: 2.hours, # Hit frt
next_response_time_threshold: 1.hour, # Miss nrt multiple times
resolution_time_threshold: 4.hours # Miss rt
Expand Down
26 changes: 26 additions & 0 deletions spec/listeners/participation_listener_spec.rb
@@ -0,0 +1,26 @@
require 'rails_helper'
describe ParticipationListener do
let(:listener) { described_class.instance }
let!(:account) { create(:account) }
let!(:admin) { create(:user, account: account, role: :administrator) }
let!(:inbox) { create(:inbox, account: account) }
let!(:agent) { create(:user, account: account, role: :agent) }
let!(:conversation) { create(:conversation, account: account, inbox: inbox, assignee: agent) }

before do
create(:inbox_member, inbox: inbox, user: agent)
Current.user = nil
Current.account = nil
end

describe '#assignee_changed' do
let(:event_name) { :assignee_changed }
let!(:event) { Events::Base.new(event_name, Time.zone.now, conversation: conversation) }

it 'adds the assignee as a participant to the conversation' do
expect(conversation.conversation_participants.map(&:user_id)).not_to include(admin.id)
listener.assignee_changed(event)
expect(conversation.conversation_participants.map(&:user_id)).to include(agent.id)
end
end
end
4 changes: 0 additions & 4 deletions spec/models/concerns/auto_assignment_handler_shared.rb
Expand Up @@ -26,10 +26,6 @@
expect(conversation.reload.assignee).to eq(agent)
end

it 'adds assignee to conversation participants' do
expect(conversation.conversation_participants.map(&:user)).to include(agent)
end

it 'will not auto assign agent if enable_auto_assignment is false' do
inbox.update(enable_auto_assignment: false)

Expand Down
6 changes: 5 additions & 1 deletion spec/models/message_spec.rb
Expand Up @@ -107,7 +107,11 @@
end

describe 'message create event' do
let(:conversation) { create(:conversation) }
let!(:conversation) { create(:conversation) }

before do
conversation.reload
end

it 'updates the conversation first reply created at if it is the first outgoing message' do
expect(conversation.first_reply_created_at).to be_nil
Expand Down

0 comments on commit f6d7f3b

Please sign in to comment.