# Unidade de FECHAMENTO por veículo dentro de uma consolidação. Espelha o padrão de # consolidacao_motoristas (arquivamento reversível + valor_total), mas o que ela # controla é o estado "fechado/consolidado" de cada carro — o PAGAMENTO continua no # motorista (consolidacao_motoristas). Assim dá para consolidar um veículo pronto # sem esperar os outros. O bucket sem veículo (termo/apontamento manual legado) usa # o sentinel '(sem veículo)' para que o índice único funcione (NULL quebraria). class CreateConsolidacaoVeiculos < ActiveRecord::Migration[7.1] SEM_VEICULO = '(sem veículo)' def up unless table_exists?(:consolidacao_veiculos) create_table :consolidacao_veiculos do |t| t.references :consolidacao, null: false, foreign_key: { to_table: :consolidacoes } t.string :motorista_nome, null: false t.string :vehicle, null: false t.decimal :valor_total, precision: 10, scale: 2, default: 0 t.datetime :fechado_em # NULL = aberto (ainda não consolidado) t.integer :fechado_por t.datetime :arquivado_em # NULL = ativo t.integer :arquivado_por t.timestamps end add_index :consolidacao_veiculos, %i[consolidacao_id motorista_nome vehicle], unique: true, name: 'idx_consolidacao_veiculo_unique' add_index :consolidacao_veiculos, :arquivado_em end # Backfill: uma linha por (consolidação · motorista · veículo) já classificado, # somando o valor (desconto = tipo 3 subtrai). Consolidações já finalizadas # (status 1) nascem FECHADAS, herdando quem/quando finalizou — para não # "reabrir" o que já foi pago. say_with_time 'backfill consolidacao_veiculos a partir das entregas' do execute(<<~SQL.squish) INSERT INTO consolidacao_veiculos (consolidacao_id, motorista_nome, vehicle, valor_total, fechado_em, fechado_por, created_at, updated_at) SELECT ce.consolidacao_id, ce.motorista_nome, COALESCE(NULLIF(ce.vehicle, ''), '#{SEM_VEICULO}') AS vehicle, COALESCE(SUM(CASE WHEN ce.tipo = 3 THEN -ce.valor_aplicado ELSE ce.valor_aplicado END), 0) AS valor_total, CASE WHEN c.status = 1 THEN c.finalizado_em END AS fechado_em, CASE WHEN c.status = 1 THEN c.finalizado_por END AS fechado_por, NOW(), NOW() FROM consolidacao_entregas ce JOIN consolidacoes c ON c.id = ce.consolidacao_id GROUP BY ce.consolidacao_id, ce.motorista_nome, COALESCE(NULLIF(ce.vehicle, ''), '#{SEM_VEICULO}'), c.status, c.finalizado_em, c.finalizado_por SQL end end def down drop_table :consolidacao_veiculos if table_exists?(:consolidacao_veiculos) end end