feat(v4): Add API to fetch aggregate reports for inboxes (#10604)

The Inbox Overview section is being updated to offer a more detailed
report, showing an overall view of the account grouped by inboxes. To
view detailed reports and access specific graphs for individual inboxes,
click on the inbox name to navigate to its dedicated report page.

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
This commit is contained in:
Pranav
2024-12-19 14:47:19 -08:00
committed by GitHub
parent eef70b9bd7
commit 4fd9bddb9d
5 changed files with 221 additions and 3 deletions

View File

@@ -0,0 +1,101 @@
require 'rails_helper'
RSpec.describe V2::Reports::InboxSummaryBuilder do
let(:account) { create(:account) }
let(:i1) { create(:inbox, account: account) }
let(:i2) { create(:inbox, account: account) }
let(:params) do
{
business_hours: business_hours,
since: 1.week.ago.beginning_of_day,
until: Time.current.end_of_day
}
end
let(:builder) { described_class.new(account: account, params: params) }
before do
c1 = create(:conversation, account: account, inbox: i1, created_at: 2.days.ago)
c2 = create(:conversation, account: account, inbox: i2, created_at: 1.day.ago)
c2.resolved!
create(:reporting_event, account: account, conversation: c2, inbox: i2, name: 'conversation_resolved', value: 100, value_in_business_hours: 60,
created_at: 1.day.ago)
create(:reporting_event, account: account, conversation: c1, inbox: i1, name: 'first_response', value: 50, value_in_business_hours: 30,
created_at: 1.day.ago)
create(:reporting_event, account: account, conversation: c1, inbox: i1, name: 'reply_time', value: 30, value_in_business_hours: 10,
created_at: 1.day.ago)
create(:reporting_event, account: account, conversation: c1, inbox: i1, name: 'reply_time', value: 40, value_in_business_hours: 20,
created_at: 1.day.ago)
end
describe '#build' do
subject(:report) { builder.build }
context 'when business hours is disabled' do
let(:business_hours) { false }
it 'includes correct stats for each inbox' do
expect(report).to eq(
[
{
id: i1.id,
conversations_count: 1,
resolved_conversations_count: 0,
avg_resolution_time: nil,
avg_first_response_time: 50.0,
avg_reply_time: 35.0
}, {
id: i2.id,
conversations_count: 1,
resolved_conversations_count: 1,
avg_resolution_time: 100.0,
avg_first_response_time: nil,
avg_reply_time: nil
}
]
)
end
end
context 'when business hours is enabled' do
let(:business_hours) { true }
it 'uses business hours values for calculations' do
expect(report).to eq(
[
{
id: i1.id,
conversations_count: 1,
resolved_conversations_count: 0,
avg_resolution_time: nil,
avg_first_response_time: 30.0,
avg_reply_time: 15.0
}, {
id: i2.id,
conversations_count: 1,
resolved_conversations_count: 1,
avg_resolution_time: 60.0,
avg_first_response_time: nil,
avg_reply_time: nil
}
]
)
end
end
context 'when there is no data for an inbox' do
let!(:empty_inbox) { create(:inbox, account: account) }
let(:business_hours) { false }
it 'returns nil values for metrics' do
expect(report).to include(
id: empty_inbox.id,
conversations_count: 0,
resolved_conversations_count: 0,
avg_resolution_time: nil,
avg_first_response_time: nil,
avg_reply_time: nil
)
end
end
end
end

View File

@@ -59,6 +59,57 @@ RSpec.describe 'Summary Reports API', type: :request do
end
end
describe 'GET /api/v2/accounts/:account_id/summary_reports/inbox' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
get "/api/v2/accounts/#{account.id}/summary_reports/inbox"
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:params) do
{
since: start_of_today.to_s,
until: end_of_today.to_s,
business_hours: true
}
end
it 'returns unauthorized for inbox' do
get "/api/v2/accounts/#{account.id}/summary_reports/inbox",
params: params,
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:unauthorized)
end
it 'calls V2::Reports::InboxSummaryBuilder with the right params if the user is an admin' do
inbox_summary_builder = double
allow(V2::Reports::InboxSummaryBuilder).to receive(:new).and_return(inbox_summary_builder)
allow(inbox_summary_builder).to receive(:build).and_return([{ id: 1, conversations_count: 110 }])
get "/api/v2/accounts/#{account.id}/summary_reports/inbox",
params: params,
headers: admin.create_new_auth_token,
as: :json
expect(V2::Reports::InboxSummaryBuilder).to have_received(:new).with(account: account, params: params)
expect(inbox_summary_builder).to have_received(:build)
expect(response).to have_http_status(:success)
json_response = response.parsed_body
expect(json_response.length).to eq(1)
expect(json_response.first['id']).to eq(1)
expect(json_response.first['conversations_count']).to eq(110)
expect(json_response.first['avg_reply_time']).to be_nil
end
end
end
describe 'GET /api/v2/accounts/:account_id/summary_reports/team' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do