From 09867c8d39b5f3689b11202c4115adc110b37d4f4f6a62868eee2e361cbab22f Mon Sep 17 00:00:00 2001 From: victor Date: Fri, 26 Jun 2026 09:32:59 -0300 Subject: [PATCH] =?UTF-8?q?novo=20pilar=20tipo:=20termo=20(valor=205=20no?= =?UTF-8?q?=20enum),=20lan=C3=A7ado=20como=20uma=20linha=20por=20lote=20co?= =?UTF-8?q?m=20manual:=20true=20e=20uma=20coluna=20nova=20quantidade.=20O?= =?UTF-8?q?=20valor=5Faplicado=20guarda=20o=20total=20do=20lote=20(qtd=20?= =?UTF-8?q?=C3=97=20pre=C3=A7o),=20ent=C3=A3o=20recalcular=5Fmotorista!=20?= =?UTF-8?q?e=20todas=20as=20somas=20existentes=20seguem=20corretas=20sem?= =?UTF-8?q?=20mudan=C3=A7a=20=E2=80=94=20linhas=20antigas=20ficam=20com=20?= =?UTF-8?q?quantidade=20=3D=201.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Imagem colada (20).png | Bin 0 -> 43049 bytes .../consolidacao_entregas_controller.rb | 30 ++++++- app/controllers/consolidacoes_controller.rb | 3 +- .../apontamento_termo_controller.js | 78 ++++++++++++++++++ app/models/configuracao.rb | 11 ++- app/models/consolidacao.rb | 31 +++++++ app/models/consolidacao_entrega.rb | 8 +- app/services/pdf/extrato_pdf.rb | 4 +- .../relatorio_financeiro_consolidacao_pdf.rb | 3 +- app/services/pdf/relatorio_motorista_pdf.rb | 5 +- .../consolidacao_entregas/revisar.html.erb | 7 +- .../consolidacao_entregas/validar.html.erb | 55 ++++++++++++ app/views/consolidacoes/show.html.erb | 9 +- config/routes.rb | 1 + ...add_quantidade_to_consolidacao_entregas.rb | 9 ++ ...0626000002_add_preco_termo_configuracao.rb | 18 ++++ db/seeds.rb | 1 + 17 files changed, 256 insertions(+), 17 deletions(-) create mode 100644 Imagens para implantação /Imagem colada (20).png create mode 100644 app/javascript/controllers/apontamento_termo_controller.js create mode 100644 db/migrate/20260626000001_add_quantidade_to_consolidacao_entregas.rb create mode 100644 db/migrate/20260626000002_add_preco_termo_configuracao.rb diff --git a/Imagens para implantação /Imagem colada (20).png b/Imagens para implantação /Imagem colada (20).png new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..a1078bdb4114ad3570cb1f5e52280553e649a4f46ce3f1a74232b89968d52db8 GIT binary patch literal 43049 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 e + render_apontamento_erro(e.message) + end + # DELETE /consolidacoes/:consolidacao_id/consolidacao_entregas/remover_apontamento # Remove um apontamento manual — por ?id= (um pilar) ou por ?tracking_id=&motorista= # (todos os pilares daquela nota). Não passa pelo guard de elegibilidade, pois o diff --git a/app/controllers/consolidacoes_controller.rb b/app/controllers/consolidacoes_controller.rb index c640bcd..e215600 100644 --- a/app/controllers/consolidacoes_controller.rb +++ b/app/controllers/consolidacoes_controller.rb @@ -353,7 +353,8 @@ class ConsolidacoesController < ApplicationController authorize @consolidacao, :show? @motorista = params[:motorista] @entregas = @consolidacao.consolidacao_entregas.where(motorista_nome: @motorista) - @resumo = @entregas.group(:tipo).count + # sum(:quantidade) (default 1) conta os termos lançados em lote como N entregas. + @resumo = @entregas.group(:tipo).sum(:quantidade) @total = @entregas.sum { |e| e.desconto? ? -e.valor_aplicado : e.valor_aplicado } render layout: false # renderiza dentro do modal (Turbo Frame) end diff --git a/app/javascript/controllers/apontamento_termo_controller.js b/app/javascript/controllers/apontamento_termo_controller.js new file mode 100644 index 0000000..aea439d --- /dev/null +++ b/app/javascript/controllers/apontamento_termo_controller.js @@ -0,0 +1,78 @@ +// app/javascript/controllers/apontamento_termo_controller.js +// Stimulus — Entrega de termo. Lança um lote de N termos para o motorista da tela. +// Entrega sem NF nem código de rastreio: só a quantidade (stepper − N +), a um +// preço fixo configurável. + +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static targets = ["modal", "quantidade", "erro"] + static values = { apontarTermoUrl: String, motorista: String } + + abrir() { + this.erroTarget.classList.add("hidden") + this.quantidadeTarget.value = "1" + this.modalTarget.classList.remove("hidden") + } + + fechar() { + this.modalTarget.classList.add("hidden") + } + + // Fecha ao clicar no fundo (fora do card) + fundo(event) { + if (event.target === this.modalTarget) this.fechar() + } + + // Stepper + mais() { + this.quantidadeTarget.value = String(this.qtdAtual() + 1) + } + + menos() { + this.quantidadeTarget.value = String(Math.max(1, this.qtdAtual() - 1)) + } + + qtdAtual() { + const n = parseInt(this.quantidadeTarget.value, 10) + return Number.isFinite(n) && n > 0 ? n : 1 + } + + async adicionar(event) { + event?.preventDefault() + + const quantidade = this.qtdAtual() + const motorista = this.motoristaValue.trim() + if (!motorista) { this.mostrarErro("Motorista não identificado."); return } + + const btn = event.currentTarget + btn.disabled = true + try { + const resp = await fetch(this.apontarTermoUrlValue, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content + }, + body: JSON.stringify({ motorista: motorista, quantidade: quantidade }) + }) + const data = await resp.json() + if (!resp.ok || data.ok === false) { + this.mostrarErro(data.erro || "Não foi possível adicionar as entregas de termo.") + return + } + // Recarrega para refletir o valor atualizado do motorista. + window.location.reload() + } catch (e) { + this.mostrarErro("Erro ao adicionar as entregas de termo. Tente novamente.") + } finally { + btn.disabled = false + } + } + + mostrarErro(msg) { + this.erroTarget.textContent = msg + this.erroTarget.classList.remove("hidden") + } +} diff --git a/app/models/configuracao.rb b/app/models/configuracao.rb index 22d1e51..56ae369 100644 --- a/app/models/configuracao.rb +++ b/app/models/configuracao.rb @@ -9,6 +9,7 @@ class Configuracao < ApplicationRecord preco_bonus preco_desconto preco_extraordinaria + preco_termo notificacao_whatsapp notificacao_email empresa_nome @@ -21,6 +22,7 @@ class Configuracao < ApplicationRecord preco_bonus preco_desconto preco_extraordinaria + preco_termo ].freeze validates :chave, presence: true, inclusion: { in: CHAVES }, uniqueness: true @@ -52,6 +54,10 @@ class Configuracao < ApplicationRecord valor('preco_extraordinaria').to_f end + def self.preco_termo + valor('preco_termo').to_f + end + # Mapa usado pelo DashboardController (Fase 3) def self.mapa_de_precos { @@ -59,7 +65,8 @@ class Configuracao < ApplicationRecord retirada: preco_retirada, bonus: preco_bonus, desconto: preco_desconto, - extraordinaria: preco_extraordinaria + extraordinaria: preco_extraordinaria, + termo: preco_termo } end @@ -69,6 +76,7 @@ class Configuracao < ApplicationRecord 'preco_bonus' => 'Bônus', 'preco_desconto' => 'Desconto', 'preco_extraordinaria' => 'Entrega Extraordinária', + 'preco_termo' => 'Entrega de Termo', 'notificacao_whatsapp' => 'Notificação WhatsApp', 'notificacao_email' => 'Notificação E-mail', 'empresa_nome' => 'Nome da Empresa' @@ -80,6 +88,7 @@ class Configuracao < ApplicationRecord 'preco_bonus' => '⭐', 'preco_desconto' => '⚠️', 'preco_extraordinaria' => '✨', + 'preco_termo' => '📄', 'notificacao_whatsapp' => '💬', 'notificacao_email' => '✉️', 'empresa_nome' => '🏢' diff --git a/app/models/consolidacao.rb b/app/models/consolidacao.rb index f80dbbf..45b3a15 100644 --- a/app/models/consolidacao.rb +++ b/app/models/consolidacao.rb @@ -244,6 +244,37 @@ class Consolidacao < ApplicationRecord nome end + # ── Entrega de termo ──────────────────────────────────────── + # Lança um LOTE de N "entregas de termo" — entregas sem NF nem código de rastreio + # para atrelar (só motorista + quantidade, a um preço fixo configurável). Fica + # numa única linha (manual: true): quantidade guarda o N e valor_aplicado guarda + # o total do lote, então recalcular_motorista! e demais somas seguem inalteradas. + def adicionar_termos!(motorista:, quantidade:, user:) + nome = motorista.to_s.strip + raise ArgumentError, 'Informe o motorista do termo.' if nome.blank? + + qtd = quantidade.to_i + raise ArgumentError, 'Informe uma quantidade válida de termos.' if qtd < 1 + + transaction do + consolidacao_motoristas.find_or_create_by!(motorista_nome: nome) + + consolidacao_entregas.create!( + tracking_id: "TERMO-#{SecureRandom.uuid}", # sintético: não há Entrega/NF + tipo: 'termo', + motorista_nome: nome, + quantidade: qtd, + valor_aplicado: qtd * ConsolidacaoEntrega.valor_para('termo'), # total do lote + manual: true, + created_by: user&.id + ) + + recalcular_motorista!(nome) + end + + nome + end + # Recalcula o valor de um motorista (soma dos pilares, desconto subtrai) e o # total da consolidação. Fonte única usada pelo wizard e pelos apontamentos. def recalcular_motorista!(nome) diff --git a/app/models/consolidacao_entrega.rb b/app/models/consolidacao_entrega.rb index 980e58e..df93357 100644 --- a/app/models/consolidacao_entrega.rb +++ b/app/models/consolidacao_entrega.rb @@ -14,7 +14,8 @@ class ConsolidacaoEntrega < ApplicationRecord retirada: 1, bonus: 2, desconto: 3, - extraordinaria: 4 + extraordinaria: 4, + termo: 5 } TIPO_CORES = { @@ -22,7 +23,8 @@ class ConsolidacaoEntrega < ApplicationRecord 'retirada' => { bg: 'bg-orange-800', text: 'text-white', label: 'Retirada' }, 'bonus' => { bg: 'bg-white border border-orange-500', text: 'text-black', label: 'Bônus' }, 'desconto' => { bg: 'bg-gray-900', text: 'text-white', label: 'Desconto' }, - 'extraordinaria' => { bg: 'bg-purple-600', text: 'text-white', label: 'Entrega Extraordinária' } + 'extraordinaria' => { bg: 'bg-purple-600', text: 'text-white', label: 'Entrega Extraordinária' }, + 'termo' => { bg: 'bg-blue-600', text: 'text-white', label: 'Entrega de Termo' } }.freeze # Uma entrega pode ter vários pilares (Normal + Bônus + Retirada…), @@ -31,6 +33,7 @@ class ConsolidacaoEntrega < ApplicationRecord validates :motorista_nome, presence: true validates :tipo, presence: true validates :valor_aplicado, presence: true, numericality: { greater_than_or_equal_to: 0 } + validates :quantidade, numericality: { greater_than: 0 } # Busca a entrega original (leitura do banco existente) def entrega_original @@ -50,6 +53,7 @@ class ConsolidacaoEntrega < ApplicationRecord when 'bonus' then Configuracao.preco_bonus when 'desconto' then Configuracao.preco_desconto when 'extraordinaria' then Configuracao.preco_extraordinaria + when 'termo' then Configuracao.preco_termo else 0 end end diff --git a/app/services/pdf/extrato_pdf.rb b/app/services/pdf/extrato_pdf.rb index 54a7d07..0bbee3d 100644 --- a/app/services/pdf/extrato_pdf.rb +++ b/app/services/pdf/extrato_pdf.rb @@ -46,7 +46,9 @@ module Pdf secao "PROVENTOS E DESCONTOS" - resumo = @entregas.group(:tipo).count + # `quantidade` (default 1) conta as entregas de termo lançadas em lote; + # para os demais pilares equivale ao número de linhas. + resumo = @entregas.group(:tipo).sum(:quantidade) # Lista os quatro pilares sempre (Normal, Retirada, Bônus, Desconto), # mesmo zerados, para o motorista ver o descritivo completo. por_tipo = ConsolidacaoEntrega::TIPO_CORES.map do |tipo, cfg| diff --git a/app/services/pdf/relatorio_financeiro_consolidacao_pdf.rb b/app/services/pdf/relatorio_financeiro_consolidacao_pdf.rb index 60a8f47..69428e2 100644 --- a/app/services/pdf/relatorio_financeiro_consolidacao_pdf.rb +++ b/app/services/pdf/relatorio_financeiro_consolidacao_pdf.rb @@ -70,7 +70,8 @@ module Pdf def tabela_por_tipo soma = @entregas.reorder(nil).group(:tipo).sum(:valor_aplicado) - qtd = @entregas.reorder(nil).group(:tipo).count + # `quantidade` (default 1) conta os termos lançados em lote como N entregas. + qtd = @entregas.reorder(nil).group(:tipo).sum(:quantidade) linhas = [['Tipo', 'Quantidade', 'Valor']] ConsolidacaoEntrega::TIPO_CORES.each do |tipo, cfg| diff --git a/app/services/pdf/relatorio_motorista_pdf.rb b/app/services/pdf/relatorio_motorista_pdf.rb index 9708d32..afd5b71 100644 --- a/app/services/pdf/relatorio_motorista_pdf.rb +++ b/app/services/pdf/relatorio_motorista_pdf.rb @@ -37,7 +37,7 @@ module Pdf original&.vehicle.presence || (e.manual? ? 'manual' : '—'), original ? "NF #{original.numero_nf}" : (e.nf_manual.present? ? "NF #{e.nf_manual}" : '—'), original ? original.address.to_s : (e.obs_manual.presence || '—'), - e.tipo_cor[:label], + e.termo? && e.quantidade > 1 ? "#{e.tipo_cor[:label]} ×#{e.quantidade}" : e.tipo_cor[:label], (e.desconto? ? '-' : '') + moeda(e.valor_aplicado) ] end @@ -67,7 +67,8 @@ module Pdf secao "RESUMO" # reorder(nil): remove o .order(:created_at) da relação — senão o Postgres # recusa "GROUP BY tipo ORDER BY created_at" (PG::GroupingError → 500). - resumo = @entregas.reorder(nil).group(:tipo).count + # sum(:quantidade) (default 1) conta os termos lançados em lote como N entregas. + resumo = @entregas.reorder(nil).group(:tipo).sum(:quantidade) total = @entregas.sum { |e| e.desconto? ? -e.valor_aplicado : e.valor_aplicado } resumo_linhas = [['Tipo', 'Quantidade']] diff --git a/app/views/consolidacao_entregas/revisar.html.erb b/app/views/consolidacao_entregas/revisar.html.erb index 52bd067..fd3161a 100644 --- a/app/views/consolidacao_entregas/revisar.html.erb +++ b/app/views/consolidacao_entregas/revisar.html.erb @@ -12,13 +12,14 @@ <%# Resumo por tipo %> -

