Implantação da geração de mensagem de forma livre e mudança na engine de mensagem
This commit is contained in:
133
app/services/notificacao/gatilhos.rb
Normal file
133
app/services/notificacao/gatilhos.rb
Normal file
@@ -0,0 +1,133 @@
|
||||
# app/services/notificacao/gatilhos.rb
|
||||
#
|
||||
# Os pontos do sistema que DISPARAM um evento de notificação. Cada método monta
|
||||
# o contexto das {{variaveis}} daquele gatilho e entrega ao Despachante.
|
||||
#
|
||||
# Existe para que o código de negócio (consolidação, edição de lançamento, jobs)
|
||||
# tenha UMA linha de chamada, sem saber de template, canal ou destinatário — e
|
||||
# para que a lista de variáveis que o editor oferece (Notificacao::Variaveis)
|
||||
# tenha um par exato aqui. Variável anunciada na tela e nunca preenchida sai como
|
||||
# vazio na mensagem, o que é pior do que não existir.
|
||||
#
|
||||
# NADA aqui levanta: uma notificação não pode derrubar um fechamento nem uma
|
||||
# edição de lançamento. O Despachante já engole, e os métodos que montam o
|
||||
# contexto também.
|
||||
module Notificacao
|
||||
module Gatilhos
|
||||
module_function
|
||||
|
||||
# Valor do motorista mudou DEPOIS do fechamento (lançamento editado,
|
||||
# desconto aplicado, pilar remarcado). Em rascunho o valor muda a cada
|
||||
# clique do wizard — avisar ali seria spam, não informação.
|
||||
def valor_alterado(consolidacao, consolidacao_motorista, anterior:)
|
||||
return unless consolidacao.finalizada?
|
||||
|
||||
atual = consolidacao_motorista.valor_total.to_f
|
||||
return if anterior.to_f == atual
|
||||
|
||||
Despachante.disparar(
|
||||
chave: 'valor_alterado',
|
||||
dados: Variaveis.comuns_reais.merge(
|
||||
'motorista' => consolidacao_motorista.motorista_nome,
|
||||
'consolidacao' => consolidacao.nome,
|
||||
'periodo' => periodo(consolidacao.data_inicio, consolidacao.data_fim),
|
||||
'valor' => moeda(atual),
|
||||
'entregas' => contar_entregas(consolidacao, consolidacao_motorista).to_s,
|
||||
'link_painel' => link_painel,
|
||||
'o_que_mudou' => "Valor passou de #{moeda(anterior)} para #{moeda(atual)}"
|
||||
),
|
||||
assunto: "Valor alterado — #{consolidacao_motorista.motorista_nome}",
|
||||
corpo: "⚠️ O valor de #{consolidacao_motorista.motorista_nome} em #{consolidacao.nome} " \
|
||||
"passou de #{moeda(anterior)} para #{moeda(atual)}.",
|
||||
# O próprio motorista é parte interessada: o valor DELE mudou depois de
|
||||
# fechado. Fica sob o `notificar_envolvido` do evento, então o ADM pode
|
||||
# desligar sem perder o aviso à diretoria.
|
||||
envolvido: motorista_usuario(consolidacao_motorista)
|
||||
)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("[Gatilhos] valor_alterado: #{e.class}: #{e.message}")
|
||||
end
|
||||
|
||||
# Dados da operação mudaram. Duas origens, os dois caminham para cá:
|
||||
# - edição de lançamento no SimpliRoute feita por dentro do sistema;
|
||||
# - varredura periódica que compara o espelho com o retrato anterior
|
||||
# (DetectarMudancasOperacaoJob) — é por onde chega a maioria, já que o
|
||||
# espelho sincroniza mudanças feitas fora daqui.
|
||||
def operacao_alterada(operacao:, o_que_mudou:, nf: nil)
|
||||
Despachante.disparar(
|
||||
chave: 'operacao_alterada',
|
||||
dados: Variaveis.comuns_reais.merge(
|
||||
'operacao' => operacao.to_s,
|
||||
'o_que_mudou' => o_que_mudou.to_s,
|
||||
'nf' => nf.to_s
|
||||
),
|
||||
assunto: "Alteração na operação #{operacao}",
|
||||
corpo: "🔄 #{operacao}: #{o_que_mudou}#{nf.present? ? " (NF #{nf})" : ''}"
|
||||
)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("[Gatilhos] operacao_alterada: #{e.class}: #{e.message}")
|
||||
end
|
||||
|
||||
# Resumo periódico de um evento `agendado`.
|
||||
def resumo_agendado(evento, inicio:, fim:)
|
||||
numeros = Analytics::ResumoOperacao.new(inicio: inicio, fim: fim).numeros
|
||||
|
||||
Despachante.disparar(
|
||||
chave: evento.chave,
|
||||
dados: Variaveis.comuns_reais.merge(numeros).merge(
|
||||
'periodo' => periodo(inicio, fim)
|
||||
),
|
||||
assunto: "Resumo da operação — #{periodo(inicio, fim)}",
|
||||
corpo: corpo_resumo(numeros, inicio, fim)
|
||||
)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("[Gatilhos] resumo_agendado #{evento.chave}: #{e.class}: #{e.message}")
|
||||
end
|
||||
|
||||
# ── Auxiliares ─────────────────────────────────────────────
|
||||
|
||||
def corpo_resumo(numeros, inicio, fim)
|
||||
"📊 Resumo da operação — #{periodo(inicio, fim)}\n" \
|
||||
"• Entregues: #{numeros['entregues']}\n" \
|
||||
"• Não entregues: #{numeros['recusas']}\n" \
|
||||
"• Em aberto: #{numeros['pendentes']}\n" \
|
||||
"• Retentativas: #{numeros['retentativas']}\n" \
|
||||
"• Notas fora da operação: #{numeros['fora_operacao']}"
|
||||
end
|
||||
|
||||
def periodo(inicio, fim)
|
||||
"#{inicio&.strftime('%d/%m/%Y')} a #{fim&.strftime('%d/%m/%Y')}"
|
||||
end
|
||||
|
||||
def link_painel
|
||||
"https://#{ENV.fetch('APP_HOST', 'localhost:3000')}/motorista"
|
||||
end
|
||||
|
||||
# Mesma busca do NotificacaoService (casa pelo nome, que é o que a
|
||||
# consolidação guarda). Só roda em consolidação finalizada, então o custo
|
||||
# por recálculo é irrelevante.
|
||||
def motorista_usuario(consolidacao_motorista)
|
||||
User.motorista.ativos.find_by('LOWER(nome) = ?', consolidacao_motorista.motorista_nome.to_s.downcase)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
def contar_entregas(consolidacao, consolidacao_motorista)
|
||||
consolidacao.consolidacao_entregas
|
||||
.where(motorista_nome: consolidacao_motorista.motorista_nome)
|
||||
.where.not(tipo: :desconto)
|
||||
.count
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
# Moeda BR com separador de milhar. Duplica o helper do NotificacaoService de
|
||||
# propósito: este módulo é chamado de dentro de models e jobs, onde puxar o
|
||||
# service inteiro só para formatar número seria acoplamento à toa.
|
||||
def moeda(valor)
|
||||
inteiro, decimais = format('%.2f', valor.to_f).split('.')
|
||||
inteiro = inteiro.reverse.gsub(/(\d{3})(?=\d)/, '\1.').reverse
|
||||
"R$ #{inteiro},#{decimais}"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user