boleto_bancario 0.0.1.beta → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Changelog.markdown +58 -2
- data/README.markdown +679 -156
- data/lib/boleto_bancario/calculos/documento.rb +191 -0
- data/lib/boleto_bancario/calculos/fator_vencimento.rb +78 -31
- data/lib/boleto_bancario/calculos/modulo11_fator_de9a2.rb +65 -0
- data/lib/boleto_bancario/calculos/modulo11_fator_de9a2_resto_x.rb +5 -51
- data/lib/boleto_bancario/calculos/modulo_numero_de_controle.rb +117 -0
- data/lib/boleto_bancario/core/banco_brasil.rb +30 -5
- data/lib/boleto_bancario/core/banrisul.rb +182 -0
- data/lib/boleto_bancario/core/boleto.rb +97 -35
- data/lib/boleto_bancario/core/bradesco.rb +28 -16
- data/lib/boleto_bancario/core/c6_bank.rb +155 -0
- data/lib/boleto_bancario/core/caixa.rb +233 -0
- data/lib/boleto_bancario/core/inter.rb +155 -0
- data/lib/boleto_bancario/core/itau.rb +20 -10
- data/lib/boleto_bancario/core/nubank.rb +156 -0
- data/lib/boleto_bancario/core/santander.rb +19 -22
- data/lib/boleto_bancario/core/sicoob.rb +172 -0
- data/lib/boleto_bancario/core/sicredi.rb +290 -0
- data/lib/boleto_bancario/locales/pt-BR.yml +55 -0
- data/lib/boleto_bancario/renderers/base.rb +154 -0
- data/lib/boleto_bancario/renderers/html_renderer.rb +92 -0
- data/lib/boleto_bancario/renderers/pdf_renderer.rb +130 -0
- data/lib/boleto_bancario/renderers/png_renderer.rb +66 -0
- data/lib/boleto_bancario/templates/_barcode.html.erb +3 -0
- data/lib/boleto_bancario/templates/_cedente.html.erb +14 -0
- data/lib/boleto_bancario/templates/_header.html.erb +4 -0
- data/lib/boleto_bancario/templates/_instructions.html.erb +10 -0
- data/lib/boleto_bancario/templates/_payment.html.erb +36 -0
- data/lib/boleto_bancario/templates/_sacado.html.erb +10 -0
- data/lib/boleto_bancario/templates/boleto.html.erb +22 -0
- data/lib/boleto_bancario/templates/boleto_styles.css +18 -0
- data/lib/boleto_bancario/version.rb +3 -2
- data/lib/boleto_bancario.rb +48 -19
- data/lib/generators/boleto_bancario/views_generator.rb +47 -0
- metadata +140 -106
- data/.gitignore +0 -18
- data/.rspec +0 -1
- data/.rvmrc +0 -1
- data/Gemfile +0 -3
- data/Planning.markdown +0 -131
- data/Rakefile +0 -9
- data/TODO.markdown +0 -5
- data/boleto_bancario.gemspec +0 -25
- data/documentacoes_dos_boletos/Bradesco/Manual_BRADESCO.PDF +0 -0
- data/spec/boleto_bancario/calculos/digitos_spec.rb +0 -19
- data/spec/boleto_bancario/calculos/fator_vencimento_spec.rb +0 -59
- data/spec/boleto_bancario/calculos/fatores_de_multiplicacao_spec.rb +0 -69
- data/spec/boleto_bancario/calculos/linha_digitavel_spec.rb +0 -57
- data/spec/boleto_bancario/calculos/modulo10_spec.rb +0 -49
- data/spec/boleto_bancario/calculos/modulo11_fator_de2a7_spec.rb +0 -43
- data/spec/boleto_bancario/calculos/modulo11_fator_de2a9_resto_zero_spec.rb +0 -39
- data/spec/boleto_bancario/calculos/modulo11_fator_de2a9_spec.rb +0 -61
- data/spec/boleto_bancario/calculos/modulo11_fator_de9a2_resto_x_spec.rb +0 -37
- data/spec/boleto_bancario/calculos/modulo11_spec.rb +0 -19
- data/spec/boleto_bancario/core/banco_brasil_spec.rb +0 -383
- data/spec/boleto_bancario/core/boleto_spec.rb +0 -102
- data/spec/boleto_bancario/core/bradesco_spec.rb +0 -170
- data/spec/boleto_bancario/core/itau_spec.rb +0 -336
- data/spec/boleto_bancario/core/santander_spec.rb +0 -135
- data/spec/shared_examples/boleto_bancario_shared_example.rb +0 -164
- data/spec/spec_helper.rb +0 -14
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
|
|
5
|
+
module BoletoBancario
|
|
6
|
+
module Renderers
|
|
7
|
+
# Classe base para renderizadores de boletos.
|
|
8
|
+
#
|
|
9
|
+
# Esta classe fornece a interface comum para todos os renderizadores
|
|
10
|
+
# (PDF, HTML, PNG).
|
|
11
|
+
#
|
|
12
|
+
# @abstract Subclasses devem implementar o método #render
|
|
13
|
+
#
|
|
14
|
+
class Base
|
|
15
|
+
attr_reader :boleto
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
# Caminho customizado para templates ERB.
|
|
19
|
+
# Se não definido, usa o caminho padrão dos templates bundled.
|
|
20
|
+
#
|
|
21
|
+
# @return [String, nil]
|
|
22
|
+
#
|
|
23
|
+
attr_accessor :template_path
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Inicializa o renderizador com um boleto.
|
|
27
|
+
#
|
|
28
|
+
# @param [BoletoBancario::Core::Boleto] boleto O boleto a ser renderizado
|
|
29
|
+
# @raise [ArgumentError] Se o boleto não for válido
|
|
30
|
+
#
|
|
31
|
+
def initialize(boleto)
|
|
32
|
+
raise ArgumentError, 'Boleto deve ser válido' unless boleto.valid?
|
|
33
|
+
|
|
34
|
+
@boleto = boleto
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Renderiza o boleto.
|
|
38
|
+
#
|
|
39
|
+
# @abstract Subclasses devem implementar este método
|
|
40
|
+
# @raise [NotImplementedError]
|
|
41
|
+
#
|
|
42
|
+
def render
|
|
43
|
+
raise NotImplementedError, "#{self.class} deve implementar #render"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Retorna o partial path para integração com Rails.
|
|
47
|
+
#
|
|
48
|
+
# @return [String]
|
|
49
|
+
#
|
|
50
|
+
def to_partial_path
|
|
51
|
+
boleto.to_partial_path
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
protected
|
|
55
|
+
|
|
56
|
+
# Retorna o caminho para os templates.
|
|
57
|
+
# Usa o template_path da classe se definido, caso contrário usa o padrão.
|
|
58
|
+
#
|
|
59
|
+
# @return [String]
|
|
60
|
+
#
|
|
61
|
+
def template_path
|
|
62
|
+
self.class.template_path || default_template_path
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Retorna o caminho padrão para os templates bundled.
|
|
66
|
+
#
|
|
67
|
+
# @return [String]
|
|
68
|
+
#
|
|
69
|
+
def default_template_path
|
|
70
|
+
File.expand_path('../templates', __dir__)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Renderiza um template ERB.
|
|
74
|
+
#
|
|
75
|
+
# @param [String] template_name Nome do arquivo de template (ex: 'boleto.html.erb')
|
|
76
|
+
# @return [String] Conteúdo renderizado
|
|
77
|
+
#
|
|
78
|
+
def render_template(template_name)
|
|
79
|
+
template_file = File.join(template_path, template_name)
|
|
80
|
+
template_content = File.read(template_file)
|
|
81
|
+
erb = ERB.new(template_content, trim_mode: '-')
|
|
82
|
+
erb.result(binding)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Renderiza um partial ERB.
|
|
86
|
+
#
|
|
87
|
+
# @param [String] partial_name Nome do partial (sem underscore, ex: 'header')
|
|
88
|
+
# @return [String] Conteúdo renderizado
|
|
89
|
+
#
|
|
90
|
+
def render_partial(partial_name)
|
|
91
|
+
render_template("_#{partial_name}.html.erb")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Retorna as variáveis locais disponíveis nos templates.
|
|
95
|
+
#
|
|
96
|
+
# @return [Hash]
|
|
97
|
+
#
|
|
98
|
+
def locals
|
|
99
|
+
{
|
|
100
|
+
boleto: boleto,
|
|
101
|
+
renderer: self
|
|
102
|
+
}
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Retorna o código de barras do boleto.
|
|
106
|
+
#
|
|
107
|
+
# @return [String]
|
|
108
|
+
#
|
|
109
|
+
def codigo_de_barras
|
|
110
|
+
boleto.codigo_de_barras
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Retorna a linha digitável do boleto.
|
|
114
|
+
#
|
|
115
|
+
# @return [String]
|
|
116
|
+
#
|
|
117
|
+
def linha_digitavel
|
|
118
|
+
boleto.linha_digitavel
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Retorna o nosso número formatado.
|
|
122
|
+
#
|
|
123
|
+
# @return [String]
|
|
124
|
+
#
|
|
125
|
+
def nosso_numero
|
|
126
|
+
boleto.nosso_numero
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Retorna o valor formatado.
|
|
130
|
+
#
|
|
131
|
+
# @return [String]
|
|
132
|
+
#
|
|
133
|
+
def valor_formatado
|
|
134
|
+
format('%.2f', boleto.valor_documento).tr('.', ',')
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Retorna a data de vencimento formatada.
|
|
138
|
+
#
|
|
139
|
+
# @return [String]
|
|
140
|
+
#
|
|
141
|
+
def data_vencimento_formatada
|
|
142
|
+
boleto.data_vencimento.strftime('%d/%m/%Y')
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Retorna a data do documento formatada.
|
|
146
|
+
#
|
|
147
|
+
# @return [String]
|
|
148
|
+
#
|
|
149
|
+
def data_documento_formatada
|
|
150
|
+
boleto.data_documento&.strftime('%d/%m/%Y')
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BoletoBancario
|
|
4
|
+
module Renderers
|
|
5
|
+
# Renderizador de boletos em formato HTML usando templates ERB.
|
|
6
|
+
#
|
|
7
|
+
# @example Gerando HTML com template padrão
|
|
8
|
+
#
|
|
9
|
+
# boleto = BoletoBancario::Itau.new(...)
|
|
10
|
+
# html_content = BoletoBancario::Renderers::HtmlRenderer.new(boleto).render
|
|
11
|
+
#
|
|
12
|
+
# @example Customizando o caminho dos templates
|
|
13
|
+
#
|
|
14
|
+
# class MyHtmlRenderer < BoletoBancario::Renderers::HtmlRenderer
|
|
15
|
+
# self.template_path = 'path/to/my/templates'
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# renderer = MyHtmlRenderer.new(boleto)
|
|
19
|
+
# html = renderer.render
|
|
20
|
+
#
|
|
21
|
+
class HtmlRenderer < Base
|
|
22
|
+
# Renderiza o boleto em HTML usando template ERB.
|
|
23
|
+
#
|
|
24
|
+
# @return [String] O conteúdo HTML do boleto
|
|
25
|
+
#
|
|
26
|
+
def render
|
|
27
|
+
render_template('boleto.html.erb')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Retorna os estilos CSS para o boleto.
|
|
31
|
+
# Pode ser sobrescrito em subclasses para customização.
|
|
32
|
+
#
|
|
33
|
+
# @return [String]
|
|
34
|
+
#
|
|
35
|
+
def css_styles
|
|
36
|
+
css_file = File.join(template_path, 'boleto_styles.css')
|
|
37
|
+
if File.exist?(css_file)
|
|
38
|
+
File.read(css_file)
|
|
39
|
+
else
|
|
40
|
+
default_css_styles
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Retorna a lista de instruções não vazias.
|
|
45
|
+
#
|
|
46
|
+
# @return [Array<String>]
|
|
47
|
+
#
|
|
48
|
+
def instructions
|
|
49
|
+
[
|
|
50
|
+
boleto.instrucoes1,
|
|
51
|
+
boleto.instrucoes2,
|
|
52
|
+
boleto.instrucoes3,
|
|
53
|
+
boleto.instrucoes4,
|
|
54
|
+
boleto.instrucoes5,
|
|
55
|
+
boleto.instrucoes6
|
|
56
|
+
].compact.reject(&:empty?)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Retorna o nome do banco formatado.
|
|
60
|
+
#
|
|
61
|
+
# @return [String]
|
|
62
|
+
#
|
|
63
|
+
def bank_name
|
|
64
|
+
boleto.class.name.split('::').last
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def default_css_styles
|
|
70
|
+
<<~CSS
|
|
71
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
72
|
+
body { font-family: Arial, sans-serif; font-size: 12px; }
|
|
73
|
+
.boleto { max-width: 800px; margin: 20px auto; border: 1px solid #000; padding: 15px; }
|
|
74
|
+
.header { display: flex; justify-content: space-between; border-bottom: 2px solid #000; padding-bottom: 10px; margin-bottom: 10px; }
|
|
75
|
+
.bank-name { font-size: 18px; font-weight: bold; }
|
|
76
|
+
.bank-code { font-size: 16px; font-weight: bold; }
|
|
77
|
+
.linha-digitavel { text-align: center; font-size: 14px; font-weight: bold; margin: 15px 0; letter-spacing: 1px; }
|
|
78
|
+
.info-row { display: flex; border-bottom: 1px solid #ccc; }
|
|
79
|
+
.info-cell { flex: 1; padding: 5px; border-right: 1px solid #ccc; }
|
|
80
|
+
.info-cell:last-child { border-right: none; }
|
|
81
|
+
.info-cell label { font-size: 10px; color: #666; display: block; }
|
|
82
|
+
.info-cell span { font-weight: bold; }
|
|
83
|
+
.instructions { margin: 15px 0; padding: 10px; background: #f9f9f9; }
|
|
84
|
+
.instructions h4 { margin-bottom: 5px; }
|
|
85
|
+
.instructions ul { margin-left: 20px; }
|
|
86
|
+
.barcode { text-align: center; margin: 20px 0; font-family: 'Libre Barcode 128', monospace; font-size: 48px; }
|
|
87
|
+
.barcode-text { font-size: 10px; margin-top: 5px; }
|
|
88
|
+
CSS
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'prawn'
|
|
4
|
+
require 'prawn/table'
|
|
5
|
+
require 'barby'
|
|
6
|
+
require 'barby/barcode/code_25_interleaved'
|
|
7
|
+
require 'barby/outputter/prawn_outputter'
|
|
8
|
+
|
|
9
|
+
module BoletoBancario
|
|
10
|
+
module Renderers
|
|
11
|
+
# Renderizador de boletos em formato PDF usando Prawn.
|
|
12
|
+
#
|
|
13
|
+
# @example Gerando um PDF
|
|
14
|
+
#
|
|
15
|
+
# boleto = BoletoBancario::Itau.new(...)
|
|
16
|
+
# pdf_content = BoletoBancario::Renderers::PdfRenderer.new(boleto).render
|
|
17
|
+
# File.write('boleto.pdf', pdf_content)
|
|
18
|
+
#
|
|
19
|
+
class PdfRenderer < Base
|
|
20
|
+
# Configurações padrão do documento PDF.
|
|
21
|
+
DEFAULT_OPTIONS = {
|
|
22
|
+
page_size: 'A4',
|
|
23
|
+
margin: [20, 20, 20, 20]
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
# Renderiza o boleto em PDF.
|
|
27
|
+
#
|
|
28
|
+
# @return [String] O conteúdo binário do PDF
|
|
29
|
+
#
|
|
30
|
+
def render
|
|
31
|
+
Prawn::Document.new(**DEFAULT_OPTIONS) do |pdf|
|
|
32
|
+
render_header(pdf)
|
|
33
|
+
render_bank_info(pdf)
|
|
34
|
+
pdf.move_down 10
|
|
35
|
+
render_recipient_info(pdf)
|
|
36
|
+
pdf.move_down 10
|
|
37
|
+
render_payment_info(pdf)
|
|
38
|
+
pdf.move_down 10
|
|
39
|
+
render_barcode(pdf)
|
|
40
|
+
pdf.move_down 20
|
|
41
|
+
render_instructions(pdf)
|
|
42
|
+
pdf.move_down 30
|
|
43
|
+
render_tear_line(pdf)
|
|
44
|
+
pdf.move_down 10
|
|
45
|
+
render_stub(pdf)
|
|
46
|
+
end.render
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def render_header(pdf)
|
|
52
|
+
pdf.text boleto.class.name.demodulize, size: 14, style: :bold
|
|
53
|
+
pdf.text "Código do Banco: #{boleto.codigo_banco_formatado}", size: 10
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def render_bank_info(pdf)
|
|
57
|
+
pdf.move_down 10
|
|
58
|
+
pdf.text linha_digitavel, size: 12, style: :bold, align: :center
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def render_recipient_info(pdf)
|
|
62
|
+
data = [
|
|
63
|
+
['Cedente', boleto.cedente],
|
|
64
|
+
['CPF/CNPJ', boleto.documento_cedente],
|
|
65
|
+
['Endereço', boleto.endereco_cedente],
|
|
66
|
+
['Agência/Código Cedente', boleto.agencia_codigo_cedente]
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
pdf.table(data, width: pdf.bounds.width) do |t|
|
|
70
|
+
t.cells.borders = [:bottom]
|
|
71
|
+
t.cells.padding = [2, 5]
|
|
72
|
+
t.column(0).font_style = :bold
|
|
73
|
+
t.column(0).width = 150
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def render_payment_info(pdf)
|
|
78
|
+
data = [
|
|
79
|
+
['Data Vencimento', data_vencimento_formatada, 'Valor', "R$ #{valor_formatado}"],
|
|
80
|
+
['Nosso Número', nosso_numero, 'Nº Documento', boleto.numero_documento],
|
|
81
|
+
['Carteira', boleto.carteira_formatada, 'Espécie', boleto.especie_documento],
|
|
82
|
+
['Sacado', boleto.sacado, 'CPF/CNPJ', boleto.documento_sacado]
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
pdf.table(data, width: pdf.bounds.width) do |t|
|
|
86
|
+
t.cells.borders = [:bottom]
|
|
87
|
+
t.cells.padding = [2, 5]
|
|
88
|
+
t.columns([0, 2]).font_style = :bold
|
|
89
|
+
t.columns([0, 2]).width = 100
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def render_barcode(pdf)
|
|
94
|
+
barcode = Barby::Code25Interleaved.new(codigo_de_barras)
|
|
95
|
+
outputter = Barby::PrawnOutputter.new(barcode)
|
|
96
|
+
outputter.annotate_pdf(pdf, height: 40, x: 0)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def render_instructions(pdf)
|
|
100
|
+
pdf.text 'Instruções:', style: :bold
|
|
101
|
+
[
|
|
102
|
+
boleto.instrucoes1,
|
|
103
|
+
boleto.instrucoes2,
|
|
104
|
+
boleto.instrucoes3,
|
|
105
|
+
boleto.instrucoes4,
|
|
106
|
+
boleto.instrucoes5,
|
|
107
|
+
boleto.instrucoes6
|
|
108
|
+
].compact.each do |instrucao|
|
|
109
|
+
pdf.text "• #{instrucao}", size: 9
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def render_tear_line(pdf)
|
|
114
|
+
pdf.stroke_horizontal_rule
|
|
115
|
+
pdf.text 'Corte aqui', size: 8, align: :center
|
|
116
|
+
pdf.stroke_horizontal_rule
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def render_stub(pdf)
|
|
120
|
+
pdf.text 'RECIBO DO SACADO', size: 10, style: :bold
|
|
121
|
+
pdf.move_down 5
|
|
122
|
+
pdf.text "Cedente: #{boleto.cedente}", size: 9
|
|
123
|
+
pdf.text "Sacado: #{boleto.sacado}", size: 9
|
|
124
|
+
pdf.text "Valor: R$ #{valor_formatado}", size: 9
|
|
125
|
+
pdf.text "Vencimento: #{data_vencimento_formatada}", size: 9
|
|
126
|
+
pdf.text "Nosso Número: #{nosso_numero}", size: 9
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'barby'
|
|
4
|
+
require 'barby/barcode/code_25_interleaved'
|
|
5
|
+
require 'barby/outputter/png_outputter'
|
|
6
|
+
|
|
7
|
+
module BoletoBancario
|
|
8
|
+
module Renderers
|
|
9
|
+
# Renderizador de código de barras em formato PNG.
|
|
10
|
+
#
|
|
11
|
+
# Este renderizador gera apenas a imagem do código de barras,
|
|
12
|
+
# não o boleto completo.
|
|
13
|
+
#
|
|
14
|
+
# @example Gerando um PNG do código de barras
|
|
15
|
+
#
|
|
16
|
+
# boleto = BoletoBancario::Itau.new(...)
|
|
17
|
+
# png_content = BoletoBancario::Renderers::PngRenderer.new(boleto).render
|
|
18
|
+
# File.binwrite('barcode.png', png_content)
|
|
19
|
+
#
|
|
20
|
+
class PngRenderer < Base
|
|
21
|
+
# Configurações padrão para o PNG.
|
|
22
|
+
DEFAULT_OPTIONS = {
|
|
23
|
+
height: 50,
|
|
24
|
+
xdim: 2,
|
|
25
|
+
margin: 10
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
attr_reader :options
|
|
29
|
+
|
|
30
|
+
# Inicializa o renderizador com opções.
|
|
31
|
+
#
|
|
32
|
+
# @param [BoletoBancario::Core::Boleto] boleto O boleto
|
|
33
|
+
# @param [Hash] options Opções para o PNG
|
|
34
|
+
# @option options [Integer] :height Altura da barra (padrão: 50)
|
|
35
|
+
# @option options [Integer] :xdim Largura de cada módulo (padrão: 2)
|
|
36
|
+
# @option options [Integer] :margin Margem ao redor (padrão: 10)
|
|
37
|
+
#
|
|
38
|
+
def initialize(boleto, options = {})
|
|
39
|
+
super(boleto)
|
|
40
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Renderiza o código de barras em PNG.
|
|
44
|
+
#
|
|
45
|
+
# @return [String] O conteúdo binário do PNG
|
|
46
|
+
#
|
|
47
|
+
def render
|
|
48
|
+
barcode = Barby::Code25Interleaved.new(codigo_de_barras)
|
|
49
|
+
outputter = Barby::PngOutputter.new(barcode)
|
|
50
|
+
outputter.height = options[:height]
|
|
51
|
+
outputter.xdim = options[:xdim]
|
|
52
|
+
outputter.margin = options[:margin]
|
|
53
|
+
outputter.to_png
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Renderiza e salva o código de barras em um arquivo.
|
|
57
|
+
#
|
|
58
|
+
# @param [String] filepath Caminho do arquivo
|
|
59
|
+
# @return [Integer] Número de bytes escritos
|
|
60
|
+
#
|
|
61
|
+
def render_to_file(filepath)
|
|
62
|
+
File.binwrite(filepath, render)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<div class="info-row">
|
|
2
|
+
<div class="info-cell flex-2">
|
|
3
|
+
<label>Cedente</label>
|
|
4
|
+
<span><%= boleto.cedente %></span>
|
|
5
|
+
</div>
|
|
6
|
+
<div class="info-cell">
|
|
7
|
+
<label>CPF/CNPJ</label>
|
|
8
|
+
<span><%= boleto.documento_cedente %></span>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="info-cell">
|
|
11
|
+
<label>Agencia/Codigo Cedente</label>
|
|
12
|
+
<span><%= boleto.agencia_codigo_cedente %></span>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<div class="info-row">
|
|
2
|
+
<div class="info-cell">
|
|
3
|
+
<label>Data Vencimento</label>
|
|
4
|
+
<span><%= data_vencimento_formatada %></span>
|
|
5
|
+
</div>
|
|
6
|
+
<div class="info-cell">
|
|
7
|
+
<label>Valor Documento</label>
|
|
8
|
+
<span>R$ <%= valor_formatado %></span>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="info-cell">
|
|
11
|
+
<label>Nosso Numero</label>
|
|
12
|
+
<span><%= nosso_numero %></span>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="info-cell">
|
|
15
|
+
<label>N Documento</label>
|
|
16
|
+
<span><%= boleto.numero_documento %></span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="info-row">
|
|
20
|
+
<div class="info-cell">
|
|
21
|
+
<label>Carteira</label>
|
|
22
|
+
<span><%= boleto.carteira_formatada %></span>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="info-cell">
|
|
25
|
+
<label>Especie</label>
|
|
26
|
+
<span><%= boleto.especie_documento %></span>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="info-cell">
|
|
29
|
+
<label>Data Documento</label>
|
|
30
|
+
<span><%= data_documento_formatada %></span>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="info-cell">
|
|
33
|
+
<label>Aceite</label>
|
|
34
|
+
<span><%= boleto.aceite_formatado %></span>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="pt-BR">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Boleto Bancario</title>
|
|
7
|
+
<style>
|
|
8
|
+
<%= css_styles %>
|
|
9
|
+
</style>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div class="boleto">
|
|
13
|
+
<%= render_partial('header') %>
|
|
14
|
+
<div class="linha-digitavel"><%= linha_digitavel %></div>
|
|
15
|
+
<%= render_partial('cedente') %>
|
|
16
|
+
<%= render_partial('payment') %>
|
|
17
|
+
<%= render_partial('sacado') %>
|
|
18
|
+
<%= render_partial('instructions') %>
|
|
19
|
+
<%= render_partial('barcode') %>
|
|
20
|
+
</div>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
2
|
+
body { font-family: Arial, sans-serif; font-size: 12px; }
|
|
3
|
+
.boleto { max-width: 800px; margin: 20px auto; border: 1px solid #000; padding: 15px; }
|
|
4
|
+
.header { display: flex; justify-content: space-between; border-bottom: 2px solid #000; padding-bottom: 10px; margin-bottom: 10px; }
|
|
5
|
+
.bank-name { font-size: 18px; font-weight: bold; }
|
|
6
|
+
.bank-code { font-size: 16px; font-weight: bold; }
|
|
7
|
+
.linha-digitavel { text-align: center; font-size: 14px; font-weight: bold; margin: 15px 0; letter-spacing: 1px; }
|
|
8
|
+
.info-row { display: flex; border-bottom: 1px solid #ccc; }
|
|
9
|
+
.info-cell { flex: 1; padding: 5px; border-right: 1px solid #ccc; }
|
|
10
|
+
.info-cell:last-child { border-right: none; }
|
|
11
|
+
.info-cell label { font-size: 10px; color: #666; display: block; }
|
|
12
|
+
.info-cell span { font-weight: bold; }
|
|
13
|
+
.info-cell.flex-2 { flex: 2; }
|
|
14
|
+
.instructions { margin: 15px 0; padding: 10px; background: #f9f9f9; }
|
|
15
|
+
.instructions h4 { margin-bottom: 5px; }
|
|
16
|
+
.instructions ul { margin-left: 20px; }
|
|
17
|
+
.barcode { text-align: center; margin: 20px 0; font-family: 'Libre Barcode 128', monospace; font-size: 48px; }
|
|
18
|
+
.barcode-text { font-size: 10px; margin-top: 5px; }
|
data/lib/boleto_bancario.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'boleto_bancario/version'
|
|
3
4
|
require 'active_model'
|
|
4
5
|
require 'active_support/core_ext/class'
|
|
5
6
|
require 'active_support/core_ext/enumerable'
|
|
6
7
|
require 'active_support/core_ext/object'
|
|
7
8
|
require 'active_support/core_ext/string'
|
|
9
|
+
require 'i18n'
|
|
10
|
+
|
|
11
|
+
# Load locale files
|
|
12
|
+
I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'boleto_bancario', 'locales', '*.yml')]
|
|
8
13
|
|
|
9
|
-
# Copyright (C) 2012 Tomás D'Stefano <http://successoft.com>
|
|
14
|
+
# Copyright (C) 2012-2026 Tomás D'Stefano <http://successoft.com>
|
|
10
15
|
#
|
|
11
16
|
# @author Tomás D'Stefano <tomas_stefano@successoft.com>
|
|
12
17
|
#
|
|
@@ -17,12 +22,11 @@ require 'active_support/core_ext/string'
|
|
|
17
22
|
# Essa biblioteca é baseada em outras <b>ótimas</b> bibliotecas.
|
|
18
23
|
# Recomendo analisar muito bem cada solução!
|
|
19
24
|
#
|
|
20
|
-
# * Novo Gateway de Pagamentos da Locaweb: http://www.locaweb.com.br/produtos/gateway-pagamento.html
|
|
21
25
|
# * Brcobranca: https://github.com/kivanio/brcobranca
|
|
22
26
|
# * Boleto Php: http://boletophp.com.br
|
|
23
27
|
# * Stella Caelum: http://stella.caelum.com.br
|
|
24
28
|
#
|
|
25
|
-
# ===
|
|
29
|
+
# === Contribuições
|
|
26
30
|
#
|
|
27
31
|
# Você pode contribuir de N formas. Seguem elas:
|
|
28
32
|
#
|
|
@@ -57,26 +61,51 @@ module BoletoBancario
|
|
|
57
61
|
# você precise mudar os nomes dos campos nos boletos)
|
|
58
62
|
#
|
|
59
63
|
module Core
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
autoload :
|
|
63
|
-
autoload :
|
|
64
|
-
autoload :
|
|
64
|
+
extend ActiveSupport::Autoload
|
|
65
|
+
|
|
66
|
+
autoload :Boleto
|
|
67
|
+
autoload :BancoBrasil
|
|
68
|
+
autoload :Banrisul
|
|
69
|
+
autoload :Bradesco
|
|
70
|
+
autoload :C6Bank
|
|
71
|
+
autoload :Caixa
|
|
72
|
+
autoload :Inter
|
|
73
|
+
autoload :Itau
|
|
74
|
+
autoload :Nubank
|
|
75
|
+
autoload :Santander
|
|
76
|
+
autoload :Sicoob
|
|
77
|
+
autoload :Sicredi
|
|
65
78
|
end
|
|
66
79
|
|
|
67
80
|
# Módulo que possui classes que realizam os cálculos dos campos que serão mostrados nos boletos.
|
|
68
81
|
#
|
|
69
82
|
module Calculos
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
autoload :
|
|
73
|
-
autoload :
|
|
74
|
-
autoload :
|
|
75
|
-
autoload :
|
|
76
|
-
autoload :
|
|
77
|
-
autoload :
|
|
78
|
-
autoload :
|
|
79
|
-
autoload :
|
|
83
|
+
extend ActiveSupport::Autoload
|
|
84
|
+
|
|
85
|
+
autoload :Documento
|
|
86
|
+
autoload :FatorVencimento
|
|
87
|
+
autoload :FatoresDeMultiplicacao
|
|
88
|
+
autoload :LinhaDigitavel
|
|
89
|
+
autoload :Modulo10
|
|
90
|
+
autoload :Modulo11
|
|
91
|
+
autoload :Modulo11FatorDe2a9
|
|
92
|
+
autoload :Modulo11FatorDe2a9RestoZero
|
|
93
|
+
autoload :Modulo11FatorDe2a7
|
|
94
|
+
autoload :Modulo11FatorDe9a2
|
|
95
|
+
autoload :Modulo11FatorDe9a2RestoX
|
|
96
|
+
autoload :ModuloNumeroDeControle
|
|
97
|
+
autoload :Digitos
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Módulo que possui classes para renderização de boletos em diferentes formatos.
|
|
101
|
+
#
|
|
102
|
+
module Renderers
|
|
103
|
+
extend ActiveSupport::Autoload
|
|
104
|
+
|
|
105
|
+
autoload :Base
|
|
106
|
+
autoload :PdfRenderer
|
|
107
|
+
autoload :HtmlRenderer
|
|
108
|
+
autoload :PngRenderer
|
|
80
109
|
end
|
|
81
110
|
|
|
82
111
|
include Core
|