feat: API to download breached conversations (#9150)
* feat: add download conversations endpoint * feat: template for conversation list download * feat: setup download API and tests * chore: revert formatting change * feat: rename download method * feat: rename template * feat: include sla_policy table in download query * refactor: add nil safety to assignee * chore: Update en.yml * fix: remove applied_sla relation
This commit is contained in:
@@ -106,6 +106,15 @@ en:
|
||||
avg_resolution_time: Avg resolution time
|
||||
conversation_traffic_csv:
|
||||
timezone: Timezone
|
||||
sla_csv:
|
||||
conversation_id: Conversation ID
|
||||
sla_policy_breached: SLA Policy
|
||||
assignee: Assignee
|
||||
team: Team
|
||||
inbox: Inbox
|
||||
labels: Labels
|
||||
conversation_link: Link to the Conversation
|
||||
breached_events: Breached Events
|
||||
default_group_by: day
|
||||
csat:
|
||||
headers:
|
||||
|
||||
@@ -147,6 +147,7 @@ Rails.application.routes.draw do
|
||||
resources :applied_slas, only: [:index] do
|
||||
collection do
|
||||
get :metrics
|
||||
get :download
|
||||
end
|
||||
end
|
||||
resources :custom_attribute_definitions, only: [:index, :show, :create, :update, :destroy]
|
||||
|
||||
@@ -4,7 +4,7 @@ class Api::V1::Accounts::AppliedSlasController < Api::V1::Accounts::EnterpriseAc
|
||||
|
||||
RESULTS_PER_PAGE = 25
|
||||
|
||||
before_action :set_applied_slas, only: [:index, :metrics]
|
||||
before_action :set_applied_slas, only: [:index, :metrics, :download]
|
||||
before_action :set_current_page, only: [:index]
|
||||
before_action :paginate_slas, only: [:index]
|
||||
before_action :check_admin_authorization?
|
||||
@@ -19,8 +19,22 @@ class Api::V1::Accounts::AppliedSlasController < Api::V1::Accounts::EnterpriseAc
|
||||
@hit_rate = hit_rate
|
||||
end
|
||||
|
||||
def download
|
||||
@breached_slas = breached_slas
|
||||
|
||||
response.headers['Content-Type'] = 'text/csv'
|
||||
response.headers['Content-Disposition'] = 'attachment; filename=breached_conversation.csv'
|
||||
render layout: false, formats: [:csv]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def breached_slas
|
||||
@applied_slas.includes(:sla_policy).joins(:conversation)
|
||||
.where.not(conversations: { status: :resolved })
|
||||
.where(applied_slas: { sla_status: :missed })
|
||||
end
|
||||
|
||||
def total_applied_slas
|
||||
@total_applied_slas ||= @applied_slas.count
|
||||
end
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<% headers = [
|
||||
I18n.t('reports.sla_csv.conversation_id'),
|
||||
I18n.t('reports.sla_csv.sla_policy_breached'),
|
||||
I18n.t('reports.sla_csv.assignee'),
|
||||
I18n.t('reports.sla_csv.team'),
|
||||
I18n.t('reports.sla_csv.inbox'),
|
||||
I18n.t('reports.sla_csv.labels'),
|
||||
I18n.t('reports.sla_csv.conversation_link'),
|
||||
I18n.t('reports.sla_csv.breached_events')
|
||||
] %>
|
||||
<%= CSV.generate_line headers %>
|
||||
|
||||
<% @breached_slas.each do |sla| %>
|
||||
<% breached_events = sla.sla_events.map(&:event_type).join(', ') %>
|
||||
<% conversation = sla.conversation %>
|
||||
<%= CSV.generate_line([
|
||||
conversation.display_id,
|
||||
sla.sla_policy.name,
|
||||
conversation.assignee&.name,
|
||||
conversation.team&.name,
|
||||
conversation.inbox&.name,
|
||||
conversation.cached_label_list,
|
||||
app_account_conversation_url(account_id: conversation.account_id, id: conversation.display_id),
|
||||
breached_events
|
||||
]) %>
|
||||
<% end %>
|
||||
@@ -104,6 +104,36 @@ RSpec.describe 'Applied SLAs API', type: :request do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/applied_slas/download' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
get "/api/v1/accounts/#{account.id}/applied_slas/download"
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
it 'returns a CSV file with breached conversations' do
|
||||
create(:applied_sla, sla_policy: sla_policy1, conversation: conversation1, sla_status: 'missed')
|
||||
create(:applied_sla, sla_policy: sla_policy1, conversation: conversation2, sla_status: 'missed')
|
||||
conversation1.update(status: 'open')
|
||||
conversation2.update(status: 'resolved')
|
||||
|
||||
get "/api/v1/accounts/#{account.id}/applied_slas/download",
|
||||
headers: administrator.create_new_auth_token
|
||||
|
||||
expect(response).to have_http_status(:success)
|
||||
expect(response.headers['Content-Type']).to eq('text/csv')
|
||||
expect(response.headers['Content-Disposition']).to include('attachment; filename=breached_conversation.csv')
|
||||
|
||||
csv_data = CSV.parse(response.body)
|
||||
csv_data.reject! { |row| row.all?(&:nil?) }
|
||||
expect(csv_data.size).to eq(2)
|
||||
expect(csv_data[1][0].to_i).to eq(conversation1.display_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/{account.id}/applied_slas' do
|
||||
context 'when it is an unauthenticated user' do
|
||||
it 'returns unauthorized' do
|
||||
|
||||
Reference in New Issue
Block a user