- Adiciona check_in_at/duration_hours ao schema do tool CreateReservationIntent para que a IA capture o horário EXATO de chegada informado pelo cliente - Cria captain_notification_templates: label, content, timing_minutes, timing_direction (before/after), active, position - Implementa SendNotificationService com interpolação de variáveis (guest_name, check_in_time, check_out_time, suite_name, unit_name) - Implementa NotificationScannerJob (Sidekiq-cron a cada 5min) com janela de tolerância de ±5min e idempotência via metadata JSONB - API REST: /captain/units/:unit_id/notification_templates (CRUD) - Store Vuex captainNotificationTemplates + API client - UI: página de gestão de templates com editor inline e botão '+' - Configura rota captain_settings_notifications - i18n PT/EN para todas as strings novas - Rubocop e ESLint: zero offenses
55 lines
1.6 KiB
Ruby
55 lines
1.6 KiB
Ruby
class Captain::Notifications::SendNotificationService
|
|
VARIABLES = {
|
|
'{{guest_name}}' => ->(r) { r.contact.name.to_s },
|
|
'{{check_in_time}}' => ->(r) { r.check_in_at.strftime('%H:%M') },
|
|
'{{check_out_time}}' => ->(r) { r.check_out_at.strftime('%H:%M') },
|
|
'{{suite_name}}' => ->(r) { r.suite_identifier.to_s },
|
|
'{{unit_name}}' => ->(r) { r.unit&.name.to_s }
|
|
}.freeze
|
|
|
|
def initialize(reservation, template)
|
|
@reservation = reservation
|
|
@template = template
|
|
end
|
|
|
|
def perform
|
|
return unless @reservation.conversation_id?
|
|
|
|
rendered = render_content
|
|
send_message(rendered)
|
|
mark_template_sent
|
|
rescue StandardError => e
|
|
Rails.logger.error "[SendNotificationService] Failed for reservation #{@reservation.id}, template #{@template.id}: #{e.message}"
|
|
end
|
|
|
|
private
|
|
|
|
def render_content
|
|
content = @template.content.dup
|
|
VARIABLES.each do |placeholder, resolver|
|
|
content.gsub!(placeholder, resolver.call(@reservation))
|
|
end
|
|
content
|
|
end
|
|
|
|
def send_message(content)
|
|
conversation = @reservation.conversation
|
|
assistant = conversation.inbox&.captain_inbox&.assistant
|
|
|
|
conversation.messages.create!(
|
|
content: content,
|
|
message_type: :outgoing,
|
|
account: conversation.account,
|
|
inbox: conversation.inbox,
|
|
sender: assistant
|
|
)
|
|
end
|
|
|
|
def mark_template_sent
|
|
current_notified = @reservation.metadata.to_h.fetch('notified_templates', [])
|
|
updated = (current_notified + [@template.id]).uniq
|
|
new_metadata = @reservation.metadata.to_h.merge('notified_templates' => updated)
|
|
@reservation.update!(metadata: new_metadata)
|
|
end
|
|
end
|