49 lines
1.8 KiB
Ruby
49 lines
1.8 KiB
Ruby
# app/jobs/disparar_eventos_agendados_job.rb
|
|
#
|
|
# Varre os eventos de gatilho `agendado` e dispara os que venceram. Roda de hora
|
|
# em hora pelo cron do container (config/schedule.rb).
|
|
#
|
|
# POR QUE DE HORA EM HORA e não "no horário exato": o evento guarda hora e
|
|
# frequência escolhidas na tela, e essas podem mudar a qualquer momento — reler
|
|
# o crontab a cada edição seria acoplar a UI ao cron do sistema. Uma varredura
|
|
# horária resolve com uma linha fixa no schedule, e `EventoNotificacao#vencido?`
|
|
# garante que cada evento dispara UMA vez por dia (ele grava ultimo_disparo_em).
|
|
#
|
|
# PERÍODO do resumo — recortes FECHADOS, para o número não mudar depois de
|
|
# enviado:
|
|
# diária → o dia anterior
|
|
# semanal → os 7 dias anteriores
|
|
class DispararEventosAgendadosJob < ApplicationJob
|
|
queue_as :default
|
|
|
|
def perform(agora = Time.current)
|
|
EventoNotificacao.ativos.where(gatilho: 'agendado').find_each do |evento|
|
|
next unless evento.vencido?(agora)
|
|
|
|
inicio, fim = janela(evento, agora)
|
|
resumo = Analytics::ResumoOperacao.new(inicio: inicio, fim: fim)
|
|
|
|
# Resumo zerado (feriado, fim de semana) só treinaria o leitor a ignorar a
|
|
# mensagem. Marca como disparado assim mesmo, senão tentaria de hora em
|
|
# hora até o dia virar.
|
|
if resumo.vazio?
|
|
evento.update_columns(ultimo_disparo_em: agora)
|
|
Rails.logger.info("[Agendados] #{evento.chave}: período sem movimento, nada enviado")
|
|
next
|
|
end
|
|
|
|
Notificacao::Gatilhos.resumo_agendado(evento, inicio: inicio, fim: fim)
|
|
evento.update_columns(ultimo_disparo_em: agora)
|
|
end
|
|
rescue StandardError => e
|
|
Rails.logger.error("[Agendados] #{e.class}: #{e.message}")
|
|
end
|
|
|
|
private
|
|
|
|
def janela(evento, agora)
|
|
hoje = agora.to_date
|
|
evento.frequencia == 'semanal' ? [hoje - 7, hoje - 1] : [hoje - 1, hoje - 1]
|
|
end
|
|
end
|