Fix(Captain): Correção na geração de relatórios de IA e adição do status Confirmada nas Reservas

This commit is contained in:
Rodrigo Borba 2026-03-01 15:40:10 -03:00
parent e8b51109cb
commit dc3d1bbcf7
9 changed files with 36 additions and 16 deletions

View File

@ -1,6 +1,6 @@
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '3.4.4' ruby '>= 3.4.4'
##-- base gems for rails --## ##-- base gems for rails --##
gem 'rack-cors', '2.0.0', require: 'rack/cors' gem 'rack-cors', '2.0.0', require: 'rack/cors'

View File

@ -32,6 +32,10 @@ class Api::V1::Accounts::Captain::Reports::InsightsController < Api::V1::Account
unit_id = params[:unit_id].present? ? params[:unit_id].to_i : nil unit_id = params[:unit_id].present? ? params[:unit_id].to_i : nil
inbox_id = params[:inbox_id].present? ? params[:inbox_id].to_i : nil inbox_id = params[:inbox_id].present? ? params[:inbox_id].to_i : nil
# Log parameters to help debugging
Rails.logger.info '[Captain::Reports::InsightsController] Generating insight ' \
"for Unit: #{unit_id}, Inbox: #{inbox_id}, Period: #{period_start} to #{period_end}"
enqueue_insight(unit_id, inbox_id, period_start, period_end) enqueue_insight(unit_id, inbox_id, period_start, period_end)
end end
# rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/AbcSize
@ -69,8 +73,10 @@ class Api::V1::Accounts::Captain::Reports::InsightsController < Api::V1::Account
end end
def parse_date(param, default) def parse_date(param, default)
param.present? ? Date.parse(param) : default return default if param.blank?
rescue ArgumentError
Date.parse(param.to_s)
rescue ArgumentError, TypeError
default default
end end

View File

@ -54,10 +54,12 @@
"ACTIONS": "Actions" "ACTIONS": "Actions"
}, },
"STATUS": { "STATUS": {
"DRAFT": "Draft", "SCHEDULED": "Scheduled",
"PENDING_PAYMENT": "Awaiting payment", "PENDING_PAYMENT": "Awaiting payment",
"CONFIRMED": "Confirmed", "ACTIVE": "Active",
"CANCELLED": "Cancelled" "COMPLETED": "Completed",
"CANCELLED": "Cancelled",
"DRAFT": "Draft"
}, },
"ACTIONS": { "ACTIONS": {
"OPEN_CONVERSATION": "Open conversation", "OPEN_CONVERSATION": "Open conversation",

View File

@ -54,10 +54,13 @@
"ACTIONS": "Ações" "ACTIONS": "Ações"
}, },
"STATUS": { "STATUS": {
"DRAFT": "Rascunho", "SCHEDULED": "Agendado",
"PENDING_PAYMENT": "Aguardando pagamento", "PENDING_PAYMENT": "Aguardando pagamento",
"ACTIVE": "Ativa",
"CONFIRMED": "Confirmada", "CONFIRMED": "Confirmada",
"CANCELLED": "Cancelada" "COMPLETED": "Concluída",
"CANCELLED": "Cancelada",
"DRAFT": "Rascunho"
}, },
"ACTIONS": { "ACTIONS": {
"OPEN_CONVERSATION": "Abrir conversa", "OPEN_CONVERSATION": "Abrir conversa",

View File

@ -76,8 +76,8 @@ const statusOptions = computed(() => [
value: 'pending_payment', value: 'pending_payment',
}, },
{ {
label: t('CAPTAIN_RESERVATIONS.STATUS.ACTIVE'), label: t('CAPTAIN_RESERVATIONS.STATUS.CONFIRMED'),
value: 'active', value: 'confirmed',
}, },
]); ]);

View File

@ -33,13 +33,16 @@ const onFilterChange = async event => {
}; };
const onGenerateInsight = async () => { const onGenerateInsight = async () => {
if (uiFlags.value.isGenerating) return;
try { try {
await store.dispatch('captainReports/generateInsight', { await store.dispatch('captainReports/generateInsight', {
inbox_id: selectedInboxId.value, inbox_id: selectedInboxId.value,
}); });
useAlert(t('CAPTAIN_REPORTS.GENERATE.SUCCESS')); useAlert(t('CAPTAIN_REPORTS.GENERATE.SUCCESS'));
} catch { } catch (error) {
useAlert(t('CAPTAIN_REPORTS.GENERATE.ERROR')); const errorMessage =
error?.response?.data?.message || t('CAPTAIN_REPORTS.GENERATE.ERROR');
useAlert(errorMessage);
} }
}; };
@ -103,6 +106,7 @@ const periodLabel = insight =>
<Button <Button
:label="t('CAPTAIN_REPORTS.GENERATE.BUTTON')" :label="t('CAPTAIN_REPORTS.GENERATE.BUTTON')"
icon="i-lucide-sparkles" icon="i-lucide-sparkles"
color="blue"
:is-loading="uiFlags.isGenerating" :is-loading="uiFlags.isGenerating"
@click="onGenerateInsight" @click="onGenerateInsight"
/> />
@ -240,6 +244,7 @@ const periodLabel = insight =>
<Button <Button
:label="t('CAPTAIN_REPORTS.GENERATE.BUTTON')" :label="t('CAPTAIN_REPORTS.GENERATE.BUTTON')"
icon="i-lucide-sparkles" icon="i-lucide-sparkles"
color="blue"
:is-loading="uiFlags.isGenerating" :is-loading="uiFlags.isGenerating"
@click="onGenerateInsight" @click="onGenerateInsight"
/> />

View File

@ -1,4 +1,4 @@
import * as MutationTypes from '../mutation-types'; import MutationTypes from '../mutation-types';
import CaptainReportsAPI from '../../api/captain/reports'; import CaptainReportsAPI from '../../api/captain/reports';
export const getters = { export const getters = {

View File

@ -4,6 +4,10 @@ class Captain::Reports::GenerateInsightsJob < ApplicationJob
# Gera insights de IA para uma unidade ou inbox específica em um período. # 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. # 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) 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) account = Account.find_by(id: account_id)
return unless account return unless account

View File

@ -60,11 +60,11 @@ class Captain::Reservation < ApplicationRecord
belongs_to :contact belongs_to :contact
belongs_to :contact_inbox belongs_to :contact_inbox
belongs_to :conversation, class_name: '::Conversation', optional: true belongs_to :conversation, class_name: '::Conversation', optional: true
belongs_to :brand, class_name: 'Captain::Brand', foreign_key: 'captain_brand_id', optional: true belongs_to :brand, class_name: 'Captain::Brand', foreign_key: 'captain_brand_id', optional: true, inverse_of: false
belongs_to :unit, class_name: 'Captain::Unit', foreign_key: 'captain_unit_id', optional: true belongs_to :unit, class_name: 'Captain::Unit', foreign_key: 'captain_unit_id', optional: true, inverse_of: false
belongs_to :current_pix_charge, class_name: 'Captain::PixCharge', optional: true belongs_to :current_pix_charge, class_name: 'Captain::PixCharge', optional: true
enum status: { scheduled: 0, active: 1, completed: 2, cancelled: 3, pending_payment: 4, draft: 5 } enum status: { scheduled: 0, active: 1, completed: 2, cancelled: 3, pending_payment: 4, draft: 5, confirmed: 6 }
validates :suite_identifier, presence: true validates :suite_identifier, presence: true
validates :check_in_at, presence: true validates :check_in_at, presence: true