iachat/enterprise/app/models/captain/conversation_insight.rb
Rodrigo Borba 87bff8126c feat(captain): add AI reports page with insights generation
Implementa a página Relatórios IA com geração de análises semanais
por IA baseadas nas conversas de cada unidade/caixa de entrada.

Funcionalidades:
- Página /settings/captain/reports com dois tabs (Insights IA / Operacional)
- Botão "Gerar Análise" que enfileira job Sidekiq
- Filtro por unidade ou caixa de entrada
- Exibe insights com status (pendente/processando/concluído/falhou)
- Mostra top_topics, ai_failures e period_summary
- Estado vazio com CTA para gerar primeiro relatório

Backend:
- InsightsController com endpoints index/show/generate
- GenerateInsightsJob que processa conversas com LLM
- ConversationInsightService com chunking e merge inteligente
- Migração para adicionar inbox_id à tabela captain_conversation_insights
- Link sidebar "Relatórios IA" em /settings/captain/reports

Frontend:
- Vuex store captainReports com actions/mutations/getters
- API client CaptainReportsAPI (getInsights, generateInsight)
- i18n en e pt_BR para CAPTAIN_REPORTS.*

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:05:58 -03:00

66 lines
1.8 KiB
Ruby

# == Schema Information
#
# Table name: captain_conversation_insights
#
# id :bigint not null, primary key
# account_id :bigint not null
# captain_unit_id :bigint
# period_start :date not null
# period_end :date not null
# status :string default("pending"), not null
# payload :jsonb
# conversations_count :integer default(0)
# messages_count :integer default(0)
# llm_tokens_used :integer
# generated_at :datetime
# created_at :datetime not null
# updated_at :datetime not null
#
class Captain::ConversationInsight < ApplicationRecord
include Rails.application.routes.url_helpers
STATUSES = %w[pending processing done failed].freeze
belongs_to :account
belongs_to :captain_unit, class_name: 'Captain::Unit', optional: true
belongs_to :inbox, optional: true
validates :period_start, :period_end, :status, presence: true
validates :status, inclusion: { in: STATUSES }
scope :done, -> { where(status: 'done') }
scope :for_unit, ->(unit_id) { where(captain_unit_id: unit_id) }
scope :for_inbox, ->(inbox_id) { where(inbox_id: inbox_id) }
scope :for_period, ->(start_date, end_date) { where(period_start: start_date, period_end: end_date) }
def mark_processing!
update!(status: 'processing')
end
def mark_done!(payload, tokens_used: nil)
update!(
status: 'done',
payload: payload,
llm_tokens_used: tokens_used,
generated_at: Time.current
)
end
def mark_failed!
update!(status: 'failed')
end
def pending?
status == 'pending'
end
def processing?
status == 'processing'
end
def done?
status == 'done'
end
end