Implantação da função d adicionar entregas por fora da operação

This commit is contained in:
2026-06-19 14:35:18 -03:00
parent 81128e7a68
commit 79c0f646da
11 changed files with 361 additions and 3 deletions

View File

@@ -164,6 +164,91 @@ class ConsolidacaoEntregasController < ApplicationController
end
end
# GET /consolidacoes/:consolidacao_id/consolidacao_entregas/buscar_nf?nf=123
# APONTAMENTO MANUAL — busca a NF na SimpleRoute (sem filtro de período).
def buscar_nf
authorize @consolidacao, :update?
nf = params[:nf].to_s.strip
return render(json: { ok: false, erro: 'Informe o número da nota.' }, status: :unprocessable_entity) if nf.blank?
entregas = Entrega.da_conta_gade.por_nf(nf).order(:checkout)
if entregas.empty?
render json: { ok: false, erro: "Nota #{nf} não encontrada na base de rastreio." }
else
render json: { ok: true, nf: nf, entregas: entregas.map { |e| entrega_json(e) } }
end
end
# POST /consolidacoes/:consolidacao_id/consolidacao_entregas/apontar
# Cria um apontamento manual a partir de um tracking_id encontrado pela NF.
def apontar
authorize @consolidacao, :update?
tipo = params[:tipo].to_s
return render_apontamento_erro('Tipo inválido.') unless ConsolidacaoEntrega.tipos.key?(tipo)
entrega = Entrega.da_conta_gade.find_by(tracking_id: params[:tracking_id])
return render_apontamento_erro('Entrega não encontrada na base de rastreio.') unless entrega
motorista = entrega.driver.to_s.strip
return render_apontamento_erro('Entrega sem motorista — não é possível apontar.') if motorista.blank?
# Garante o motorista na consolidação (pode não estar, já que a NF veio por fora).
@consolidacao.consolidacao_motoristas.find_or_create_by!(motorista_nome: motorista)
ce = @consolidacao.consolidacao_entregas
.find_or_initialize_by(tracking_id: entrega.tracking_id, tipo: tipo)
if ce.persisted?
return render_apontamento_erro("Essa nota já está classificada como #{ConsolidacaoEntrega::TIPO_CORES[tipo][:label]} para #{motorista}.")
end
ce.assign_attributes(
motorista_nome: motorista,
valor_aplicado: valor_para_tipo(tipo),
manual: true,
created_by: current_user.id
)
ce.save!
recalcular_motorista(motorista)
auditar!(:editar, @consolidacao,
dados_novos: { apontamento_manual: entrega.numero_nf, tipo: tipo, motorista: motorista })
respond_to do |format|
format.json { render json: resumo_json(motorista).merge(motorista: motorista) }
format.html do
redirect_to validar_consolidacao_consolidacao_entregas_path(@consolidacao, motorista: motorista),
notice: "Apontamento da nota #{entrega.numero_nf} adicionado para #{motorista}."
end
end
end
# DELETE /consolidacoes/:consolidacao_id/consolidacao_entregas/remover_apontamento?id=1
# Remove um apontamento manual. (Não passa pelo guard de elegibilidade, pois o
# tracking está fora do período — por isso não reusa o toggle classificar.)
def remover_apontamento
authorize @consolidacao, :update?
ce = @consolidacao.consolidacao_entregas.apontamentos.find_by(id: params[:id])
return render_apontamento_erro('Apontamento não encontrado.') unless ce
motorista = ce.motorista_nome
ce.destroy
recalcular_motorista(motorista)
auditar!(:editar, @consolidacao,
dados_novos: { remover_apontamento_manual: ce.tracking_id, motorista: motorista })
respond_to do |format|
format.json { render json: resumo_json(motorista).merge(motorista: motorista) }
format.html do
redirect_to revisar_consolidacao_consolidacao_entregas_path(@consolidacao, motorista: motorista),
notice: 'Apontamento removido.'
end
end
end
private
def set_consolidacao
@@ -200,6 +285,27 @@ class ConsolidacaoEntregasController < ApplicationController
tracking_ids_elegiveis(motorista).include?(tracking_id)
end
# Dados da entrega para o modal de apontamento (conferência antes de salvar).
def entrega_json(e)
{
tracking_id: e.tracking_id,
nf: e.numero_nf,
motorista: e.driver,
veiculo: e.vehicle,
local: e.local,
status: e.status,
pago: e.elegivel_pagamento?,
data: (e.checkout || e.planned_date)&.to_s
}
end
def render_apontamento_erro(msg)
respond_to do |format|
format.json { render json: { ok: false, erro: msg }, status: :unprocessable_entity }
format.html { redirect_to wizard_consolidacao_path(@consolidacao), alert: msg }
end
end
def render_nao_elegivel
respond_to do |format|
format.json { render json: { ok: false, erro: 'Entrega não elegível para este motorista.' }, status: :unprocessable_entity }

View File

@@ -114,11 +114,18 @@ class ConsolidacoesController < ApplicationController
@motoristas = @consolidacao.consolidacao_motoristas.order(:motorista_nome).map do |cm|
total = @consolidacao.entregas_elegiveis_count(cm.motorista_nome)
classificadas = @consolidacao.classificadas_count(cm.motorista_nome)
apontamentos = @consolidacao.consolidacao_entregas
.apontamentos
.where(motorista_nome: cm.motorista_nome)
.distinct.count(:tracking_id)
{
registro: cm,
total: total,
classificadas: classificadas,
completo: total.positive? && classificadas >= total
apontamentos: apontamentos,
# Espelha o gate do servidor (todas_entregas_classificadas?): um motorista
# só com apontamento manual tem 0 entregas elegíveis e já está "completo".
completo: total.zero? || classificadas >= total
}
end
end