+
<% [ ['entrega_normal', 'Normal', 'bg-orange-500 text-black'], ['retirada', 'Retirada', 'bg-orange-800 text-white'], ['bonus', 'Bônus', 'bg-white text-black'], ['desconto', 'Desconto', 'bg-black text-white border border-gray-700'], - ['extraordinaria', 'Extraordinária', 'bg-purple-600 text-white'] + ['extraordinaria', 'Extraordinária', 'bg-purple-600 text-white'], + ['termo', 'Termo', 'bg-blue-600 text-white'] ].each do |tipo, label, cores| %>

<%= @resumo[tipo] || 0 %>

@@ -66,7 +67,7 @@ <%= c.entrega_original&.address.presence || endereco_manual.presence || '—' %> - <%= c.tipo_cor[:label] %> + <%= c.tipo_cor[:label] %><% if c.termo? && c.quantidade > 1 %> ×<%= c.quantidade %><% end %> <% if c.manual? %> ➕ Apontamento diff --git a/app/views/consolidacao_entregas/validar.html.erb b/app/views/consolidacao_entregas/validar.html.erb index 2cfe31a..78ccd40 100644 --- a/app/views/consolidacao_entregas/validar.html.erb +++ b/app/views/consolidacao_entregas/validar.html.erb @@ -197,6 +197,61 @@
+ + <%# Entrega de termo — entrega SEM nota fiscal nem código; só motorista + quantidade. %> +
+ + + <%# Modal %> + +
<% end %>
diff --git a/app/views/consolidacoes/show.html.erb b/app/views/consolidacoes/show.html.erb index 8dcf34f..2ddc59d 100644 --- a/app/views/consolidacoes/show.html.erb +++ b/app/views/consolidacoes/show.html.erb @@ -159,13 +159,14 @@ <% @apontamentos.each do |(motorista, _tracking), pilares| %> - <% entrega = pilares.first.entrega_original %> + <% eh_termo = pilares.first.termo? %> + <% entrega = eh_termo ? nil : pilares.first.entrega_original %> <% nf_exibida = entrega&.numero_nf || pilares.first.nf_manual %> <% obs_manual = pilares.first.obs_manual %> <% total = pilares.sum { |p| p.desconto? ? -p.valor_aplicado : p.valor_aplicado } %> -

