feat: Add APIs

This commit is contained in:
Muhsin
2026-01-29 19:04:17 +04:00
parent 9238b4cc92
commit 49acab85f5
13 changed files with 57 additions and 4 deletions
@@ -8,13 +8,17 @@ class V2::Reports::AgentSummaryBuilder < V2::Reports::BaseSummaryBuilder
private
attr_reader :conversations_count, :resolved_count,
attr_reader :conversations_count, :outgoing_messages_count, :resolved_count,
:avg_resolution_time, :avg_first_response_time, :avg_reply_time
def fetch_conversations_count
account.conversations.where(created_at: range).group('assignee_id').count
end
def fetch_outgoing_messages_count
account.messages.unscope(:order).where(created_at: range, message_type: :outgoing).joins(:conversation).group('conversations.assignee_id').count
end
def prepare_report
account.account_users.map do |account_user|
build_agent_stats(account_user)
@@ -26,6 +30,7 @@ class V2::Reports::AgentSummaryBuilder < V2::Reports::BaseSummaryBuilder
{
id: user_id,
conversations_count: conversations_count[user_id] || 0,
outgoing_messages_count: outgoing_messages_count[user_id] || 0,
resolved_conversations_count: resolved_count[user_id] || 0,
avg_resolution_time: avg_resolution_time[user_id],
avg_first_response_time: avg_first_response_time[user_id],
@@ -10,6 +10,7 @@ class V2::Reports::BaseSummaryBuilder
def load_data
@conversations_count = fetch_conversations_count
@outgoing_messages_count = fetch_outgoing_messages_count
load_reporting_events_data
end
@@ -42,6 +43,10 @@ class V2::Reports::BaseSummaryBuilder
# Override this method
end
def fetch_outgoing_messages_count
# Override this method
end
def group_by_key
# Override this method
end
@@ -8,11 +8,12 @@ class V2::Reports::InboxSummaryBuilder < V2::Reports::BaseSummaryBuilder
private
attr_reader :conversations_count, :resolved_count,
attr_reader :conversations_count, :outgoing_messages_count, :resolved_count,
:avg_resolution_time, :avg_first_response_time, :avg_reply_time
def load_data
@conversations_count = fetch_conversations_count
@outgoing_messages_count = fetch_outgoing_messages_count
load_reporting_events_data
end
@@ -20,6 +21,10 @@ class V2::Reports::InboxSummaryBuilder < V2::Reports::BaseSummaryBuilder
account.conversations.where(created_at: range).group(group_by_key).count
end
def fetch_outgoing_messages_count
account.messages.unscope(:order).where(created_at: range, message_type: :outgoing).group(:inbox_id).count
end
def prepare_report
account.inboxes.map do |inbox|
build_inbox_stats(inbox)
@@ -30,6 +35,7 @@ class V2::Reports::InboxSummaryBuilder < V2::Reports::BaseSummaryBuilder
{
id: inbox.id,
conversations_count: conversations_count[inbox.id] || 0,
outgoing_messages_count: outgoing_messages_count[inbox.id] || 0,
resolved_conversations_count: resolved_count[inbox.id] || 0,
avg_resolution_time: avg_resolution_time[inbox.id],
avg_first_response_time: avg_first_response_time[inbox.id],
@@ -28,6 +28,7 @@ class V2::Reports::LabelSummaryBuilder < V2::Reports::BaseSummaryBuilder
{
conversation_counts: fetch_conversation_counts(conversation_filter),
outgoing_messages_counts: fetch_outgoing_messages_count,
resolved_counts: fetch_resolved_counts,
resolution_metrics: fetch_metrics(conversation_filter, 'conversation_resolved', use_business_hours),
first_response_metrics: fetch_metrics(conversation_filter, 'first_response', use_business_hours),
@@ -40,6 +41,7 @@ class V2::Reports::LabelSummaryBuilder < V2::Reports::BaseSummaryBuilder
id: label.id,
name: label.title,
conversations_count: report_data[:conversation_counts][label.title] || 0,
outgoing_messages_count: report_data[:outgoing_messages_counts][label.title] || 0,
avg_resolution_time: report_data[:resolution_metrics][label.title] || 0,
avg_first_response_time: report_data[:first_response_metrics][label.title] || 0,
avg_reply_time: report_data[:reply_metrics][label.title] || 0,
@@ -62,6 +64,19 @@ class V2::Reports::LabelSummaryBuilder < V2::Reports::BaseSummaryBuilder
fetch_counts(conversation_filter)
end
def fetch_outgoing_messages_count
Message.unscope(:order)
.joins(conversation: { taggings: :tag })
.where(
account_id: account.id,
created_at: range,
message_type: :outgoing,
taggings: { taggable_type: 'Conversation', context: 'labels' }
)
.group('tags.name')
.count
end
def fetch_resolved_counts
# Count resolution events, not conversations currently in resolved status
# Filter by reporting_event.created_at, not conversation.created_at
@@ -3,13 +3,17 @@ class V2::Reports::TeamSummaryBuilder < V2::Reports::BaseSummaryBuilder
private
attr_reader :conversations_count, :resolved_count,
attr_reader :conversations_count, :outgoing_messages_count, :resolved_count,
:avg_resolution_time, :avg_first_response_time, :avg_reply_time
def fetch_conversations_count
account.conversations.where(created_at: range).group(:team_id).count
end
def fetch_outgoing_messages_count
account.messages.unscope(:order).where(created_at: range, message_type: :outgoing).joins(:conversation).group('conversations.team_id').count
end
def reporting_events
@reporting_events ||= account.reporting_events.where(created_at: range).joins(:conversation)
end
@@ -24,6 +28,7 @@ class V2::Reports::TeamSummaryBuilder < V2::Reports::BaseSummaryBuilder
{
id: team.id,
conversations_count: conversations_count[team.id] || 0,
outgoing_messages_count: outgoing_messages_count[team.id] || 0,
resolved_conversations_count: resolved_count[team.id] || 0,
avg_resolution_time: avg_resolution_time[team.id],
avg_first_response_time: avg_first_response_time[team.id],
@@ -72,6 +72,7 @@ module Api::V2::Accounts::ReportsHelper
def generate_readable_report_metrics(report)
[
report[:conversations_count],
report[:outgoing_messages_count],
Reports::TimeFormatPresenter.new(report[:avg_first_response_time]).format,
Reports::TimeFormatPresenter.new(report[:avg_resolution_time]).format,
Reports::TimeFormatPresenter.new(report[:avg_reply_time]).format,
@@ -622,6 +622,7 @@
"AVG_FIRST_RESPONSE_TIME": "Avg. First Response Time",
"AVG_REPLY_TIME": "Avg. Customer Waiting Time",
"RESOLUTION_COUNT": "Resolution Count",
"CONVERSATIONS": "No. of conversations"
"CONVERSATIONS": "No. of conversations",
"OUTGOING_MESSAGES": "No. of outgoing messages"
}
}
@@ -70,6 +70,11 @@ const columns = computed(() => [
width: 200,
cell: defaulSpanRender,
}),
columnHelper.accessor('outgoingMessagesCount', {
header: t('SUMMARY_REPORTS.OUTGOING_MESSAGES'),
width: 200,
cell: defaulSpanRender,
}),
columnHelper.accessor('avgFirstResponseTime', {
header: t('SUMMARY_REPORTS.AVG_FIRST_RESPONSE_TIME'),
width: 200,
@@ -101,6 +106,7 @@ const tableData = computed(() =>
const rowMetrics = getMetrics(row.id);
const {
conversationsCount,
outgoingMessagesCount,
avgFirstResponseTime,
avgResolutionTime,
avgReplyTime,
@@ -112,6 +118,7 @@ const tableData = computed(() =>
name: row.name ?? row.title,
type: props.type,
conversationsCount: renderCount(conversationsCount),
outgoingMessagesCount: renderCount(outgoingMessagesCount),
avgFirstResponseTime: renderAvgTime(avgFirstResponseTime),
avgReplyTime: renderAvgTime(avgReplyTime),
avgResolutionTime: renderAvgTime(avgResolutionTime),
@@ -3,6 +3,7 @@
<% headers = [
I18n.t('reports.agent_csv.agent_name'),
I18n.t('reports.agent_csv.conversations_count'),
I18n.t('reports.agent_csv.outgoing_messages_count'),
I18n.t('reports.agent_csv.avg_first_response_time'),
I18n.t('reports.agent_csv.avg_resolution_time'),
I18n.t('reports.agent_csv.avg_customer_waiting_time'),
@@ -4,6 +4,7 @@
I18n.t('reports.inbox_csv.inbox_name'),
I18n.t('reports.inbox_csv.inbox_type'),
I18n.t('reports.inbox_csv.conversations_count'),
I18n.t('reports.inbox_csv.outgoing_messages_count'),
I18n.t('reports.inbox_csv.avg_first_response_time'),
I18n.t('reports.inbox_csv.avg_resolution_time')
]
@@ -3,6 +3,7 @@
<% headers = [
I18n.t('reports.label_csv.label_title'),
I18n.t('reports.label_csv.conversations_count'),
I18n.t('reports.label_csv.outgoing_messages_count'),
I18n.t('reports.label_csv.avg_first_response_time'),
I18n.t('reports.label_csv.avg_resolution_time'),
I18n.t('reports.label_csv.avg_reply_time'),
@@ -3,6 +3,7 @@
<% headers = [
I18n.t('reports.team_csv.team_name'),
I18n.t('reports.team_csv.conversations_count'),
I18n.t('reports.team_csv.outgoing_messages_count'),
I18n.t('reports.team_csv.avg_first_response_time'),
I18n.t('reports.team_csv.avg_resolution_time'),
I18n.t('reports.team_csv.avg_customer_waiting_time'),
+4
View File
@@ -148,6 +148,7 @@ en:
agent_csv:
agent_name: Agent name
conversations_count: Assigned conversations
outgoing_messages_count: Outgoing messages count
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
resolution_count: Resolution Count
@@ -156,11 +157,13 @@ en:
inbox_name: Inbox name
inbox_type: Inbox type
conversations_count: No. of conversations
outgoing_messages_count: Outgoing messages count
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
label_csv:
label_title: Label
conversations_count: No. of conversations
outgoing_messages_count: Outgoing messages count
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
avg_reply_time: Avg reply time
@@ -168,6 +171,7 @@ en:
team_csv:
team_name: Team name
conversations_count: Conversations count
outgoing_messages_count: Outgoing messages count
avg_first_response_time: Avg first response time
avg_resolution_time: Avg resolution time
resolution_count: Resolution Count