# app/controllers/motorista/dashboard_controller.rb module Motorista class DashboardController < ApplicationController before_action :garantir_motorista # GET /motorista?inicio=&fim= # # UMA tela só: o motorista escolhe o período e vê, para aquele recorte, o que # já foi FECHADO pela empresa, o que ainda é ESTIMATIVA e de onde vem cada # centavo (os fechamentos que compõem o total). Antes o total ficava numa # tela e a composição em outra — e nenhuma das duas tinha período. def index nome = current_user.nome @inicio, @fim = periodo_selecionado @faixa_total = faixa_completa(nome) # para o atalho "Tudo" carregar_estimado(nome) carregar_fechado(nome) # Aviso in-app: pagamentos confirmados nos últimos 7 dias (notificação na # própria página do motorista, além de WhatsApp/email). Independe do # período escolhido — é um aviso, não um relatório. @pagamentos_recentes = ConsolidacaoMotorista .joins(:consolidacao) .where(motorista_nome: nome, consolidacoes: { status: :finalizada, deleted_at: nil }) .where.not(pago_em: nil) .where('pago_em >= ?', 7.days.ago) .order(pago_em: :desc) .includes(:consolidacao) end # GET /motorista/totais/pdf?inicio=&fim= — o extrato do período (total, # composição e assinaturas), para guardar ou mandar por WhatsApp. Mesmo # service da tela, então o papel e o painel nunca divergem. def totais_pdf inicio, fim = periodo_selecionado totais = Analytics::TotaisPorMotorista.new( inicio: inicio, fim: fim, motorista: current_user.nome ) arquivo = ['meu_total', current_user.nome.parameterize(separator: '_'), inicio.strftime('%Y%m%d'), fim.strftime('%Y%m%d')].join('_') send_data Pdf::TotaisMotoristaPdf.new(totais: totais).render, filename: "#{arquivo}.pdf", type: 'application/pdf', disposition: 'attachment' end private # Card ESTIMADO: entregas ATENDIDAS × preco_entrega dentro do período. # # Atendida = o motorista FOI ao local e fechou a visita, com sucesso # ('completed') OU insucesso ('failed') — no insucesso o deslocamento # aconteceu e teve custo, então a empresa paga os dois. É o MESMO recorte do # dashboard administrativo e da consolidação (ver Entrega::STATUS_ATENDIDO e # Entrega.contar_atendidas): usava `pagas` (só concluídas) e o motorista via # um valor MENOR que o do fechamento, sem entender de onde vinha a diferença. # # ⚠️ O eixo é o CHECKOUT (data real da visita), não planned_date: falhada TEM # checkout, e uma entrega planejada em 31/07 mas fechada em 01/08 pertence a # agosto — igual ao que a consolidação considera elegível. # # O fim é limitado a HOJE: estimar entregas de dias que ainda não # aconteceram não faz sentido (o período pode ir até o fim do mês). def carregar_estimado(nome) @estimado_inicio = @inicio @estimado_fim = [@fim, Date.current].min if @estimado_fim < @estimado_inicio @entregas_concluidas = @entregas_falhadas = @entregas_mes = 0 @valor_estimado = 0 return end atendidas = Entrega.atendidas.da_conta_gade .do_motorista(nome) .no_periodo_checkout(@estimado_inicio, @estimado_fim) @entregas_concluidas = atendidas.concluidas.count @entregas_falhadas = atendidas.falhadas.count @entregas_mes = @entregas_concluidas + @entregas_falhadas @valor_estimado = @entregas_mes * Configuracao.preco_entrega end # Card FECHADO + composição: o mesmo service do modo "Por motorista" do # admin, recortado neste motorista — os dois lados mostram o mesmo número. def carregar_fechado(nome) @totais = Analytics::TotaisPorMotorista.new(inicio: @inicio, fim: @fim, motorista: nome) @consolidacoes = @totais.consolidacoes_de(nome) @valor_consolidado = @totais.total_geral end # Primeira e última data de fechamento do motorista — alimenta o atalho # "Tudo" com datas reais em vez de uma faixa inventada. def faixa_completa(nome) escopo = Consolidacao.ativas.finalizada .joins(:consolidacao_motoristas) .where(consolidacao_motoristas: { motorista_nome: nome, arquivado_em: nil }) inicio = escopo.minimum(:data_inicio) fim = escopo.maximum(:data_fim) return nil if inicio.nil? || fim.nil? [inicio.to_date, fim.to_date] end # Default: mês corrente INTEIRO (fim = último dia do mês). O recorte exige a # consolidação inteira dentro da faixa, então terminar em "hoje" esconderia # um fechamento que vai até o fim do mês. Mesma regra do lado do admin. def periodo_selecionado inicio = parse_data(params[:inicio]) || Date.current.beginning_of_month fim = parse_data(params[:fim]) || Date.current.end_of_month 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 def garantir_motorista return if current_user.motorista? redirect_to dashboard_path, alert: 'Área exclusiva dos motoristas.' end end end