Implantação da geração de mensagem de forma livre e mudança na engine de mensagem

This commit is contained in:
2026-08-24 17:32:16 -03:00
parent 94bbe7556f
commit 88f19dd8f5
77 changed files with 4650 additions and 25 deletions

68
app/models/contato.rb Normal file
View File

@@ -0,0 +1,68 @@
# app/models/contato.rb
#
# Destinatário das notificações, cadastrado à mão pelo ADM: nome, número e/ou
# e-mail, e o grupo a que pertence.
#
# Telefone é gravado SEMPRE em E.164 (+5511920051157). O ADM digita como quiser
# — "(11) 92005-1157", "011 92005 1157" — e a normalização acontece aqui, uma
# vez, na gravação. Mandar o texto cru para o provedor devolve erro de destino
# inválido que o rescue do envio esconderia.
class Contato < ApplicationRecord
belongs_to :grupo_contato, optional: true
belongs_to :user, optional: true
has_many :notificacao_envios, dependent: :nullify
EMAIL_RE = /\A[^@\s]+@[^@\s]+\z/
validates :nome, presence: true
validates :email, format: { with: EMAIL_RE }, allow_blank: true
validate :telefone_ou_email
validate :telefone_valido
before_validation :normalizar
scope :ativos, -> { where(ativo: true) }
scope :ordenados, -> { order(Arel.sql('LOWER(nome)')) }
scope :com_whatsapp, -> { where.not(telefone: [nil, '']) }
scope :com_email, -> { where.not(email: [nil, '']) }
# Filtra pelo canal do disparo. 'ambos' = quem tiver qualquer um dos dois.
scope :com_canal, ->(canal) {
case canal.to_s
when 'whatsapp' then com_whatsapp
when 'email' then com_email
else where("(telefone IS NOT NULL AND telefone <> '') OR (email IS NOT NULL AND email <> '')")
end
}
def whatsapp? = telefone.present?
def email? = email.present?
def primeiro_nome
nome.to_s.split.first.to_s
end
private
def normalizar
self.nome = nome.to_s.strip.squeeze(' ').presence
self.email = email.to_s.strip.downcase.presence
# Mantém o que foi digitado se não der para normalizar — a validação acusa e
# o ADM vê o próprio valor de volta no campo para corrigir.
bruto = telefone.to_s.strip.presence
self.telefone = bruto && (ConfiguracaoNotificacao.normalizar_telefone(bruto) || bruto)
end
def telefone_ou_email
return if telefone.present? || email.present?
errors.add(:base, 'Informe ao menos um WhatsApp ou um e-mail.')
end
def telefone_valido
return if telefone.blank?
return if ConfiguracaoNotificacao.normalizar_telefone(telefone).present?
errors.add(:telefone, 'não parece um número brasileiro válido (DDD + número)')
end
end