Correções: - Erro de sintaxe em Admin::Usuarios#toggle_ativo (entidade: \'User\') que derrubava /admin/usuarios - Migration fase2 readicionava coluna `ativo` sem guard (db:migrate do zero quebrava); db:seed colidia no índice único de email para motoristas - Dashboard e HistoricoEstimado agora aplicam .da_conta_gade - ConsolidacaoMotorista#recalcular_valor usa valor_aplicado (fonte única) - Gate de finalização por motorista (antes soma agregada com >=) e validação de elegibilidade em classificar/classificar_em_massa - Remove coluna órfã pin_acesso; registra autor do arquivamento (arquivado_por/arquivado_em + belongs_to :arquivador) - Dashboard redireciona motorista; Date.parse tolerante - Remove MotoristaController + view órfãos (não roteados e quebrados) Testes: infra RSpec + factories + specs de models, policy e request. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
90 lines
3.0 KiB
Ruby
90 lines
3.0 KiB
Ruby
# app/controllers/dashboard_controller.rb
|
|
class DashboardController < ApplicationController
|
|
def index
|
|
skip_authorization
|
|
|
|
# Motorista tem painel próprio — não enxerga o dashboard administrativo
|
|
return redirect_to(motorista_dashboard_path) if current_user.motorista?
|
|
|
|
@data_referencia = parse_data(params[:data])
|
|
@mes_inicio = @data_referencia.beginning_of_month
|
|
@mes_fim = @data_referencia.end_of_month
|
|
|
|
carregar_dados_dashboard
|
|
end
|
|
|
|
private
|
|
|
|
# Parse tolerante: data inválida/ausente cai no dia atual em vez de estourar 500.
|
|
def parse_data(str)
|
|
return Date.current if str.blank?
|
|
Date.parse(str)
|
|
rescue ArgumentError, TypeError
|
|
Date.current
|
|
end
|
|
|
|
def carregar_dados_dashboard
|
|
# Entregas do mês atual (da tabela read-only) — restritas à conta Gade
|
|
entregas_mes = Entrega.da_conta_gade.do_mes(@data_referencia)
|
|
|
|
# Totais gerais
|
|
@total_entregas = entregas_mes.count
|
|
@entregas_pagas = entregas_mes.pagas.count
|
|
@entregas_pendentes = @total_entregas - @entregas_pagas
|
|
|
|
# Configurações de preço
|
|
config = Configuracao.mapa_de_precos
|
|
|
|
# Valor estimado total
|
|
@valor_estimado = (@entregas_pagas * config[:entrega]).round(2)
|
|
|
|
# Por motorista (top 10)
|
|
@motoristas = entregas_mes.pagas
|
|
.group(:driver)
|
|
.count
|
|
.sort_by { |_, v| -v }
|
|
.first(10)
|
|
.map do |driver, qtd|
|
|
{
|
|
nome: driver,
|
|
entregas: qtd,
|
|
valor: (qtd * config[:entrega]).round(2)
|
|
}
|
|
end
|
|
|
|
# Por operação (route_id → contact_name)
|
|
@por_operacao = entregas_mes.pagas
|
|
.group(:contact_name)
|
|
.count
|
|
.sort_by { |_, v| -v }
|
|
.first(6)
|
|
.to_h
|
|
|
|
# Evolução diária do mês (para Chart.js)
|
|
@grafico_diario = build_grafico_diario(entregas_mes, config[:entrega])
|
|
|
|
# Consolidações do mês
|
|
@consolidacoes_mes = Consolidacao.ativas.where(created_at: @mes_inicio.beginning_of_day..@mes_fim.end_of_day)
|
|
@consolidacoes_abertas = @consolidacoes_mes.where(status: :rascunho).count
|
|
@consolidacoes_fechadas = @consolidacoes_mes.where(status: :finalizada).count
|
|
|
|
# Histórico estimado mais recente
|
|
@historico_recente = HistoricoEstimado.order(created_at: :desc).limit(5)
|
|
end
|
|
|
|
def build_grafico_diario(entregas, preco_entrega)
|
|
dias = ((@mes_inicio)..[@mes_fim, Date.today].min).map(&:to_s)
|
|
|
|
contagem = entregas.pagas
|
|
.group("DATE(planned_date)")
|
|
.count
|
|
.transform_keys { |k| k.to_s }
|
|
|
|
labels = dias.map { |d| Date.parse(d).strftime('%d/%m') }
|
|
valores = dias.map { |d| ((contagem[d] || 0) * preco_entrega).round(2) }
|
|
qtds = dias.map { |d| contagem[d] || 0 }
|
|
|
|
{ labels: labels, valores: valores, qtds: qtds }
|
|
end
|
|
end
|