Implantação da geração de mensagem de forma livre e mudança na engine de mensagem
This commit is contained in:
85
app/models/mensagem_template.rb
Normal file
85
app/models/mensagem_template.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
# app/models/mensagem_template.rb
|
||||
#
|
||||
# Corpo de um evento em UM canal, montado com blocos no editor.
|
||||
#
|
||||
# `blocos` vem de um campo hidden preenchido por JavaScript — ou seja, de fora.
|
||||
# Por isso #normalizar_blocos DESCARTA o que não está no catálogo: tipo
|
||||
# desconhecido, campo que aquele tipo não tem, e qualquer coisa que não seja
|
||||
# Hash. Sem isso, um JSON adulterado no form viraria conteúdo renderizado sem
|
||||
# passar por validação nenhuma.
|
||||
class MensagemTemplate < ApplicationRecord
|
||||
CANAIS = %w[whatsapp email].freeze
|
||||
# Teto de segurança: um template com milhares de blocos só serviria para
|
||||
# travar o render do e-mail.
|
||||
MAX_BLOCOS = 40
|
||||
MAX_LINHAS_TABELA = 20
|
||||
|
||||
belongs_to :evento_notificacao
|
||||
|
||||
validates :canal, inclusion: { in: CANAIS }
|
||||
validates :canal, uniqueness: { scope: :evento_notificacao_id }
|
||||
validate :assunto_no_email
|
||||
|
||||
before_validation :normalizar_blocos
|
||||
|
||||
scope :ativos, -> { where(ativo: true) }
|
||||
scope :do_canal, ->(canal) { where(canal: canal.to_s) }
|
||||
|
||||
def email? = canal == 'email'
|
||||
def whatsapp? = canal == 'whatsapp'
|
||||
|
||||
# Um template só entra em uso quando tem conteúdo — template ativo e vazio
|
||||
# mandaria mensagem em branco, o que é pior do que cair no texto padrão.
|
||||
def utilizavel?
|
||||
ativo? && blocos.present?
|
||||
end
|
||||
|
||||
def renderizador(dados = {})
|
||||
Notificacao::Renderizador.new(blocos, dados)
|
||||
end
|
||||
|
||||
def preview(dados = nil)
|
||||
dados ||= Notificacao::Variaveis.amostra(evento_notificacao&.gatilho)
|
||||
r = renderizador(dados)
|
||||
email? ? r.html : r.texto
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def normalizar_blocos
|
||||
lista = blocos.is_a?(Array) ? blocos : []
|
||||
self.blocos = lista.filter_map { |bruto| limpar(bruto) }.first(MAX_BLOCOS)
|
||||
end
|
||||
|
||||
def limpar(bruto)
|
||||
return nil unless bruto.is_a?(Hash)
|
||||
|
||||
tipo = bruto['tipo'] || bruto[:tipo]
|
||||
return nil unless Notificacao::Blocos.valido?(tipo)
|
||||
|
||||
limpo = { 'tipo' => tipo.to_s }
|
||||
Notificacao::Blocos.campos(tipo).each do |campo, especie|
|
||||
valor = bruto[campo] || bruto[campo.to_sym]
|
||||
limpo[campo] = especie == :lista ? limpar_linhas(valor) : valor.to_s
|
||||
end
|
||||
limpo
|
||||
end
|
||||
|
||||
def limpar_linhas(valor)
|
||||
Array(valor).filter_map do |linha|
|
||||
next unless linha.is_a?(Hash)
|
||||
|
||||
rotulo = (linha['rotulo'] || linha[:rotulo]).to_s
|
||||
conteudo = (linha['valor'] || linha[:valor]).to_s
|
||||
next if rotulo.blank? && conteudo.blank?
|
||||
|
||||
{ 'rotulo' => rotulo, 'valor' => conteudo }
|
||||
end.first(MAX_LINHAS_TABELA)
|
||||
end
|
||||
|
||||
def assunto_no_email
|
||||
return unless email? && ativo? && blocos.present? && assunto.to_s.strip.blank?
|
||||
|
||||
errors.add(:assunto, 'é obrigatório no e-mail')
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user