Implantação da geração de mensagem de forma livre e mudança na engine de mensagem
This commit is contained in:
@@ -13,10 +13,12 @@
|
||||
class NotificacaoService
|
||||
EVENTOS = {
|
||||
fechado: { mailer: :pagamento_fechado,
|
||||
chave: 'consolidacao_finalizada',
|
||||
emoji: '🚚',
|
||||
titulo: 'Seu pagamento de entregas foi fechado.',
|
||||
cta: 'Acesse seu painel para baixar o extrato:' },
|
||||
pago: { mailer: :pagamento_efetuado,
|
||||
chave: 'pagamento_efetuado',
|
||||
emoji: '✅',
|
||||
titulo: 'Seu pagamento foi efetuado.',
|
||||
cta: 'Acesse seu painel para conferir:' }
|
||||
@@ -48,10 +50,70 @@ class NotificacaoService
|
||||
|
||||
def notificar(cm, evento)
|
||||
user = motorista_de(cm)
|
||||
return unless user
|
||||
|
||||
enviar_whatsapp(user, cm, evento) if @config.whatsapp_habilitado?
|
||||
enviar_email(user, cm, evento) if @config.email_habilitado? && user.email.present?
|
||||
# Aviso pessoal ao motorista: continua com o e-mail formatado do
|
||||
# ConsolidacaoMailer (não vira texto puro) e passa a usar o provedor de
|
||||
# WhatsApp escolhido na tela — Baileys por QR ou Twilio.
|
||||
if user
|
||||
enviar_whatsapp(user, cm, evento) if @config.whatsapp_habilitado?
|
||||
enviar_email(user, cm, evento) if @config.email_habilitado? && user.email.present?
|
||||
end
|
||||
|
||||
# Cópia para os grupos que assinam este evento (diretoria, operação...).
|
||||
# `envolvido: nil` de propósito: o motorista já foi avisado acima e receberia
|
||||
# a mensagem duas vezes.
|
||||
avisar_grupos(cm, evento, user)
|
||||
end
|
||||
|
||||
# O corpo aqui é o mesmo texto do WhatsApp — na etapa do editor de blocos ele
|
||||
# passa a vir do template configurado pelo ADM.
|
||||
def avisar_grupos(cm, evento, user)
|
||||
evt = EVENTOS.fetch(evento)
|
||||
Notificacao::Despachante.disparar(
|
||||
chave: evt[:chave],
|
||||
dados: variaveis(cm, user),
|
||||
assunto: "#{evt[:titulo]} — #{@consolidacao.nome}",
|
||||
corpo: mensagem_para_grupos(cm, evento, user)
|
||||
)
|
||||
end
|
||||
|
||||
# Contexto das {{variaveis}} do editor de blocos. As chaves são as mesmas de
|
||||
# Notificacao::Variaveis::FECHAMENTO — é o que o ADM vê na paleta da tela.
|
||||
def variaveis(cm, user)
|
||||
Notificacao::Variaveis.comuns_reais.merge(
|
||||
'motorista' => user&.nome.presence || cm.motorista_nome,
|
||||
'consolidacao' => @consolidacao.nome,
|
||||
'periodo' => "#{l_data(@consolidacao.data_inicio)} a #{l_data(@consolidacao.data_fim)}",
|
||||
'valor' => moeda(cm.valor_total),
|
||||
# ConsolidacaoMotorista não guarda contagem — só valor_total. As entregas
|
||||
# do motorista são as linhas classificadas na consolidação (mesma fonte do
|
||||
# #recalcular_valor), descontando os lançamentos de desconto, que não são
|
||||
# entregas.
|
||||
'entregas' => entregas_do_motorista(cm).to_s,
|
||||
'link_painel' => "https://#{ENV.fetch('APP_HOST', 'localhost:3000')}/motorista"
|
||||
)
|
||||
end
|
||||
|
||||
def l_data(data)
|
||||
data&.strftime('%d/%m/%Y').to_s
|
||||
end
|
||||
|
||||
def entregas_do_motorista(cm)
|
||||
@consolidacao.consolidacao_entregas
|
||||
.where(motorista_nome: cm.motorista_nome)
|
||||
.where.not(tipo: :desconto)
|
||||
.count
|
||||
rescue StandardError => e
|
||||
Rails.logger.warn("[Notificacao] contagem de entregas indisponível: #{e.class}: #{e.message}")
|
||||
nil
|
||||
end
|
||||
|
||||
def mensagem_para_grupos(cm, evento, user)
|
||||
evt = EVENTOS.fetch(evento)
|
||||
"#{evt[:emoji]} #{evt[:titulo]}\n" \
|
||||
"👤 #{user&.nome || cm.motorista_nome}\n" \
|
||||
"📋 #{@consolidacao.nome}\n" \
|
||||
"💰 Valor: #{moeda(cm.valor_total)}"
|
||||
end
|
||||
|
||||
def motorista_de(cm)
|
||||
@@ -59,34 +121,57 @@ class NotificacaoService
|
||||
end
|
||||
|
||||
def enviar_whatsapp(user, cm, evento)
|
||||
# O telefone no cadastro pode estar como "(11) 92005-1157"; mandar esse
|
||||
# texto cru para o Twilio devolve erro 21211 (destino inválido), que o
|
||||
# rescue abaixo esconderia. Normalizar para E.164 é o que faz o envio
|
||||
# realmente funcionar.
|
||||
destino = ConfiguracaoNotificacao.canal(user.telefone)
|
||||
# O telefone no cadastro pode estar como "(11) 92005-1157"; a normalização
|
||||
# para E.164 acontece dentro de Notificacao::Whatsapp — mandar o texto cru
|
||||
# devolve erro de destino inválido que o rescue esconderia.
|
||||
destino = ConfiguracaoNotificacao.normalizar_telefone(user.telefone)
|
||||
return if destino.blank?
|
||||
|
||||
credenciais = @config.credenciais_whatsapp
|
||||
return if credenciais.blank? || credenciais[:from].blank?
|
||||
texto = mensagem(user, cm, evento)
|
||||
envio = registrar_envio(evento, canal: 'whatsapp', destino: destino, user: user, corpo: texto)
|
||||
|
||||
Notificacao::ClienteTwilio
|
||||
.montar(credenciais[:sid], credenciais[:token])
|
||||
.messages.create(from: credenciais[:from], to: destino, body: mensagem(user, cm, evento))
|
||||
|
||||
Rails.logger.info("[Notificacao] WhatsApp (#{evento}) enviado para #{user.nome}")
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("[Notificacao] Falha WhatsApp (#{evento}) #{user.nome}: #{e.class}: #{e.message}")
|
||||
resposta = Notificacao::Whatsapp.enviar(para: destino, texto: texto, config: @config)
|
||||
if resposta.ok?
|
||||
envio&.marcar_enviado!
|
||||
Rails.logger.info("[Notificacao] WhatsApp (#{evento}) enviado para #{user.nome}")
|
||||
else
|
||||
envio&.marcar_falha!(resposta.erro)
|
||||
Rails.logger.error("[Notificacao] Falha WhatsApp (#{evento}) #{user.nome}: #{resposta.erro}")
|
||||
end
|
||||
end
|
||||
|
||||
def enviar_email(user, cm, evento)
|
||||
ConsolidacaoMailer
|
||||
.public_send(EVENTOS.fetch(evento)[:mailer], user, @consolidacao, cm)
|
||||
.deliver_later
|
||||
evt = EVENTOS.fetch(evento)
|
||||
envio = registrar_envio(evento, canal: 'email', destino: user.email, user: user,
|
||||
corpo: mensagem(user, cm, evento), assunto: evt[:titulo])
|
||||
|
||||
ConsolidacaoMailer.public_send(evt[:mailer], user, @consolidacao, cm).deliver_later
|
||||
# `deliver_later` só ENFILEIRA: marcar como enviado aqui significa "saiu do
|
||||
# nosso lado". Uma falha do SMTP aparece no log do Rails, não aqui.
|
||||
envio&.marcar_enviado!
|
||||
Rails.logger.info("[Notificacao] Email (#{evento}) agendado para #{user.email}")
|
||||
rescue StandardError => e
|
||||
envio&.marcar_falha!("#{e.class}: #{e.message}")
|
||||
Rails.logger.error("[Notificacao] Falha email (#{evento}) #{user.email}: #{e.class}: #{e.message}")
|
||||
end
|
||||
|
||||
# Log do aviso pessoal. Nunca levanta: se a tabela ainda não existir (deploy
|
||||
# antes do migrate), o envio precisa seguir mesmo sem registro.
|
||||
def registrar_envio(evento, canal:, destino:, user:, corpo:, assunto: nil)
|
||||
NotificacaoEnvio.create!(
|
||||
evento_notificacao: evento_registrado(evento), user: user, canal: canal,
|
||||
destino: destino, assunto: assunto, corpo: corpo, status: 'pendente'
|
||||
)
|
||||
rescue StandardError => e
|
||||
Rails.logger.warn("[Notificacao] sem log de envio (#{e.class}: #{e.message})")
|
||||
nil
|
||||
end
|
||||
|
||||
def evento_registrado(evento)
|
||||
@eventos_cache ||= {}
|
||||
@eventos_cache[evento] ||= EventoNotificacao.find_by(chave: EVENTOS.fetch(evento)[:chave])
|
||||
end
|
||||
|
||||
def mensagem(user, cm, evento)
|
||||
evt = EVENTOS.fetch(evento)
|
||||
"Olá #{user.nome.split.first}! #{evt[:emoji]}\n" \
|
||||
|
||||
Reference in New Issue
Block a user