Criação da visão geral da consolidação por motorista
This commit is contained in:
90
spec/requests/totais_por_motorista_spec.rb
Normal file
90
spec/requests/totais_por_motorista_spec.rb
Normal file
@@ -0,0 +1,90 @@
|
||||
require 'rails_helper'
|
||||
|
||||
# Rotas do relatório "total por motorista": quem entra, o que a tela mostra e o
|
||||
# PDF. O drill-down (?motorista=) é o que responde "de onde vem esse valor".
|
||||
RSpec.describe 'Totais por motorista', type: :request do
|
||||
def consolidacao_finalizada(motorista:, valor:, nome: 'Fechamento Junho')
|
||||
c = create(:consolidacao, nome: nome, status: :finalizada,
|
||||
data_inicio: Date.new(2026, 6, 1), data_fim: Date.new(2026, 6, 30))
|
||||
create(:consolidacao_entrega, consolidacao: c, motorista_nome: motorista, valor_aplicado: valor)
|
||||
create(:consolidacao_motorista, consolidacao: c, motorista_nome: motorista)
|
||||
c
|
||||
end
|
||||
|
||||
let(:periodo) { { inicio: '2026-06-01', fim: '2026-06-30' } }
|
||||
|
||||
describe 'admin — /consolidacoes/totais' do
|
||||
it 'exige login' do
|
||||
get totais_consolidacoes_path
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
|
||||
it 'bloqueia motorista (Pundit)' do
|
||||
sign_in create(:motorista)
|
||||
get totais_consolidacoes_path
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it 'mostra o total do motorista no período' do
|
||||
consolidacao_finalizada(motorista: 'Carlos', valor: 120.0)
|
||||
sign_in create(:gerente)
|
||||
|
||||
get totais_consolidacoes_path(periodo)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include('Carlos')
|
||||
end
|
||||
|
||||
it 'abre a composição do motorista clicado' do
|
||||
consolidacao_finalizada(motorista: 'Carlos', valor: 120.0, nome: 'Fechamento Junho')
|
||||
sign_in create(:gerente)
|
||||
|
||||
get totais_consolidacoes_path(periodo.merge(motorista: 'Carlos'))
|
||||
|
||||
expect(response.body).to include('Composição de Carlos')
|
||||
expect(response.body).to include('Fechamento Junho')
|
||||
end
|
||||
|
||||
it 'gera o PDF' do
|
||||
consolidacao_finalizada(motorista: 'Carlos', valor: 120.0)
|
||||
sign_in create(:gerente)
|
||||
|
||||
get totais_pdf_consolidacoes_path(periodo)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.media_type).to eq('application/pdf')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'motorista — /motorista/totais' do
|
||||
it 'mostra só o total dele e as consolidações que o compõem' do
|
||||
motorista = create(:motorista, nome: 'Carlos')
|
||||
consolidacao_finalizada(motorista: 'Carlos', valor: 120.0, nome: 'Fechamento Junho')
|
||||
consolidacao_finalizada(motorista: 'Pedro', valor: 999.0, nome: 'Fechamento do Pedro')
|
||||
sign_in motorista
|
||||
|
||||
get motorista_totais_path(periodo)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include('Fechamento Junho')
|
||||
expect(response.body).not_to include('Fechamento do Pedro')
|
||||
end
|
||||
|
||||
it 'gera o PDF do período' do
|
||||
motorista = create(:motorista, nome: 'Carlos')
|
||||
consolidacao_finalizada(motorista: 'Carlos', valor: 120.0)
|
||||
sign_in motorista
|
||||
|
||||
get motorista_totais_pdf_path(periodo)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.media_type).to eq('application/pdf')
|
||||
end
|
||||
|
||||
it 'não é acessível por quem não é motorista' do
|
||||
sign_in create(:gerente)
|
||||
get motorista_totais_path
|
||||
expect(response).to redirect_to(dashboard_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
92
spec/services/analytics/totais_por_motorista_spec.rb
Normal file
92
spec/services/analytics/totais_por_motorista_spec.rb
Normal file
@@ -0,0 +1,92 @@
|
||||
require 'rails_helper'
|
||||
|
||||
# Trava a conta do relatório "total por motorista" — a mesma que alimenta
|
||||
# /consolidacoes/totais (admin) e /motorista/totais (motorista). As duas telas
|
||||
# usam ESTE service justamente para não poderem divergir.
|
||||
RSpec.describe Analytics::TotaisPorMotorista do
|
||||
let(:inicio) { Date.new(2026, 6, 1) }
|
||||
let(:fim) { Date.new(2026, 6, 30) }
|
||||
|
||||
# Uma consolidação com um motorista e `qtd` lançamentos de `valor` cada. As
|
||||
# entregas vêm ANTES do ConsolidacaoMotorista porque é o before_save dele que
|
||||
# calcula valor_total a partir delas.
|
||||
def consolidar(motorista:, valor: 100.0, qtd: 1, status: :finalizada,
|
||||
data_inicio: Date.new(2026, 6, 1), data_fim: Date.new(2026, 6, 30),
|
||||
pago: false, arquivado: false)
|
||||
c = create(:consolidacao, status: status, data_inicio: data_inicio, data_fim: data_fim)
|
||||
qtd.times { create(:consolidacao_entrega, consolidacao: c, motorista_nome: motorista, valor_aplicado: valor) }
|
||||
cm = create(:consolidacao_motorista, consolidacao: c, motorista_nome: motorista)
|
||||
cm.update!(pago_em: Time.current, forma_pagamento: 'pix') if pago
|
||||
cm.arquivar!(nil) if arquivado
|
||||
[c, cm]
|
||||
end
|
||||
|
||||
subject(:totais) { described_class.new(inicio: inicio, fim: fim) }
|
||||
|
||||
it 'soma por motorista só as consolidações finalizadas do período' do
|
||||
consolidar(motorista: 'Carlos', valor: 100.0, qtd: 2) # 200
|
||||
consolidar(motorista: 'Carlos', valor: 50.0, qtd: 1) # 50
|
||||
consolidar(motorista: 'Pedro', valor: 30.0, qtd: 1) # 30
|
||||
consolidar(motorista: 'Carlos', valor: 999.0, status: :rascunho) # fora (rascunho)
|
||||
consolidar(motorista: 'Carlos', valor: 999.0, # fora (período)
|
||||
data_inicio: Date.new(2026, 7, 1), data_fim: Date.new(2026, 7, 31))
|
||||
|
||||
expect(totais.linhas.map { |l| [l[:motorista], l[:valor_total]] })
|
||||
.to eq([['Carlos', 250.0], ['Pedro', 30.0]])
|
||||
expect(totais.total_geral).to eq(280.0)
|
||||
expect(totais.total_consolidacoes).to eq(3)
|
||||
end
|
||||
|
||||
it 'inclui rascunhos quando pedido' do
|
||||
consolidar(motorista: 'Carlos', valor: 100.0)
|
||||
consolidar(motorista: 'Carlos', valor: 40.0, status: :rascunho)
|
||||
|
||||
com_rascunho = described_class.new(inicio: inicio, fim: fim, incluir_rascunhos: true)
|
||||
expect(totais.total_geral).to eq(100.0)
|
||||
expect(com_rascunho.total_geral).to eq(140.0)
|
||||
end
|
||||
|
||||
it 'separa pago de a receber' do
|
||||
consolidar(motorista: 'Carlos', valor: 100.0, pago: true)
|
||||
consolidar(motorista: 'Carlos', valor: 60.0)
|
||||
|
||||
linha = totais.linhas.first
|
||||
expect(linha[:valor_pago]).to eq(100.0)
|
||||
expect(linha[:valor_pendente]).to eq(60.0)
|
||||
expect(totais.total_pago).to eq(100.0)
|
||||
expect(totais.total_pendente).to eq(60.0)
|
||||
end
|
||||
|
||||
it 'ignora motorista arquivado (mesmo conjunto que a consolidação paga)' do
|
||||
consolidar(motorista: 'Carlos', valor: 100.0)
|
||||
consolidar(motorista: 'Carlos', valor: 70.0, arquivado: true)
|
||||
|
||||
expect(totais.total_geral).to eq(100.0)
|
||||
end
|
||||
|
||||
it 'lista as consolidações que compõem o total do motorista' do
|
||||
c1, = consolidar(motorista: 'Carlos', valor: 100.0)
|
||||
c2, = consolidar(motorista: 'Carlos', valor: 60.0, data_fim: Date.new(2026, 6, 15))
|
||||
consolidar(motorista: 'Pedro', valor: 30.0)
|
||||
|
||||
composicao = totais.consolidacoes_de('Carlos')
|
||||
expect(composicao.map(&:consolidacao_id)).to match_array([c1.id, c2.id])
|
||||
expect(composicao.sum(&:valor_total)).to eq(160.0)
|
||||
end
|
||||
|
||||
it 'recortado por motorista, só enxerga o dele (visão do painel do motorista)' do
|
||||
consolidar(motorista: 'Carlos', valor: 100.0)
|
||||
consolidar(motorista: 'Pedro', valor: 30.0)
|
||||
|
||||
meu = described_class.new(inicio: inicio, fim: fim, motorista: 'Carlos')
|
||||
expect(meu.total_geral).to eq(100.0)
|
||||
expect(meu.linhas.size).to eq(1)
|
||||
end
|
||||
|
||||
it 'período sem fechamento fica vazio (e não quebra)' do
|
||||
vazio = described_class.new(inicio: Date.new(2026, 1, 1), fim: Date.new(2026, 1, 31))
|
||||
expect(vazio).to be_vazio
|
||||
expect(vazio.total_geral).to eq(0)
|
||||
expect(vazio.linhas).to eq([])
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user