diff --git a/app/controllers/admin/configuracoes_controller.rb b/app/controllers/admin/configuracoes_controller.rb index 6477b5f..5a77376 100644 --- a/app/controllers/admin/configuracoes_controller.rb +++ b/app/controllers/admin/configuracoes_controller.rb @@ -4,7 +4,8 @@ class Admin::ConfiguracoesController < ApplicationController def index authorize Configuracao - @configuracoes = Configuracao.all.order(:chave) + # Só os pilares de PREÇO (empresa/notificações não são preço e não entram aqui) + @configuracoes = Configuracao.where(chave: Configuracao::CHAVES_MOEDA).order(:chave) end def edit diff --git a/app/controllers/consolidacao_entregas_controller.rb b/app/controllers/consolidacao_entregas_controller.rb index 069f53b..42c8405 100644 --- a/app/controllers/consolidacao_entregas_controller.rb +++ b/app/controllers/consolidacao_entregas_controller.rb @@ -19,10 +19,14 @@ class ConsolidacaoEntregasController < ApplicationController @entregas = @entregas.da_veiculo(@consolidacao.vehicle_ids) if @consolidacao.vehicle_ids.present? @entregas = @entregas.order(:planned_date) - # Classificações já feitas — indexadas por tracking_id + # Classificações já feitas — agrupadas por tracking_id (uma entrega pode ter + # vários pilares). { tracking_id => [ConsolidacaoEntrega, ...] } @classificacoes = @consolidacao.consolidacao_entregas .where(motorista_nome: @motorista) - .index_by(&:tracking_id) + .group_by(&:tracking_id) + + @total_entregas = @consolidacao.entregas_elegiveis_count(@motorista) + @classificadas = @consolidacao.classificadas_count(@motorista) # Filtro "apenas não classificadas" if params[:apenas_pendentes] == '1' @@ -44,17 +48,32 @@ class ConsolidacaoEntregasController < ApplicationController return render_nao_elegivel unless entrega_elegivel?(params[:motorista], params[:tracking_id]) - ce = @consolidacao.consolidacao_entregas.find_or_initialize_by(tracking_id: params[:tracking_id]) - ce.motorista_nome = params[:motorista] - ce.tipo = params[:tipo] - ce.valor_aplicado = valor_para_tipo(params[:tipo]) - ce.created_by = current_user.id - ce.save! + # Toggle do pilar: se já existe, remove; senão, adiciona (permite combinar + # vários pilares na mesma entrega). + ce = @consolidacao.consolidacao_entregas + .find_by(tracking_id: params[:tracking_id], tipo: params[:tipo]) + if ce + ce.destroy + ativo = false + else + @consolidacao.consolidacao_entregas.create!( + tracking_id: params[:tracking_id], + motorista_nome: params[:motorista], + tipo: params[:tipo], + valor_aplicado: valor_para_tipo(params[:tipo]), + created_by: current_user.id + ) + ativo = true + end recalcular_motorista(params[:motorista]) respond_to do |format| - format.json { render json: resumo_json(params[:motorista]) } + format.json do + render json: resumo_json(params[:motorista]).merge( + ativo: ativo, tracking_id: params[:tracking_id], tipo: params[:tipo] + ) + end format.html { redirect_back fallback_location: wizard_consolidacao_path(@consolidacao) } end end @@ -77,10 +96,11 @@ class ConsolidacaoEntregasController < ApplicationController valor = valor_para_tipo(tipo) + # Em massa, ADICIONA o pilar às entregas (não remove os demais já marcados). ActiveRecord::Base.transaction do tracking_ids.each do |tid| - ce = @consolidacao.consolidacao_entregas.find_or_initialize_by(tracking_id: tid) - ce.assign_attributes(motorista_nome: motorista, tipo: tipo, + ce = @consolidacao.consolidacao_entregas.find_or_initialize_by(tracking_id: tid, tipo: tipo) + ce.assign_attributes(motorista_nome: motorista, valor_aplicado: valor, created_by: current_user.id) ce.save! end @@ -193,7 +213,7 @@ class ConsolidacaoEntregasController < ApplicationController classificacoes = @consolidacao.consolidacao_entregas.where(motorista_nome: motorista) { ok: true, - classificadas: classificacoes.count, + classificadas: classificacoes.distinct.count(:tracking_id), por_tipo: classificacoes.group(:tipo).count, valor_total: classificacoes.sum { |e| e.tipo == 'desconto' ? -e.valor_aplicado : e.valor_aplicado }.to_f } diff --git a/app/javascript/controllers/validacao_controller.js b/app/javascript/controllers/validacao_controller.js index e04cf25..7676d66 100644 --- a/app/javascript/controllers/validacao_controller.js +++ b/app/javascript/controllers/validacao_controller.js @@ -40,7 +40,8 @@ export default class extends Controller { tipo: tipo, motorista: this.motoristaValue }) - this.marcarToggleAtivo(tracking, tipo) + // resp.ativo indica se o pilar ficou ligado ou desligado (toggle) + this.setToggle(tracking, tipo, resp.ativo) this.atualizarResumo(resp) } catch (e) { alert("Erro ao classificar entrega. Tente novamente.") @@ -59,7 +60,7 @@ export default class extends Controller { motorista: this.motoristaValue, tracking_ids: [] // vazio = todas }) - this.linhaTargets.forEach(l => this.marcarToggleAtivo(l.dataset.tracking, tipo)) + this.linhaTargets.forEach(l => this.setToggle(l.dataset.tracking, tipo, true)) this.atualizarResumo(resp) } @@ -78,7 +79,7 @@ export default class extends Controller { motorista: this.motoristaValue, tracking_ids: ids }) - ids.forEach(id => this.marcarToggleAtivo(id, tipo)) + ids.forEach(id => this.setToggle(id, tipo, true)) this.checkboxTargets.forEach(c => c.checked = false) this.atualizarResumo(resp) } @@ -99,18 +100,23 @@ export default class extends Controller { return resp.json() } - marcarToggleAtivo(tracking, tipo) { + // Liga/desliga UM pilar (os demais pilares da entrega ficam como estão) + setToggle(tracking, tipo, ativo) { const grupo = this.togglesTargets.find(t => t.dataset.tracking === tracking) if (!grupo) return - grupo.querySelectorAll(".toggle-btn").forEach(b => { - const ativo = b.dataset.tipo === tipo - b.classList.toggle("ring-2", ativo) - b.classList.toggle("ring-green-400", ativo) - b.classList.toggle("scale-105", ativo) - b.classList.toggle("opacity-50", !ativo) - }) + + const btn = grupo.querySelector(`.toggle-btn[data-tipo="${tipo}"]`) + if (btn) { + btn.classList.toggle("ring-2", ativo) + btn.classList.toggle("ring-green-400", ativo) + btn.classList.toggle("scale-105", ativo) + btn.classList.toggle("opacity-50", !ativo) + } + + // a linha está "classificada" se tiver qualquer pilar ligado + const algumAtivo = grupo.querySelectorAll(".toggle-btn.ring-2").length > 0 const linha = this.linhaTargets.find(l => l.dataset.tracking === tracking) - if (linha) linha.dataset.classificada = "1" + if (linha) linha.dataset.classificada = algumAtivo ? "1" : "0" } atualizarResumo(dados) { diff --git a/app/models/consolidacao.rb b/app/models/consolidacao.rb index a0bebba..35dd818 100644 --- a/app/models/consolidacao.rb +++ b/app/models/consolidacao.rb @@ -84,8 +84,10 @@ class Consolidacao < ApplicationRecord ) end + # Entrega conta como classificada se tiver ≥1 pilar (distinct por tracking_id, + # já que agora pode haver vários pilares por entrega). def classificadas_count(motorista) - consolidacao_entregas.where(motorista_nome: motorista).count + consolidacao_entregas.where(motorista_nome: motorista).distinct.count(:tracking_id) end private diff --git a/app/models/consolidacao_entrega.rb b/app/models/consolidacao_entrega.rb index 7c192df..fd98bfe 100644 --- a/app/models/consolidacao_entrega.rb +++ b/app/models/consolidacao_entrega.rb @@ -19,7 +19,9 @@ class ConsolidacaoEntrega < ApplicationRecord 'desconto' => { bg: 'bg-gray-900', text: 'text-white', label: 'Desconto' } }.freeze - validates :tracking_id, presence: true, uniqueness: { scope: :consolidacao_id } + # Uma entrega pode ter vários pilares (Normal + Bônus + Retirada…), + # mas não o mesmo pilar repetido. + validates :tracking_id, presence: true, uniqueness: { scope: %i[consolidacao_id tipo] } validates :motorista_nome, presence: true validates :tipo, presence: true validates :valor_aplicado, presence: true, numericality: { greater_than_or_equal_to: 0 } diff --git a/app/views/consolidacao_entregas/validar.html.erb b/app/views/consolidacao_entregas/validar.html.erb index f4dba69..30f10fc 100644 --- a/app/views/consolidacao_entregas/validar.html.erb +++ b/app/views/consolidacao_entregas/validar.html.erb @@ -5,7 +5,7 @@ data-validacao-url-value="<%= classificar_consolidacao_consolidacao_entregas_path(@consolidacao) %>" data-validacao-massa-url-value="<%= classificar_em_massa_consolidacao_consolidacao_entregas_path(@consolidacao) %>" data-validacao-motorista-value="<%= @motorista %>" - data-validacao-total-value="<%= @entregas.size + @classificacoes.size - (@entregas.count { |e| @classificacoes.key?(e.tracking_id) }) %>"> + data-validacao-total-value="<%= @total_entregas %>"> <%# Header %>