Adição do botão de entrega manual
This commit is contained in:
@@ -33,17 +33,17 @@ class Consolidacao < ApplicationRecord
|
||||
# ── Filtro por status de pagamento (derivado dos motoristas) ─
|
||||
# pago_em NÃO-nulo conta como pago; COUNT(pago_em) ignora os NULL.
|
||||
scope :pagamento_pago, -> {
|
||||
where(id: ConsolidacaoMotorista.group(:consolidacao_id)
|
||||
where(id: ConsolidacaoMotorista.ativos.group(:consolidacao_id)
|
||||
.having('COUNT(*) > 0 AND COUNT(*) = COUNT(pago_em)')
|
||||
.select(:consolidacao_id))
|
||||
}
|
||||
scope :pagamento_pendente, -> {
|
||||
where(id: ConsolidacaoMotorista.group(:consolidacao_id)
|
||||
where(id: ConsolidacaoMotorista.ativos.group(:consolidacao_id)
|
||||
.having('COUNT(pago_em) = 0')
|
||||
.select(:consolidacao_id))
|
||||
}
|
||||
scope :pagamento_parcial, -> {
|
||||
where(id: ConsolidacaoMotorista.group(:consolidacao_id)
|
||||
where(id: ConsolidacaoMotorista.ativos.group(:consolidacao_id)
|
||||
.having('COUNT(pago_em) > 0 AND COUNT(pago_em) < COUNT(*)')
|
||||
.select(:consolidacao_id))
|
||||
}
|
||||
@@ -91,21 +91,21 @@ class Consolidacao < ApplicationRecord
|
||||
# ── Pagamento (status derivado dos motoristas da consolidação) ──
|
||||
# :pendente (nenhum pago) · :pago (todos pagos) · :parcial (alguns).
|
||||
def status_pagamento
|
||||
total = consolidacao_motoristas.count
|
||||
total = consolidacao_motoristas.ativos.count
|
||||
return :pendente if total.zero?
|
||||
|
||||
pagos = consolidacao_motoristas.pagos.count
|
||||
pagos = consolidacao_motoristas.ativos.pagos.count
|
||||
return :pendente if pagos.zero?
|
||||
|
||||
pagos >= total ? :pago : :parcial
|
||||
end
|
||||
|
||||
def valor_pago
|
||||
consolidacao_motoristas.pagos.sum(:valor_total)
|
||||
consolidacao_motoristas.ativos.pagos.sum(:valor_total)
|
||||
end
|
||||
|
||||
def valor_pendente
|
||||
consolidacao_motoristas.pendentes.sum(:valor_total)
|
||||
consolidacao_motoristas.ativos.pendentes.sum(:valor_total)
|
||||
end
|
||||
|
||||
def finalizar!(user)
|
||||
@@ -122,7 +122,7 @@ class Consolidacao < ApplicationRecord
|
||||
# classificadas. (Antes era uma soma agregada com >=, que mascarava motoristas
|
||||
# pendentes quando outro tinha entregas a mais.)
|
||||
def todas_entregas_classificadas?
|
||||
consolidacao_motoristas.all? do |cm|
|
||||
consolidacao_motoristas.ativos.all? do |cm|
|
||||
total = entregas_elegiveis_count(cm.motorista_nome)
|
||||
total.zero? || classificadas_count(cm.motorista_nome) >= total
|
||||
end
|
||||
@@ -134,7 +134,7 @@ class Consolidacao < ApplicationRecord
|
||||
end
|
||||
|
||||
def total_entregas_estimadas
|
||||
@total_entregas_estimadas ||= consolidacao_motoristas.sum do |cm|
|
||||
@total_entregas_estimadas ||= consolidacao_motoristas.ativos.sum do |cm|
|
||||
entregas_elegiveis_count(cm.motorista_nome)
|
||||
end
|
||||
end
|
||||
@@ -201,6 +201,49 @@ class Consolidacao < ApplicationRecord
|
||||
motorista
|
||||
end
|
||||
|
||||
# ── Apontamento 100% manual ─────────────────────────────────
|
||||
# Lança uma entrega à mão SEM consultar a base de rastreio. Caso de uso: um
|
||||
# motorista foi até o local mas a NF ficou registrada com outro motorista no
|
||||
# rastreio — então a busca por NF nunca o encontra, mas ele também recebe.
|
||||
# O motorista vem digitado (não de uma Entrega) e é incluído se ainda não
|
||||
# estiver. tracking_id é sintético (não há Entrega), e a NF/observação ficam
|
||||
# guardadas em nf_manual/obs_manual.
|
||||
def adicionar_apontamento_manual!(motorista:, tipos:, user:, nf: nil, obs: nil, valor_extra: nil)
|
||||
tipos_validos = Array(tipos).map(&:to_s).select { |t| ConsolidacaoEntrega.tipos.key?(t) }.uniq
|
||||
raise ArgumentError, 'Selecione ao menos uma classificação.' if tipos_validos.empty?
|
||||
|
||||
nome = motorista.to_s.strip
|
||||
raise ArgumentError, 'Informe o motorista do apontamento.' if nome.blank?
|
||||
|
||||
tracking = "MAN-#{SecureRandom.uuid}" # sintético: agrupa os pilares como UMA entrega
|
||||
|
||||
transaction do
|
||||
consolidacao_motoristas.find_or_create_by!(motorista_nome: nome)
|
||||
|
||||
tipos_validos.each do |tipo|
|
||||
valor = if tipo == 'extraordinaria' && valor_extra.present?
|
||||
valor_extra
|
||||
else
|
||||
ConsolidacaoEntrega.valor_para(tipo)
|
||||
end
|
||||
consolidacao_entregas.create!(
|
||||
tracking_id: tracking,
|
||||
tipo: tipo,
|
||||
motorista_nome: nome,
|
||||
valor_aplicado: valor,
|
||||
manual: true,
|
||||
nf_manual: nf.presence,
|
||||
obs_manual: obs.presence,
|
||||
created_by: user&.id
|
||||
)
|
||||
end
|
||||
|
||||
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)
|
||||
@@ -211,7 +254,7 @@ class Consolidacao < ApplicationRecord
|
||||
e.desconto? ? -e.valor_aplicado : e.valor_aplicado
|
||||
end
|
||||
cm.update_column(:valor_total, total)
|
||||
update_column(:valor_total, consolidacao_motoristas.sum(:valor_total))
|
||||
update_column(:valor_total, consolidacao_motoristas.ativos.sum(:valor_total))
|
||||
end
|
||||
|
||||
private
|
||||
@@ -222,6 +265,6 @@ class Consolidacao < ApplicationRecord
|
||||
end
|
||||
|
||||
def recalcular_valor_total
|
||||
self.valor_total = consolidacao_motoristas.sum(:valor_total)
|
||||
self.valor_total = consolidacao_motoristas.ativos.sum(:valor_total)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,8 @@ class ConsolidacaoMotorista < ApplicationRecord
|
||||
self.table_name = 'consolidacao_motoristas'
|
||||
|
||||
belongs_to :consolidacao
|
||||
belongs_to :pagador, class_name: 'User', foreign_key: :pago_por, optional: true
|
||||
belongs_to :pagador, class_name: 'User', foreign_key: :pago_por, optional: true
|
||||
belongs_to :arquivador, class_name: 'User', foreign_key: :arquivado_por, optional: true
|
||||
has_many :consolidacao_entregas,
|
||||
->(cm) { where(motorista_nome: cm.motorista_nome) },
|
||||
foreign_key: :consolidacao_id,
|
||||
@@ -20,6 +21,27 @@ class ConsolidacaoMotorista < ApplicationRecord
|
||||
scope :pagos, -> { where.not(pago_em: nil) }
|
||||
scope :pendentes, -> { where(pago_em: nil) }
|
||||
|
||||
# ── Arquivamento (reversível) ───────────────────────────────
|
||||
# Um motorista arquivado sai dos totais/pagamento/gate da consolidação, mas
|
||||
# os dados são mantidos e podem ser restaurados.
|
||||
scope :ativos, -> { where(arquivado_em: nil) }
|
||||
scope :arquivados, -> { where.not(arquivado_em: nil) }
|
||||
|
||||
def arquivado?
|
||||
arquivado_em.present?
|
||||
end
|
||||
|
||||
# update_columns: não dispara o before_save :recalcular_valor (que recalcula o
|
||||
# valor do PRÓPRIO motorista). O total da CONSOLIDAÇÃO é recalculado pelo
|
||||
# controller, que só soma os motoristas ativos.
|
||||
def arquivar!(user)
|
||||
update_columns(arquivado_em: Time.current, arquivado_por: user&.id, updated_at: Time.current)
|
||||
end
|
||||
|
||||
def desarquivar!(_user)
|
||||
update_columns(arquivado_em: nil, arquivado_por: nil, updated_at: Time.current)
|
||||
end
|
||||
|
||||
def pago?
|
||||
pago_em.present?
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user