Files
Reem-Notas/app/services/pdf/base_pdf.rb

134 lines
4.4 KiB
Ruby

# app/services/pdf/base_pdf.rb
#
# Layout base dos PDFs da Gade: cabeçalho preto com logo laranja,
# rodapé com data de geração. Herdar e implementar #corpo.
#
module Pdf
class BasePdf
LARANJA = 'F97316'
PRETO = '0A0A0A'
CINZA = '6B7280'
# Fonte TrueType com suporte total a UTF-8. As fontes embutidas do Prawn
# (AFM/Helvetica) só aceitam o charset Windows-1252 e estouram
# Prawn::Errors::IncompatibleStringEncoding em caracteres como "✓".
FONTS_DIR = Rails.root.join('app', 'assets', 'fonts')
def initialize
# Margem inferior folgada (72) para o rodapé repetido (desenhado em y=20)
# não sobrepor o conteúdo.
@pdf = Prawn::Document.new(page_size: 'A4', margin: [40, 40, 72, 40])
registrar_fonte_utf8
end
def render
cabecalho
corpo
rodape
@pdf.render
end
private
# Registra a família DejaVu Sans (TTF) e a define como fonte padrão.
# Como os PDFs só usam normal e :bold, mapeamos italic/bold_italic para
# as variantes existentes, evitando erro caso :italic seja solicitado.
def registrar_fonte_utf8
normal = FONTS_DIR.join('DejaVuSans.ttf').to_s
bold = FONTS_DIR.join('DejaVuSans-Bold.ttf').to_s
@pdf.font_families.update(
'DejaVu' => {
normal: normal,
bold: bold,
italic: normal,
bold_italic: bold
}
)
@pdf.font 'DejaVu'
end
def cabecalho
@pdf.fill_color PRETO
@pdf.fill_rectangle [-40, @pdf.cursor + 40], @pdf.bounds.width + 80, 70
@pdf.fill_color LARANJA
@pdf.fill_rectangle [-40 + 0, @pdf.cursor + 40], 8, 70 # faixa laranja lateral
@pdf.fill_color 'FFFFFF'
@pdf.text_box 'REEM TRANSPORTE',
at: [10, @pdf.cursor + 20], size: 20, style: :bold
@pdf.fill_color LARANJA
@pdf.text_box 'Sistema de Controle de Custos Logísticos',
at: [10, @pdf.cursor - 4], size: 10
@pdf.fill_color '000000'
@pdf.move_down 55
end
def rodape
# canvas usa coordenadas absolutas da página, então o rodapé é desenhado
# DENTRO da margem inferior (y=36), abaixo da área de conteúdo. Antes ele
# ficava em y=20 do bounds — dentro do fluxo do conteúdo — e o texto da
# tabela acabava sobrepondo o "documento interno".
@pdf.repeat(:all) do
@pdf.canvas do
@pdf.fill_color CINZA
@pdf.text_box "Gerado em #{Time.current.strftime('%d/%m/%Y %H:%M')} · Reem Transporte — documento interno",
at: [40, 36], width: @pdf.bounds.width - 80,
size: 8, align: :center
@pdf.fill_color '000000'
end
end
end
def moeda(v)
"R$ #{format('%.2f', v.to_f)}".gsub('.', ',')
end
# Bloco de assinaturas lado a lado: motorista (esquerda) e administrador
# (direita). Garante espaço criando nova página se o rodapé estiver perto.
def assinaturas(motorista: nil)
@pdf.start_new_page if @pdf.cursor < 120
@pdf.move_down 36
metade = (@pdf.bounds.width - 40) / 2.0
topo = @pdf.cursor
@pdf.stroke_color '000000'
@pdf.line_width 0.7
@pdf.stroke_horizontal_line 0, metade, at: topo
@pdf.stroke_horizontal_line metade + 40, @pdf.bounds.width, at: topo
@pdf.move_down 8
linha_nome = @pdf.cursor
@pdf.fill_color '000000'
@pdf.text_box(motorista.presence || 'Motorista',
at: [0, linha_nome], width: metade, size: 9, style: :bold, align: :center)
@pdf.text_box('Reem Transporte',
at: [metade + 40, linha_nome], width: metade, size: 9, style: :bold, align: :center)
@pdf.move_down 14
linha_rotulo = @pdf.cursor
@pdf.fill_color CINZA
@pdf.text_box('Assinatura do Motorista',
at: [0, linha_rotulo], width: metade, size: 8, align: :center)
@pdf.text_box('Assinatura do Administrador',
at: [metade + 40, linha_rotulo], width: metade, size: 8, align: :center)
@pdf.fill_color '000000'
@pdf.move_down 24
end
def secao(titulo)
@pdf.move_down 14
@pdf.fill_color LARANJA
@pdf.text titulo, size: 13, style: :bold
@pdf.stroke_color LARANJA
@pdf.stroke_horizontal_rule
@pdf.fill_color '000000'
@pdf.move_down 8
end
end
end