iachat/enterprise/app/jobs/captain/reports/generate_insights_job.rb

71 lines
2.5 KiB
Ruby

class Captain::Reports::GenerateInsightsJob < ApplicationJob
queue_as :default
# Gera insights de IA para uma unidade ou inbox específica em um período.
# Pode ser disparado on-demand (botão na UI) ou pelo WeeklyInsightsJob.
def perform(account_id, unit_id, period_start, period_end, inbox_id = nil)
# Ensure dates are Date objects as they might be serialized as strings in Sidekiq
period_start = period_start.is_a?(String) ? Date.parse(period_start) : period_start
period_end = period_end.is_a?(String) ? Date.parse(period_end) : period_end
account = Account.find_by(id: account_id)
return unless account
unit = account.captain_units.find_by(id: unit_id) if unit_id
inbox = account.inboxes.find_by(id: inbox_id) if inbox_id
insight = find_or_create_insight(account_id, unit_id, inbox_id, period_start, period_end)
return if insight.processing? || insight.done?
insight.mark_processing!
run_analysis(account, unit, inbox, insight, period_start, period_end)
rescue StandardError => e
Rails.logger.error "[Captain::Reports::GenerateInsightsJob] Error: #{e.message}\n#{e.backtrace&.first(5)&.join("\n")}"
insight&.mark_failed!
end
private
def find_or_create_insight(account_id, unit_id, inbox_id, period_start, period_end)
insight = Captain::ConversationInsight.find_or_initialize_by(
account_id: account_id,
captain_unit_id: unit_id,
inbox_id: inbox_id,
period_start: period_start,
period_end: period_end
)
insight.save! if insight.new_record?
insight
end
def run_analysis(account, unit, inbox, insight, period_start, period_end)
conversations = fetch_conversations(account, unit, inbox, period_start, period_end)
insight.update!(conversations_count: conversations.count)
payload = Captain::Llm::ConversationInsightService.new(
account: account,
unit: unit,
inbox: inbox,
conversations: conversations
).analyze
insight.update!(messages_count: conversations.sum { |conv| conv.messages.count })
insight.mark_done!(payload)
end
def fetch_conversations(account, unit, inbox, period_start, period_end)
scope = account.conversations
.where(created_at: period_start.beginning_of_day..period_end.end_of_day)
.includes(:messages)
if inbox
scope = scope.where(inbox_id: inbox.id)
elsif unit
inbox_ids = unit.inboxes.pluck(:id)
scope = scope.where(inbox_id: inbox_ids) if inbox_ids.any?
end
scope.to_a
end
end