NF <%= nf_exibida.presence || '—' %>

+

<%= eh_termo ? '📄 Entrega de termo' : "NF #{nf_exibida.presence || '—'}" %>

<%= motorista %><% if entrega&.vehicle.present? %> · <%= entrega.vehicle %><% end %> <% if entrega.nil? && obs_manual.present? %> · <%= obs_manual %><% end %> @@ -174,7 +175,7 @@

<% pilares.each do |p| %> - <%= p.tipo_cor[:label] %> + <%= p.tipo_cor[:label] %><% if p.termo? && p.quantidade > 1 %> ×<%= p.quantidade %><% end %> <% end %>
@@ -184,7 +185,7 @@ <%= button_to '✕ Remover', remover_apontamento_consolidacao_consolidacao_entregas_path(@consolidacao, tracking_id: pilares.first.tracking_id, motorista: motorista), method: :delete, - form: { data: { turbo_confirm: "Remover o apontamento da NF #{nf_exibida.presence || '—'} de #{motorista}?" } }, + form: { data: { turbo_confirm: eh_termo ? "Remover a entrega de termo de #{motorista}?" : "Remover o apontamento da NF #{nf_exibida.presence || '—'} de #{motorista}?" } }, class: 'text-gray-400 hover:text-red-400 border border-[#2a2a2a] hover:border-red-500/50 px-3 py-2 rounded-lg text-xs min-h-[40px]' %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index e3ad29c..95f1d2a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -59,6 +59,7 @@ Rails.application.routes.draw do get :buscar_nf # JSON — busca a NF na SimpleRoute (apontamento manual) post :apontar # cria apontamento manual a partir da NF post :apontar_manual # apontamento 100% manual (sem rastreio) + post :apontar_termo # lança N entregas de termo (sem NF/código) delete :remover_apontamento # remove um apontamento manual (por id) end end diff --git a/db/migrate/20260626000001_add_quantidade_to_consolidacao_entregas.rb b/db/migrate/20260626000001_add_quantidade_to_consolidacao_entregas.rb new file mode 100644 index 0000000..c406dc2 --- /dev/null +++ b/db/migrate/20260626000001_add_quantidade_to_consolidacao_entregas.rb @@ -0,0 +1,9 @@ +# Adiciona `quantidade` aos pilares da consolidação. Usado pelas "entregas de +# termo" (lote de N termos lançado numa única linha). Linhas existentes/demais +# pilares ficam com quantidade = 1 e seguem inalteradas — o valor_aplicado já +# guarda o total da linha, então as somas existentes continuam corretas. +class AddQuantidadeToConsolidacaoEntregas < ActiveRecord::Migration[7.1] + def change + add_column :consolidacao_entregas, :quantidade, :integer, null: false, default: 1 + end +end diff --git a/db/migrate/20260626000002_add_preco_termo_configuracao.rb b/db/migrate/20260626000002_add_preco_termo_configuracao.rb new file mode 100644 index 0000000..13fb9d5 --- /dev/null +++ b/db/migrate/20260626000002_add_preco_termo_configuracao.rb @@ -0,0 +1,18 @@ +# Cria a configuração de preço "Entrega de Termo" em bancos já existentes, para +# que apareça na tela de Configurações. Idempotente — não sobrescreve se o admin +# já tiver definido um valor. +class AddPrecoTermoConfiguracao < ActiveRecord::Migration[7.1] + def up + return if Configuracao.exists?(chave: 'preco_termo') + + Configuracao.create!( + chave: 'preco_termo', + valor: '15.00', + descricao: 'Valor pago por entrega de termo (R$)' + ) + end + + def down + Configuracao.where(chave: 'preco_termo').delete_all + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 3112a42..d0d1e9a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -29,6 +29,7 @@ configs = [ { chave: 'preco_bonus', valor: '10.00', descricao: 'Valor de bônus por meta/critério (R$)' }, { chave: 'preco_desconto', valor: '15.00', descricao: 'Valor descontado por problema (R$)' }, { chave: 'preco_extraordinaria', valor: '25.00', descricao: 'Valor coringa para entregas fora do planejamento (R$)' }, + { chave: 'preco_termo', valor: '15.00', descricao: 'Valor pago por entrega de termo (R$)' }, { chave: 'notificacao_whatsapp', valor: 'false', descricao: 'Notificações via WhatsApp (true/false)' }, { chave: 'notificacao_email', valor: 'false', descricao: 'Notificações via e-mail (true/false)' }, { chave: 'empresa_nome', valor: 'Reem Transporte', descricao: 'Nome da empresa exibido no sistema' },