Files
Reem-Notas/app/controllers/admin/eventos_notificacao_controller.rb

141 lines
4.8 KiB
Ruby

# app/controllers/admin/eventos_notificacao_controller.rb
#
# Cadastro dos eventos e de quais grupos assinam cada um.
#
# O ADM cria quantos eventos quiser, mas o GATILHO sai de EventoNotificacao::
# GATILHOS — gatilho é código. `manual` cobre o aviso pontual (o texto é
# digitado na hora do disparo) e `agendado` cobre o resumo periódico.
class Admin::EventosNotificacaoController < ApplicationController
before_action :set_evento, only: %i[edit update destroy disparar]
before_action :carregar_grupos, only: %i[new create edit update]
def index
authorize EventoNotificacao
@eventos = policy_scope(EventoNotificacao)
.ordenados.includes(assinaturas: :grupo_contato)
end
def new
@evento = EventoNotificacao.new(gatilho: 'manual', ativo: true, hora: 8)
authorize @evento
montar_assinaturas
end
def create
@evento = EventoNotificacao.new(evento_params)
authorize @evento
if @evento.save
salvar_assinaturas
registrar("Criou evento de notificação #{@evento.nome}")
redirect_to admin_eventos_path, notice: 'Evento criado.'
else
montar_assinaturas
render :new, status: :unprocessable_entity
end
end
def edit
authorize @evento
montar_assinaturas
end
def update
authorize @evento
# `chave` é o que o código usa para achar o evento no disparo. Deixar o ADM
# renomear a chave de um evento de sistema quebraria o gatilho em silêncio.
permitidos = @evento.sistema? ? evento_params.except(:chave, :gatilho) : evento_params
if @evento.update(permitidos)
salvar_assinaturas
registrar("Editou evento de notificação #{@evento.nome}")
redirect_to admin_eventos_path, notice: 'Evento atualizado.'
else
montar_assinaturas
render :edit, status: :unprocessable_entity
end
end
def destroy
authorize @evento
nome = @evento.nome
@evento.destroy
registrar("Excluiu evento de notificação #{nome}")
redirect_to admin_eventos_path, notice: 'Evento removido.'
end
# Disparo manual: manda mensagem DE VERDADE para todos os grupos assinantes.
# O texto é digitado na hora — o editor de blocos ainda não existe.
def disparar
authorize @evento, :disparar?
corpo = params[:corpo].to_s.strip
# Com mensagem montada no editor o texto é opcional: o template vence e o
# corpo digitado só serve de reserva para o canal que ainda não tem um.
com_template = MensagemTemplate::CANAIS.any? { |c| @evento.template_utilizavel(c) }
if corpo.blank? && !com_template
return redirect_to(admin_eventos_path, alert: 'Escreva a mensagem ou monte o template antes de disparar.')
end
Notificacao::Despachante.disparar(chave: @evento.chave,
dados: Notificacao::Variaveis.comuns_reais,
assunto: params[:assunto].presence || @evento.nome,
corpo: corpo)
registrar("Disparou manualmente o evento #{@evento.nome}")
redirect_to admin_envios_path,
notice: 'Disparo agendado. Acompanhe o resultado aqui.'
end
private
def set_evento
@evento = EventoNotificacao.find(params[:id])
end
def carregar_grupos
@grupos = GrupoContato.ativos.ordenados
end
# Uma linha por grupo ativo, marcada quando já existe assinatura. É o que faz
# a tela mostrar TODOS os grupos com checkbox, e não só os já assinados.
def montar_assinaturas
existentes = @evento.assinaturas.index_by(&:grupo_contato_id)
@linhas_assinatura = @grupos.map do |grupo|
{ grupo: grupo, assinatura: existentes[grupo.id] }
end
end
def salvar_assinaturas
# ActionController::Parameters, indexado pela id do grupo como STRING (é
# assim que o form serializa: assinaturas[12][ativo]). Nada de `to_h` aqui:
# em params não permitidos ele levanta.
marcadas = params.fetch(:assinaturas, {})
GrupoContato.ativos.find_each do |grupo|
dados = marcadas[grupo.id.to_s]
atual = @evento.assinaturas.find_by(grupo_contato_id: grupo.id)
if dados.present? && dados[:ativo] == '1'
canal = GrupoEventoAssinatura::CANAIS.include?(dados[:canal]) ? dados[:canal] : 'ambos'
atual ? atual.update(canal: canal, ativo: true)
: @evento.assinaturas.create(grupo_contato: grupo, canal: canal, ativo: true)
elsif atual
atual.destroy
end
end
end
def evento_params
params.require(:evento_notificacao)
.permit(:nome, :chave, :gatilho, :descricao, :ativo, :notificar_envolvido,
:frequencia, :hora, :dia_semana)
end
def registrar(detalhes)
AuditoriaLog.registrar(user: current_user, acao: 'evento_notificacao',
entidade: 'EventoNotificacao',
dados_novos: { detalhes: detalhes }, request: request)
end
end