Files
Reem-Notas/app/controllers/operacoes_dashboard_controller.rb

79 lines
3.0 KiB
Ruby

# app/controllers/operacoes_dashboard_controller.rb
#
# Dashboard de análise de ENTREGAS por operação (separado do dashboard
# financeiro). O operador escolhe uma operação (UBS Norte, EMAD, ...) e vê os
# KPIs/insucessos/STS/mapa; também há os modos "global" (todas no período) e
# "comparar" (uma operação vs outra). Os números vêm de Analytics::OperacaoMetricas.
class OperacoesDashboardController < ApplicationController
MODOS = %w[operacao global comparar].freeze
def index
authorize :dashboard, :operacoes?
@periodo_inicio, @periodo_fim = periodo_selecionado
@modo = MODOS.include?(params[:modo]) ? params[:modo] : 'operacao'
@operacoes_agrupadas = Operacao.agrupadas_por_mes
@tabelas_validas = Operacao.nomes_validos
@filtros, @chips = cross_filtros
case @modo
when 'global'
# Global: agrega TODAS as operações dentro da faixa de datas escolhida.
@metricas = montar(@tabelas_validas, inicio: @periodo_inicio, fim: @periodo_fim, filtros: @filtros)
when 'comparar'
# Comparar: cada operação inteira (sem filtro de data — só vale no Global).
@op_a = Operacao.sanitizar([params[:op_a]]).first || @tabelas_validas[0]
@op_b = Operacao.sanitizar([params[:op_b]]).first || @tabelas_validas[1]
@metricas_a = montar([@op_a]) if @op_a
@metricas_b = montar([@op_b]) if @op_b
else
# Operação única: a operação inteira (a data vem dos próprios dados).
@operacao = Operacao.sanitizar([params[:operacao]]).first || @tabelas_validas.first
@metricas = montar([@operacao], filtros: @filtros) if @operacao
end
end
private
def montar(tabelas, inicio: nil, fim: nil, filtros: {})
Analytics::OperacaoMetricas.new(tabelas: tabelas, inicio: inicio, fim: fim, filtros: filtros)
end
# Cross-filter por clique nas tabelas. Cada param vira um filtro de coluna e um
# "chip" removível na tela. Retorna [filtros (coluna=>valor), chips (p/ a view)].
CROSS = {
'f_driver' => { coluna: 'driver', rotulo: 'Motorista' },
'f_sts' => { coluna: 'contact_name', rotulo: 'Unidade' },
'f_status' => { coluna: 'status_gade', rotulo: 'Status' },
'f_obs' => { coluna: 'observation', rotulo: 'Observação' }
}.freeze
def cross_filtros
filtros = {}
chips = []
CROSS.each do |param, cfg|
valor = params[param].to_s.strip
next if valor.empty?
filtros[cfg[:coluna]] = valor
chips << { param: param, valor: valor, rotulo: cfg[:rotulo] }
end
[filtros, chips]
end
# Faixa de datas do filtro (params inicio/fim). Default: início do mês → hoje.
# Espelha DashboardController#periodo_selecionado.
def periodo_selecionado
inicio = parse_data(params[:inicio]) || Date.current.beginning_of_month
fim = parse_data(params[:fim]) || Date.current
inicio, fim = fim, inicio if fim < inicio
[inicio, fim]
end
def parse_data(str)
return nil if str.blank?
Date.parse(str)
rescue ArgumentError, TypeError
nil
end
end