72 lines
2.7 KiB
Ruby
72 lines
2.7 KiB
Ruby
# app/models/consolidacao_veiculo.rb
|
|
# Unidade de FECHAMENTO por veículo dentro de uma consolidação. Espelha os padrões
|
|
# de ConsolidacaoMotorista (arquivamento reversível + valor_total recalculado dos
|
|
# pilares), mas o que ela controla é o estado "fechado/consolidado" de cada carro.
|
|
# O PAGAMENTO continua no motorista (ConsolidacaoMotorista) — ver [[consolidacao]].
|
|
class ConsolidacaoVeiculo < ApplicationRecord
|
|
# Nome da tabela fixado (mesmo motivo dos outros: inflector pt-BR).
|
|
self.table_name = 'consolidacao_veiculos'
|
|
|
|
# Bucket dos lançamentos sem veículo (termo/apontamento manual legado). Igual ao
|
|
# sentinel usado no controller e na migração — NULL quebraria o índice único.
|
|
SEM_VEICULO = '(sem veículo)'
|
|
|
|
belongs_to :consolidacao
|
|
belongs_to :fechador, class_name: 'User', foreign_key: :fechado_por, optional: true
|
|
belongs_to :arquivador, class_name: 'User', foreign_key: :arquivado_por, optional: true
|
|
|
|
validates :motorista_nome, presence: true
|
|
validates :vehicle, presence: true
|
|
validates :vehicle, uniqueness: { scope: %i[consolidacao_id motorista_nome] }
|
|
|
|
before_save :recalcular_valor
|
|
|
|
# ── Fechamento (consolidação do veículo, reversível) ────────
|
|
scope :fechados, -> { where.not(fechado_em: nil) }
|
|
scope :abertos, -> { where(fechado_em: nil) }
|
|
|
|
# ── Arquivamento (reversível) — sai do gate, mantém os dados ─
|
|
scope :ativos, -> { where(arquivado_em: nil) }
|
|
scope :arquivados, -> { where.not(arquivado_em: nil) }
|
|
|
|
def fechado?
|
|
fechado_em.present?
|
|
end
|
|
|
|
def arquivado?
|
|
arquivado_em.present?
|
|
end
|
|
|
|
# update_columns: não dispara before_save (o valor já está correto no fechamento).
|
|
def fechar!(user)
|
|
update_columns(fechado_em: Time.current, fechado_por: user&.id, updated_at: Time.current)
|
|
end
|
|
|
|
def reabrir!(_user)
|
|
update_columns(fechado_em: nil, fechado_por: nil, updated_at: Time.current)
|
|
end
|
|
|
|
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
|
|
|
|
# Soma dos pilares deste (motorista + veículo). Mesma regra do ConsolidacaoMotorista:
|
|
# o valor_aplicado capturado na classificação é a fonte da verdade e o desconto
|
|
# subtrai. O bucket "(sem veículo)" casa os pilares com vehicle NULL/vazio.
|
|
def recalcular_valor
|
|
self.valor_total = escopo_entregas
|
|
.sum { |e| e.desconto? ? -e.valor_aplicado : e.valor_aplicado }
|
|
end
|
|
|
|
private
|
|
|
|
def escopo_entregas
|
|
rel = consolidacao.consolidacao_entregas.where(motorista_nome: motorista_nome)
|
|
vehicle == SEM_VEICULO ? rel.where(vehicle: [nil, '']) : rel.where(vehicle: vehicle)
|
|
end
|
|
end
|