Correção de itens que estão fora do plano valores no dash principal
This commit is contained in:
@@ -16,11 +16,19 @@ module Analytics
|
||||
# Teto da listagem na tela (os totais continuam contando tudo).
|
||||
LIMITE = 300
|
||||
|
||||
# Colunas do espelho que podem carregar o nome do PLANO/rota de origem
|
||||
# ("(Avulsa)", "INCLUSÃO"...). Nem toda base tem todas — as ausentes viram
|
||||
# NULL, mesmo padrão de selects_gade em OperacaoMetricas. Whitelist fixa:
|
||||
# nada aqui vem do usuário.
|
||||
COLUNAS_PLANO = %w[title notes comments route_id].freeze
|
||||
# Colunas extras do espelho que a tela usa. Nem toda base tem todas — as
|
||||
# ausentes viram NULL, mesmo padrão de selects_gade em OperacaoMetricas.
|
||||
# Whitelist fixa: nada aqui vem do usuário.
|
||||
COLUNAS_EXTRA = %w[title notes comments route_id].freeze
|
||||
|
||||
# Candidatas ao nome do PLANO de origem ("(Avulsa)", "INCLUSÃO"...), na ordem
|
||||
# de preferência.
|
||||
#
|
||||
# ⚠️ `title` NÃO entra aqui: conferido em 24/08/2026 com dado real, ele traz
|
||||
# "NF 89096 - KAIQUE TAUAN DA SILVA" — o formato da coluna A da planilha de
|
||||
# importação (`NF {nota_fiscal} - {nome_completo}`), ou seja, o destinatário.
|
||||
# Agrupar por ele daria um grupo por NF, o que não informa nada.
|
||||
COLUNAS_PLANO = %w[notes comments route_id].freeze
|
||||
|
||||
def initialize(inicio:, fim:)
|
||||
@inicio = inicio&.to_date
|
||||
@@ -61,21 +69,48 @@ module Analytics
|
||||
total.positive?
|
||||
end
|
||||
|
||||
# Agrupamento por plano de origem, quando a base tiver alguma das colunas de
|
||||
# COLUNAS_PLANO preenchida. Serve para separar "(Avulsa)" de "INCLUSÃO".
|
||||
def por_plano
|
||||
linhas.group_by { |r| plano(r) }
|
||||
.map { |nome, rows| { nome: nome, total: rows.size } }
|
||||
.sort_by { |h| -h[:total] }
|
||||
end
|
||||
|
||||
# Rótulo do plano de uma linha: primeira coluna de COLUNAS_PLANO preenchida.
|
||||
# Nome do plano de origem: primeira coluna de COLUNAS_PLANO preenchida.
|
||||
# nil quando o espelho não guarda essa informação.
|
||||
def plano(registro)
|
||||
COLUNAS_PLANO.each do |coluna|
|
||||
valor = registro[coluna].to_s.strip
|
||||
return valor if valor.present?
|
||||
end
|
||||
'SEM PLANO IDENTIFICADO'
|
||||
nil
|
||||
end
|
||||
|
||||
# Destinatário/título da visita (coluna `title` do espelho).
|
||||
def titulo(registro)
|
||||
registro['title'].to_s.strip.presence
|
||||
end
|
||||
|
||||
def plano_identificado?
|
||||
linhas.any? { |r| plano(r) }
|
||||
end
|
||||
|
||||
# Quebra do painel em grupos. Quando o espelho traz o plano, separa
|
||||
# "(Avulsa)" de "INCLUSÃO"; quando não traz, agrupar por título daria um
|
||||
# grupo por NF — então cai para a unidade, que ainda diz algo útil.
|
||||
# Devolve [rótulo do agrupamento, [{ nome:, total: }, ...]].
|
||||
def agrupamento
|
||||
if plano_identificado?
|
||||
['Plano', agrupar { |r| plano(r) || 'SEM PLANO' }]
|
||||
else
|
||||
['Unidade', agrupar { |r| r['contact_name'].to_s.strip.presence || 'SEM UNIDADE' }]
|
||||
end
|
||||
end
|
||||
|
||||
# Rótulo legível do resultado da última visita.
|
||||
RESULTADOS = { 'completed' => 'Entregue', 'failed' => 'Não entregue',
|
||||
'pending' => 'Em aberto', 'in_progress' => 'Em rota' }.freeze
|
||||
|
||||
def resultado(registro)
|
||||
status = registro['status'].to_s
|
||||
RESULTADOS[status] || status.presence || 'sem status'
|
||||
end
|
||||
|
||||
def sucesso?(registro)
|
||||
registro['status'] == 'completed'
|
||||
end
|
||||
|
||||
def listagem
|
||||
@@ -88,6 +123,12 @@ module Analytics
|
||||
|
||||
private
|
||||
|
||||
def agrupar
|
||||
linhas.group_by { |r| yield(r) }
|
||||
.map { |nome, rows| { nome: nome, total: rows.size } }
|
||||
.sort_by { |h| -h[:total] }
|
||||
end
|
||||
|
||||
def ordem_visita(registro)
|
||||
t = registro['checkout'].presence&.to_time
|
||||
[t ? 1 : 0, t || Time.at(0)]
|
||||
@@ -124,11 +165,11 @@ module Analytics
|
||||
conn.select_all(sql).to_a
|
||||
end
|
||||
|
||||
# Colunas de plano que existirem de fato; as demais viram NULL com o mesmo
|
||||
# Colunas extras que existirem de fato; as demais viram NULL com o mesmo
|
||||
# alias, para a leitura da linha não precisar saber quais existem.
|
||||
def selects_plano(conn)
|
||||
existentes = conn.columns(Entrega.table_name).map(&:name)
|
||||
COLUNAS_PLANO.map do |coluna|
|
||||
COLUNAS_EXTRA.map do |coluna|
|
||||
existentes.include?(coluna) ? "r.#{coluna}" : "CAST(NULL AS text) AS #{coluna}"
|
||||
end.join(', ')
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user