# frozen_string_literal: true begin require 'rghost' rescue LoadError require 'rubygems' unless ENV['NO_RUBYGEMS'] gem 'rghost' require 'rghost' end begin require 'rghost_barcode' rescue LoadError require 'rubygems' unless ENV['NO_RUBYGEMS'] gem 'rghost_barcode' require 'rghost_barcode' end module Brcobranca module Boleto module Template # Templates para usar com Rghost module Rghost extend self include RGhost unless include?(RGhost) RGhost::Config::GS[:external_encoding] = Brcobranca.configuration.external_encoding RGhost::Config::GS[:default_params] << '-dNOSAFER' # Gera o boleto em usando o formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc] # # @return [Stream] # @see http://wiki.github.com/shairontoledo/rghost/supported-devices-drivers-and-formats Veja mais formatos na documentação do rghost. # @see Rghost#modelo_generico Recebe os mesmos parâmetros do Rghost#modelo_generico. def to(formato, options = {}) modelo_generico(self, options.merge!(formato: formato)) end # Gera o boleto em usando o formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc] # # @return [Stream] # @see http://wiki.github.com/shairontoledo/rghost/supported-devices-drivers-and-formats Veja mais formatos na documentação do rghost. # @see Rghost#modelo_generico Recebe os mesmos parâmetros do Rghost#modelo_generico. def lote(boletos, options = {}) modelo_generico_multipage(boletos, options) end # Cria o métodos dinâmicos (to_pdf, to_gif e etc) com todos os fomátos válidos. # # @return [Stream] # @see Rghost#modelo_generico Recebe os mesmos parâmetros do Rghost#modelo_generico. # @example # @boleto.to_pdf #=> boleto gerado no formato pdf def method_missing(m, *args) method = m.to_s if method.start_with?('to_') modelo_generico(self, (args.first || {}).merge!(formato: method[3..])) else super end end private # Retorna um stream pronto para gravação em arquivo. # # @return [Stream] # @param [Boleto] Instância de uma classe de boleto. # @param [Hash] options Opção para a criação do boleto. # @option options [Symbol] :resolucao Resolução em pixels. # @option options [Symbol] :formato Formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc] def modelo_generico(boleto, options = {}) doc = Document.new paper: :A4 # 210x297 template_path = File.join(File.dirname(__FILE__), '..', '..', 'arquivos', 'templates', 'modelo_generico.eps') raise 'Não foi possível encontrar o template. Verifique o caminho' unless File.exist?(template_path) modelo_generico_template(doc, boleto, template_path) modelo_generico_cabecalho(doc, boleto) modelo_generico_rodape(doc, boleto) # Gerando codigo de barra com rghost_barcode if boleto.codigo_barras doc.barcode_interleaved2of5(boleto.codigo_barras, width: '10.3 cm', height: '1.3 cm', x: "#{@x - 1.7} cm", y: "#{@y - 1.67} cm") end # Gerando stream formato = options.delete(:formato) || Brcobranca.configuration.formato resolucao = options.delete(:resolucao) || Brcobranca.configuration.resolucao doc.render_stream(formato.to_sym, resolution: resolucao) end # Retorna um stream para multiplos boletos pronto para gravação em arquivo. # # @return [Stream] # @param [Array] Instâncias de classes de boleto. # @param [Hash] options Opção para a criação do boleto. # @option options [Symbol] :resolucao Resolução em pixels. # @option options [Symbol] :formato Formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc] def modelo_generico_multipage(boletos, options = {}) doc = Document.new paper: :A4 # 210x297 template_path = File.join(File.dirname(__FILE__), '..', '..', 'arquivos', 'templates', 'modelo_generico.eps') raise 'Não foi possível encontrar o template. Verifique o caminho' unless File.exist?(template_path) boletos.each_with_index do |boleto, index| modelo_generico_template(doc, boleto, template_path) modelo_generico_cabecalho(doc, boleto) modelo_generico_rodape(doc, boleto) # Gerando codigo de barra com rghost_barcode if boleto.codigo_barras doc.barcode_interleaved2of5(boleto.codigo_barras, width: '10.3 cm', height: '1.3 cm', x: "#{@x - 1.7} cm", y: "#{@y - 1.67} cm") end # Cria nova página se não for o último boleto doc.next_page unless index == boletos.length - 1 end # Gerando stream formato = options.delete(:formato) || Brcobranca.configuration.formato resolucao = options.delete(:resolucao) || Brcobranca.configuration.resolucao doc.render_stream(formato.to_sym, resolution: resolucao) end # Define o template a ser usado no boleto def modelo_generico_template(doc, _boleto, template_path) doc.define_template(:template, template_path, x: '0.5 cm', y: '2.7 cm') doc.use_template :template doc.define_tags do tag :grande, size: 13 tag :maior, size: 15 end end def move_more(doc, x, y) @x += x @y += y doc.moveto x: "#{@x} cm", y: "#{@y} cm" end # Monta o cabeçalho do layout do boleto def modelo_generico_cabecalho(doc, boleto) # INICIO Primeira parte do BOLETO # Pontos iniciais em x e y @x = 0.50 @y = 27.42 # LOGOTIPO do BANCO doc.image boleto.logotipo, x: "#{@x} cm", y: "#{@y} cm" # Dados move_more(doc, 4.84, 0.02) doc.show "#{boleto.banco}-#{boleto.banco_dv}", tag: :maior move_more(doc, 2, 0) doc.show boleto.codigo_barras.linha_digitavel, tag: :grande move_more(doc, -6.5, -0.83) doc.show boleto.cedente move_more(doc, 15.8, 0) doc.show boleto.agencia_conta_boleto move_more(doc, -15.8, -0.9) doc.show boleto.cedente_endereco move_more(doc, 15.8, 0) doc.show boleto.nosso_numero_boleto move_more(doc, -15.8, -0.8) doc.show boleto.documento_numero move_more(doc, 3.5, 0) doc.show boleto.especie move_more(doc, 1.5, 0) doc.show boleto.quantidade move_more(doc, 2, 0) doc.show boleto.documento_cedente.formata_documento.to_s move_more(doc, 3.8, 0) doc.show boleto.data_vencimento.to_s_br move_more(doc, 5, 0) doc.show boleto.valor_documento.to_currency move_more(doc, -15, -1.3) doc.show "#{boleto.sacado} - #{boleto.sacado_documento.formata_documento}" move_more(doc, 0, -0.3) doc.show boleto.sacado_endereco.to_s return unless boleto.demonstrativo doc.text_area boleto.demonstrativo, width: '18.5 cm', text_align: :left, x: "#{@x - 0.8} cm", y: "#{@y - 0.9} cm", row_height: '0.4 cm' # FIM Primeira parte do BOLETO end # Monta o corpo e rodapé do layout do boleto def modelo_generico_rodape(doc, boleto) # INICIO Segunda parte do BOLETO BB # Pontos iniciais em x e y @x = 0.50 @y = 12.22 # LOGOTIPO do BANCO doc.image boleto.logotipo, x: "#{@x} cm", y: "#{@y} cm" move_more(doc, 4.84, 0.01) doc.show "#{boleto.banco}-#{boleto.banco_dv}", tag: :maior move_more(doc, 2, 0) doc.show boleto.codigo_barras.linha_digitavel, tag: :grande move_more(doc, -6.5, -0.9) doc.show boleto.local_pagamento move_more(doc, 15.8, 0) doc.show boleto.data_vencimento.to_s_br if boleto.data_vencimento move_more(doc, -15.8, -0.8) if boleto.cedente_endereco doc.show boleto.cedente_endereco move_more(doc, 1.2, 0.3) doc.show boleto.cedente move_more(doc, -1.2, -0.3) else doc.show boleto.cedente end move_more(doc, 15.8, 0) doc.show boleto.agencia_conta_boleto move_more(doc, -15.8, -0.9) doc.show boleto.data_documento.to_s_br if boleto.data_documento move_more(doc, 3.5, 0) doc.show boleto.documento_numero move_more(doc, 5.8, 0) doc.show boleto.especie_documento move_more(doc, 1.7, 0) doc.show boleto.aceite move_more(doc, 1.3, 0) doc.show boleto.data_processamento.to_s_br if boleto.data_processamento move_more(doc, 3.5, 0) doc.show boleto.nosso_numero_boleto move_more(doc, -12.1, -0.8) if boleto.variacao doc.show "#{boleto.carteira}-#{boleto.variacao}" else doc.show boleto.carteira end move_more(doc, 2, 0) doc.show boleto.especie move_more(doc, 10.1, 0) doc.show boleto.valor_documento.to_currency if boleto.instrucoes doc.text_area boleto.instrucoes, width: '14 cm', text_align: :left, x: "#{@x -= 15.8} cm", y: "#{@y -= 0.9} cm", row_height: '0.4 cm' move_more(doc, 0, -2) else move_more(doc, -15.8, -0.9) doc.show boleto.instrucao1 move_more(doc, 0, -0.4) doc.show boleto.instrucao2 move_more(doc, 0, -0.4) doc.show boleto.instrucao3 move_more(doc, 0, -0.4) doc.show boleto.instrucao4 move_more(doc, 0, -0.4) doc.show boleto.instrucao5 move_more(doc, 0, -0.4) doc.show boleto.instrucao6 end move_more(doc, 0.5, -1.9) if boleto.sacado && boleto.sacado_documento doc.show "#{boleto.sacado} - CPF/CNPJ: #{boleto.sacado_documento.formata_documento}" end move_more(doc, 0, -0.4) doc.show boleto.sacado_endereco.to_s move_more(doc, 1.2, -0.93) doc.show "#{boleto.avalista} - #{boleto.avalista_documento}" if boleto.avalista && boleto.avalista_documento # FIM Segunda parte do BOLETO end end end end end