From 6325bd667a357f2497416072617943daf03dff5f Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 21 Jan 2026 17:55:38 +0530 Subject: [PATCH] feat: include additional information --- app/listeners/reporting_event_listener.rb | 86 ++++++++----------- .../reporting_event_listener_spec.rb | 33 ++++++- 2 files changed, 70 insertions(+), 49 deletions(-) diff --git a/app/listeners/reporting_event_listener.rb b/app/listeners/reporting_event_listener.rb index d1d8b7b5a..f5bbe6cd7 100644 --- a/app/listeners/reporting_event_listener.rb +++ b/app/listeners/reporting_event_listener.rb @@ -7,12 +7,9 @@ class ReportingEventListener < BaseListener ReportingEvent.create!( name: 'conversation_created', value: 0, - account_id: conversation.account_id, - inbox_id: conversation.inbox_id, - user_id: conversation.assignee_id, - conversation_id: conversation.id, event_start_time: conversation.created_at, - event_end_time: conversation.created_at + event_end_time: conversation.created_at, + **base_event_attributes(conversation, from_state: nil) ) end @@ -23,14 +20,10 @@ class ReportingEventListener < BaseListener reporting_event = ReportingEvent.new( name: 'conversation_resolved', value: time_to_resolve, - value_in_business_hours: business_hours(conversation.inbox, conversation.created_at, - conversation.updated_at), - account_id: conversation.account_id, - inbox_id: conversation.inbox_id, - user_id: conversation.assignee_id, - conversation_id: conversation.id, + value_in_business_hours: business_hours(conversation.inbox, conversation.created_at, conversation.updated_at), event_start_time: conversation.created_at, - event_end_time: conversation.updated_at + event_end_time: conversation.updated_at, + **base_event_attributes(conversation, from_state: 'handling') ) create_bot_resolved_event(conversation, reporting_event) @@ -42,20 +35,14 @@ class ReportingEventListener < BaseListener conversation = message.conversation first_response_time = message.created_at.to_i - last_non_human_activity(conversation).to_i - reporting_event = ReportingEvent.new( + ReportingEvent.create!( name: 'first_response', value: first_response_time, - value_in_business_hours: business_hours(conversation.inbox, last_non_human_activity(conversation), - message.created_at), - account_id: conversation.account_id, - inbox_id: conversation.inbox_id, - user_id: message.sender_id, - conversation_id: conversation.id, + value_in_business_hours: business_hours(conversation.inbox, last_non_human_activity(conversation), message.created_at), event_start_time: last_non_human_activity(conversation), - event_end_time: message.created_at + event_end_time: message.created_at, + **base_event_attributes(conversation, from_state: 'waiting', user_id: message.sender_id) ) - - reporting_event.save! end def reply_created(event) @@ -65,21 +52,16 @@ class ReportingEventListener < BaseListener return if waiting_since.blank? - # When waiting_since is nil, set reply_time to 0 reply_time = message.created_at.to_i - waiting_since.to_i - reporting_event = ReportingEvent.new( + ReportingEvent.create!( name: 'reply_time', value: reply_time, value_in_business_hours: business_hours(conversation.inbox, waiting_since, message.created_at), - account_id: conversation.account_id, - inbox_id: conversation.inbox_id, - user_id: conversation.assignee_id, - conversation_id: conversation.id, event_start_time: waiting_since, - event_end_time: message.created_at + event_end_time: message.created_at, + **base_event_attributes(conversation, from_state: 'waiting') ) - reporting_event.save! end def conversation_bot_handoff(event) @@ -91,18 +73,14 @@ class ReportingEventListener < BaseListener time_to_handoff = conversation.updated_at.to_i - conversation.created_at.to_i - reporting_event = ReportingEvent.new( + ReportingEvent.create!( name: 'conversation_bot_handoff', value: time_to_handoff, value_in_business_hours: business_hours(conversation.inbox, conversation.created_at, conversation.updated_at), - account_id: conversation.account_id, - inbox_id: conversation.inbox_id, - user_id: conversation.assignee_id, - conversation_id: conversation.id, event_start_time: conversation.created_at, - event_end_time: conversation.updated_at + event_end_time: conversation.updated_at, + **base_event_attributes(conversation, from_state: 'bot_handling') ) - reporting_event.save! end def conversation_opened(event) @@ -114,36 +92,47 @@ class ReportingEventListener < BaseListener name: 'conversation_resolved' ).order(event_end_time: :desc).first - # For first-time openings, value is 0 - # For reopenings, calculate time since resolution + # For first-time openings, value is 0, from_state is nil + # For reopenings, calculate time since resolution, from_state is 'resolved' if last_resolved_event time_since_resolved = conversation.updated_at.to_i - last_resolved_event.event_end_time.to_i business_hours_value = business_hours(conversation.inbox, last_resolved_event.event_end_time, conversation.updated_at) start_time = last_resolved_event.event_end_time + from_state = 'resolved' else time_since_resolved = 0 business_hours_value = 0 start_time = conversation.created_at + from_state = nil end - create_conversation_opened_event(conversation, time_since_resolved, business_hours_value, start_time) + create_conversation_opened_event(conversation, time_since_resolved, business_hours_value, start_time, from_state) end private - def create_conversation_opened_event(conversation, time_since_resolved, business_hours_value, start_time) - reporting_event = ReportingEvent.new( + def base_event_attributes(conversation, from_state:, user_id: nil) + { + account_id: conversation.account_id, + inbox_id: conversation.inbox_id, + user_id: user_id || conversation.assignee_id, + conversation_id: conversation.id, + conversation_created_at: conversation.created_at, + team_id: conversation.team_id, + channel_type: conversation.inbox.channel_type, + from_state: from_state + } + end + + def create_conversation_opened_event(conversation, time_since_resolved, business_hours_value, start_time, from_state) + ReportingEvent.create!( name: 'conversation_opened', value: time_since_resolved, value_in_business_hours: business_hours_value, - account_id: conversation.account_id, - inbox_id: conversation.inbox_id, - user_id: conversation.assignee_id, - conversation_id: conversation.id, event_start_time: start_time, - event_end_time: conversation.updated_at + event_end_time: conversation.updated_at, + **base_event_attributes(conversation, from_state: from_state) ) - reporting_event.save! end def create_bot_resolved_event(conversation, reporting_event) @@ -153,6 +142,7 @@ class ReportingEventListener < BaseListener bot_resolved_event = reporting_event.dup bot_resolved_event.name = 'conversation_bot_resolved' + bot_resolved_event.from_state = 'bot_handling' bot_resolved_event.save! end end diff --git a/spec/listeners/reporting_event_listener_spec.rb b/spec/listeners/reporting_event_listener_spec.rb index 782012f31..27b0a5d99 100644 --- a/spec/listeners/reporting_event_listener_spec.rb +++ b/spec/listeners/reporting_event_listener_spec.rb @@ -30,6 +30,9 @@ describe ReportingEventListener do expect(created_event.user_id).to eq(user.id) expect(created_event.event_start_time).to be_within(1.second).of(conversation.created_at) expect(created_event.event_end_time).to be_within(1.second).of(conversation.created_at) + expect(created_event.from_state).to be_nil + expect(created_event.conversation_created_at).to be_within(1.second).of(conversation.created_at) + expect(created_event.channel_type).to eq(inbox.channel_type) end context 'when conversation has no assignee' do @@ -43,6 +46,19 @@ describe ReportingEventListener do expect(created_event.user_id).to be_nil end end + + context 'when conversation has team assigned' do + let(:team) { create(:team, account: account) } + let(:team_conversation) { create(:conversation, account: account, inbox: inbox, assignee: user, team: team) } + + it 'sets team_id on the event' do + event = Events::Base.new('conversation.created', Time.zone.now, conversation: team_conversation) + listener.conversation_created(event) + + created_event = account.reporting_events.find_by(name: 'conversation_created', conversation_id: team_conversation.id) + expect(created_event.team_id).to eq(team.id) + end + end end describe '#conversation_resolved' do @@ -53,6 +69,16 @@ describe ReportingEventListener do expect(account.reporting_events.where(name: 'conversation_resolved').count).to be 1 end + it 'sets from_state to handling' do + event = Events::Base.new('conversation.resolved', Time.zone.now, conversation: conversation) + listener.conversation_resolved(event) + + resolved_event = account.reporting_events.find_by(name: 'conversation_resolved') + expect(resolved_event.from_state).to eq('handling') + expect(resolved_event.conversation_created_at).to be_within(1.second).of(conversation.created_at) + expect(resolved_event.channel_type).to eq(inbox.channel_type) + end + context 'when business hours enabled for inbox' do let(:created_at) { Time.zone.parse('March 20, 2022 00:00') } let(:updated_at) { Time.zone.parse('March 26, 2022 23:59') } @@ -281,6 +307,9 @@ describe ReportingEventListener do listener.conversation_bot_handoff(event) expect(account.reporting_events.where(name: 'conversation_bot_handoff').count).to be 1 + handoff_event = account.reporting_events.find_by(name: 'conversation_bot_handoff') + expect(handoff_event.from_state).to eq('bot_handling') + # add extra handoff event for the same and ensure it's not created event = Events::Base.new('conversation.bot_handoff', Time.zone.now, conversation: conversation) listener.conversation_bot_handoff(event) @@ -307,7 +336,7 @@ describe ReportingEventListener do context 'when conversation is opened for the first time' do let(:new_conversation) { create(:conversation, account: account, inbox: inbox, assignee: user) } - it 'creates conversation_opened event with value 0' do + it 'creates conversation_opened event with value 0 and nil from_state' do expect(account.reporting_events.where(name: 'conversation_opened').count).to be 0 event = Events::Base.new('conversation.opened', Time.zone.now, conversation: new_conversation) listener.conversation_opened(event) @@ -318,6 +347,7 @@ describe ReportingEventListener do expect(opened_event.value_in_business_hours).to eq 0 expect(opened_event.event_start_time).to be_within(1.second).of(new_conversation.created_at) expect(opened_event.event_end_time).to be_within(1.second).of(new_conversation.updated_at) + expect(opened_event.from_state).to be_nil end end @@ -367,6 +397,7 @@ describe ReportingEventListener do expect(reopened_event.inbox_id).to eq(inbox.id) expect(reopened_event.conversation_id).to eq(reopened_conversation.id) expect(reopened_event.user_id).to eq(user.id) + expect(reopened_event.from_state).to eq('resolved') end context 'when business hours enabled for inbox' do