# 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