novo pilar tipo: termo (valor 5 no enum), lançado como uma linha por lote com manual: true e uma coluna nova quantidade. O valor_aplicado guarda o total do lote (qtd × preço), então recalcular_motorista! e todas as somas existentes seguem corretas sem mudança — linhas antigas ficam com quantidade = 1.
This commit is contained in:
@@ -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' => '🏢'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user