Modificação da Planilha baixarda para ficar 1 para 1
This commit is contained in:
@@ -1,37 +1,108 @@
|
||||
# app/services/analytics/planilha_entregas_xlsx.rb
|
||||
#
|
||||
# Gera o binário .xlsx da planilha Entregas do cliente (aba ENTREGAS) a partir
|
||||
# das linhas montadas por Analytics::PlanilhaEntregas — layout A..Z idêntico ao
|
||||
# modelo "Entregas SUDESTE MM.AAAA_FINAL.xlsx".
|
||||
# Gera o binário .xlsx da planilha Entregas do cliente com as 3 abas do modelo
|
||||
# "Entregas SUDESTE MM.AAAA_FINAL.xlsx": RESUMO, ENTREGAS e SimpliRoute.
|
||||
# Os dados vêm de Analytics::PlanilhaEntregas. (Os gráficos embutidos do modelo
|
||||
# não são replicados — apenas os quadros de dados.)
|
||||
require 'caxlsx'
|
||||
|
||||
module Analytics
|
||||
class PlanilhaEntregasXlsx
|
||||
def initialize(linhas)
|
||||
@linhas = linhas
|
||||
def initialize(planilha)
|
||||
@planilha = planilha
|
||||
end
|
||||
|
||||
# String binária do .xlsx.
|
||||
def gerar
|
||||
pkg = Axlsx::Package.new
|
||||
pkg.workbook.add_worksheet(name: 'ENTREGAS') do |sheet|
|
||||
negrito = sheet.workbook.styles.add_style(b: true)
|
||||
sheet.add_row(PlanilhaEntregas::CABECALHO, style: negrito)
|
||||
@linhas.each do |l|
|
||||
valores, tipos = linha(l)
|
||||
sheet.add_row(valores, types: tipos)
|
||||
end
|
||||
sheet.auto_filter = "A1:Z#{@linhas.size + 1}"
|
||||
end
|
||||
wb = pkg.workbook
|
||||
@negrito = wb.styles.add_style(b: true)
|
||||
@titulo = wb.styles.add_style(b: true, sz: 12)
|
||||
@pct = wb.styles.add_style(format_code: '0.0%')
|
||||
|
||||
aba_resumo(wb)
|
||||
aba_entregas(wb)
|
||||
aba_simpliroute(wb)
|
||||
|
||||
pkg.to_stream.read
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# ── RESUMO ───────────────────────────────────────────────────
|
||||
# Mesma disposição do modelo: mês, totais/performance e um quadro por grupo
|
||||
# (EMAD e UBS) com as coordenadorias fixas + motivos de "Não Entregue".
|
||||
# ("Cordenadoria" sem o primeiro "o" é verbatim do modelo.)
|
||||
def aba_resumo(wb)
|
||||
resumo = @planilha.resumo
|
||||
wb.add_worksheet(name: 'RESUMO') do |s|
|
||||
s.add_row []
|
||||
s.add_row ['', resumo[:mes]], style: @titulo
|
||||
s.add_row []
|
||||
s.add_row ['', 'Total Previsto:', resumo[:total_previsto]]
|
||||
s.add_row ['', 'Total Realizado:', resumo[:total_realizado]]
|
||||
s.add_row ['', 'Performance:', resumo[:performance] || ''],
|
||||
style: [nil, nil, (resumo[:performance] ? @pct : nil)]
|
||||
|
||||
PlanilhaEntregas::GRUPOS.each { |grupo| quadro_grupo(s, grupo, resumo[:grupos][grupo]) }
|
||||
end
|
||||
end
|
||||
|
||||
def quadro_grupo(s, grupo, coords)
|
||||
s.add_row []
|
||||
s.add_row ['', grupo], style: @titulo
|
||||
s.add_row ['', '', '', '', '', 'Informações', '', '', 'Motivos de "Não Entregue"'], style: @negrito
|
||||
s.add_row ['', 'Cordenadoria', 'Previsão', 'Entregue', 'Não Entregue',
|
||||
'Status das Entregas', 'Conferência Documentos', '',
|
||||
*PlanilhaEntregas::MOTIVOS], style: @negrito
|
||||
|
||||
# Coordenadorias fixas do modelo + eventuais extras vindas dos dados.
|
||||
nomes = PlanilhaEntregas::COORDENADORIAS + (coords.keys - PlanilhaEntregas::COORDENADORIAS)
|
||||
total = @planilha.novo_bloco
|
||||
|
||||
nomes.each do |nome|
|
||||
b = coords[nome] || @planilha.novo_bloco
|
||||
total[:previsao] += b[:previsao]
|
||||
total[:entregue] += b[:entregue]
|
||||
total[:nao_entregue] += b[:nao_entregue]
|
||||
total[:pendente] += b[:pendente]
|
||||
b[:motivos].each { |m, q| total[:motivos][m] += q }
|
||||
|
||||
s.add_row ['', nome, b[:previsao], b[:entregue], b[:nao_entregue],
|
||||
(b[:pendente].zero? ? 'Concluído' : 'Em andamento'), 'A iniciar', '',
|
||||
*PlanilhaEntregas::MOTIVOS.map { |m| b[:motivos][m] }]
|
||||
end
|
||||
|
||||
s.add_row ['', 'Total', total[:previsao], total[:entregue], total[:nao_entregue], '', '', '',
|
||||
*PlanilhaEntregas::MOTIVOS.map { |m| total[:motivos][m] }], style: @negrito
|
||||
|
||||
if total[:previsao].positive?
|
||||
s.add_row ['', 'Performance %', 1,
|
||||
total[:entregue].to_f / total[:previsao],
|
||||
total[:nao_entregue].to_f / total[:previsao]],
|
||||
style: [nil, @negrito, @pct, @pct, @pct]
|
||||
else
|
||||
s.add_row ['', 'Performance %', '', '', ''], style: [nil, @negrito]
|
||||
end
|
||||
end
|
||||
|
||||
# ── ENTREGAS ─────────────────────────────────────────────────
|
||||
# A..V direto da tabela gade (texto); W..Z do rastreio:
|
||||
# W STATUS (completed/failed...), X ENTREGA (Sim/Não), Y DATA OCORRÊNCIA
|
||||
# (data real do checkout), Z OCORRÊNCIA (motivo do insucesso).
|
||||
def linha(l)
|
||||
def aba_entregas(wb)
|
||||
linhas = @planilha.linhas
|
||||
wb.add_worksheet(name: 'ENTREGAS') do |sheet|
|
||||
sheet.add_row(PlanilhaEntregas::CABECALHO, style: @negrito)
|
||||
linhas.each do |l|
|
||||
valores, tipos = linha_entrega(l)
|
||||
sheet.add_row(valores, types: tipos)
|
||||
end
|
||||
sheet.auto_filter = "A1:Z#{linhas.size + 1}"
|
||||
end
|
||||
end
|
||||
|
||||
def linha_entrega(l)
|
||||
status_r = l['rastreio_status'].to_s
|
||||
entregue = if status_r == 'completed'
|
||||
'Sim'
|
||||
@@ -49,6 +120,26 @@ module Analytics
|
||||
[valores, tipos]
|
||||
end
|
||||
|
||||
# ── SimpliRoute ──────────────────────────────────────────────
|
||||
# Dump cru do rastreio (todas as visitas das NFs da operação), com o
|
||||
# cabeçalho exato do modelo; cabeçalho sem coluna correspondente sai vazio.
|
||||
def aba_simpliroute(wb)
|
||||
colunas = @planilha.colunas_rastreio
|
||||
linhas = @planilha.linhas_rastreio
|
||||
wb.add_worksheet(name: 'SimpliRoute') do |sheet|
|
||||
sheet.add_row(colunas.keys, style: @negrito)
|
||||
linhas.each do |r|
|
||||
sheet.add_row(colunas.values.map { |col| col ? texto(r[col]) : '' },
|
||||
types: Array.new(colunas.size, :string))
|
||||
end
|
||||
sheet.auto_filter = "A1:#{Axlsx.col_ref(colunas.size - 1)}#{linhas.size + 1}"
|
||||
end
|
||||
end
|
||||
|
||||
def texto(valor)
|
||||
valor.respond_to?(:strftime) ? valor.strftime('%d/%m/%Y %H:%M') : valor.to_s
|
||||
end
|
||||
|
||||
def data_de(valor)
|
||||
return nil if valor.nil?
|
||||
return valor.to_date if valor.respond_to?(:to_date)
|
||||
|
||||
Reference in New Issue
Block a user