boleto_bancario 0.0.2 → 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.
Files changed (73) hide show
  1. checksums.yaml +5 -5
  2. data/Changelog.markdown +54 -2
  3. data/README.markdown +660 -189
  4. data/lib/boleto_bancario/calculos/documento.rb +191 -0
  5. data/lib/boleto_bancario/calculos/fator_vencimento.rb +78 -31
  6. data/lib/boleto_bancario/core/boleto.rb +30 -1
  7. data/lib/boleto_bancario/core/c6_bank.rb +155 -0
  8. data/lib/boleto_bancario/core/inter.rb +155 -0
  9. data/lib/boleto_bancario/core/nubank.rb +156 -0
  10. data/lib/boleto_bancario/locales/pt-BR.yml +55 -0
  11. data/lib/boleto_bancario/renderers/base.rb +154 -0
  12. data/lib/boleto_bancario/renderers/html_renderer.rb +92 -0
  13. data/lib/boleto_bancario/renderers/pdf_renderer.rb +130 -0
  14. data/lib/boleto_bancario/renderers/png_renderer.rb +66 -0
  15. data/lib/boleto_bancario/templates/_barcode.html.erb +3 -0
  16. data/lib/boleto_bancario/templates/_cedente.html.erb +14 -0
  17. data/lib/boleto_bancario/templates/_header.html.erb +4 -0
  18. data/lib/boleto_bancario/templates/_instructions.html.erb +10 -0
  19. data/lib/boleto_bancario/templates/_payment.html.erb +36 -0
  20. data/lib/boleto_bancario/templates/_sacado.html.erb +10 -0
  21. data/lib/boleto_bancario/templates/boleto.html.erb +22 -0
  22. data/lib/boleto_bancario/templates/boleto_styles.css +18 -0
  23. data/lib/boleto_bancario/version.rb +3 -1
  24. data/lib/boleto_bancario.rb +23 -6
  25. data/lib/generators/boleto_bancario/views_generator.rb +47 -0
  26. metadata +91 -129
  27. data/.gitignore +0 -19
  28. data/.rspec +0 -1
  29. data/.travis.yml +0 -10
  30. data/Gemfile +0 -3
  31. data/Planning.markdown +0 -63
  32. data/Rakefile +0 -15
  33. data/TODO.markdown +0 -19
  34. data/boleto_bancario.gemspec +0 -29
  35. data/documentacoes_dos_boletos/Bradesco/Manual_BRADESCO.PDF +0 -0
  36. data/lib/boleto_bancario/core/hsbc.rb +0 -170
  37. data/lib/boleto_bancario/core/real.rb +0 -177
  38. data/spec/boleto_bancario/calculos/digitos_spec.rb +0 -19
  39. data/spec/boleto_bancario/calculos/fator_vencimento_spec.rb +0 -59
  40. data/spec/boleto_bancario/calculos/fatores_de_multiplicacao_spec.rb +0 -69
  41. data/spec/boleto_bancario/calculos/linha_digitavel_spec.rb +0 -57
  42. data/spec/boleto_bancario/calculos/modulo10_spec.rb +0 -53
  43. data/spec/boleto_bancario/calculos/modulo11_fator_de2a7_spec.rb +0 -43
  44. data/spec/boleto_bancario/calculos/modulo11_fator_de2a9_resto_zero_spec.rb +0 -39
  45. data/spec/boleto_bancario/calculos/modulo11_fator_de2a9_spec.rb +0 -67
  46. data/spec/boleto_bancario/calculos/modulo11_fator_de9a2_resto_x_spec.rb +0 -37
  47. data/spec/boleto_bancario/calculos/modulo11_fator_de9a2_spec.rb +0 -31
  48. data/spec/boleto_bancario/calculos/modulo11_spec.rb +0 -19
  49. data/spec/boleto_bancario/calculos/modulo_numero_de_controle_spec.rb +0 -37
  50. data/spec/boleto_bancario/core/banco_brasil_spec.rb +0 -377
  51. data/spec/boleto_bancario/core/banrisul_spec.rb +0 -129
  52. data/spec/boleto_bancario/core/boleto_spec.rb +0 -218
  53. data/spec/boleto_bancario/core/bradesco_spec.rb +0 -163
  54. data/spec/boleto_bancario/core/caixa_spec.rb +0 -111
  55. data/spec/boleto_bancario/core/hsbc_spec.rb +0 -72
  56. data/spec/boleto_bancario/core/itau_spec.rb +0 -333
  57. data/spec/boleto_bancario/core/real_spec.rb +0 -104
  58. data/spec/boleto_bancario/core/santander_spec.rb +0 -137
  59. data/spec/boleto_bancario/core/sicoob_spec.rb +0 -111
  60. data/spec/boleto_bancario/core/sicredi_spec.rb +0 -149
  61. data/spec/inheritance/banco_brasil_spec.rb +0 -22
  62. data/spec/inheritance/banrisul_spec.rb +0 -22
  63. data/spec/inheritance/boleto_spec.rb +0 -15
  64. data/spec/inheritance/bradesco_spec.rb +0 -22
  65. data/spec/inheritance/caixa_spec.rb +0 -22
  66. data/spec/inheritance/hsbc_spec.rb +0 -22
  67. data/spec/inheritance/itau_spec.rb +0 -22
  68. data/spec/inheritance/real_spec.rb +0 -22
  69. data/spec/inheritance/santander_spec.rb +0 -22
  70. data/spec/inheritance/sicoob_spec.rb +0 -22
  71. data/spec/inheritance/sicredi_spec.rb +0 -22
  72. data/spec/shared_examples/boleto_bancario_shared_example.rb +0 -151
  73. data/spec/spec_helper.rb +0 -14
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoletoBancario
4
+ module Calculos
5
+ # Classe responsável pela validação e formatação de documentos (CPF e CNPJ).
6
+ #
7
+ # === Validação de CPF
8
+ #
9
+ # O CPF possui 11 dígitos e é validado através de dois dígitos verificadores
10
+ # calculados pelo módulo 11.
11
+ #
12
+ # === Validação de CNPJ
13
+ #
14
+ # O CNPJ possui 14 dígitos e é validado através de dois dígitos verificadores
15
+ # calculados pelo módulo 11.
16
+ #
17
+ # @example Validação
18
+ #
19
+ # Documento.valid?('111.444.777-35')
20
+ # #=> true
21
+ #
22
+ # Documento.valid?('11.222.333/0001-81')
23
+ # #=> true
24
+ #
25
+ # @example Formatação
26
+ #
27
+ # Documento.format('11144477735')
28
+ # #=> '111.444.777-35'
29
+ #
30
+ # Documento.format('11222333000181')
31
+ # #=> '11.222.333/0001-81'
32
+ #
33
+ class Documento
34
+ CPF_SIZE = 11
35
+ CNPJ_SIZE = 14
36
+
37
+ # CPF weights for first digit calculation
38
+ CPF_WEIGHTS_FIRST = [10, 9, 8, 7, 6, 5, 4, 3, 2].freeze
39
+
40
+ # CPF weights for second digit calculation
41
+ CPF_WEIGHTS_SECOND = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2].freeze
42
+
43
+ # CNPJ weights for first digit calculation
44
+ CNPJ_WEIGHTS_FIRST = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze
45
+
46
+ # CNPJ weights for second digit calculation
47
+ CNPJ_WEIGHTS_SECOND = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze
48
+
49
+ class << self
50
+ # Valida se o documento é um CPF ou CNPJ válido.
51
+ #
52
+ # @param [String] documento O documento a ser validado
53
+ # @return [Boolean] true se válido, false caso contrário
54
+ #
55
+ def valid?(documento)
56
+ return false if documento.blank?
57
+
58
+ digits = only_digits(documento)
59
+
60
+ case digits.size
61
+ when CPF_SIZE
62
+ valid_cpf?(digits)
63
+ when CNPJ_SIZE
64
+ valid_cnpj?(digits)
65
+ else
66
+ false
67
+ end
68
+ end
69
+
70
+ # Formata o documento com pontuação.
71
+ #
72
+ # @param [String] documento O documento a ser formatado
73
+ # @return [String] O documento formatado
74
+ #
75
+ def format(documento)
76
+ return documento if documento.blank?
77
+
78
+ digits = only_digits(documento)
79
+
80
+ case digits.size
81
+ when CPF_SIZE
82
+ format_cpf(digits)
83
+ when CNPJ_SIZE
84
+ format_cnpj(digits)
85
+ else
86
+ documento.to_s
87
+ end
88
+ end
89
+
90
+ # Verifica se o documento é um CPF.
91
+ #
92
+ # @param [String] documento O documento a ser verificado
93
+ # @return [Boolean]
94
+ #
95
+ def cpf?(documento)
96
+ only_digits(documento).size == CPF_SIZE
97
+ end
98
+
99
+ # Verifica se o documento é um CNPJ.
100
+ #
101
+ # @param [String] documento O documento a ser verificado
102
+ # @return [Boolean]
103
+ #
104
+ def cnpj?(documento)
105
+ only_digits(documento).size == CNPJ_SIZE
106
+ end
107
+
108
+ private
109
+
110
+ # Remove caracteres não numéricos.
111
+ #
112
+ # @param [String] value
113
+ # @return [String]
114
+ #
115
+ def only_digits(value)
116
+ value.to_s.gsub(/\D/, '')
117
+ end
118
+
119
+ # Valida um CPF.
120
+ #
121
+ # @param [String] digits Os 11 dígitos do CPF
122
+ # @return [Boolean]
123
+ #
124
+ def valid_cpf?(digits)
125
+ return false if invalid_sequence?(digits)
126
+
127
+ first_digit = calculate_digit(digits[0, 9], CPF_WEIGHTS_FIRST)
128
+ second_digit = calculate_digit(digits[0, 10], CPF_WEIGHTS_SECOND)
129
+
130
+ digits[9].to_i == first_digit && digits[10].to_i == second_digit
131
+ end
132
+
133
+ # Valida um CNPJ.
134
+ #
135
+ # @param [String] digits Os 14 dígitos do CNPJ
136
+ # @return [Boolean]
137
+ #
138
+ def valid_cnpj?(digits)
139
+ return false if invalid_sequence?(digits)
140
+
141
+ first_digit = calculate_digit(digits[0, 12], CNPJ_WEIGHTS_FIRST)
142
+ second_digit = calculate_digit(digits[0, 13], CNPJ_WEIGHTS_SECOND)
143
+
144
+ digits[12].to_i == first_digit && digits[13].to_i == second_digit
145
+ end
146
+
147
+ # Verifica se todos os dígitos são iguais (sequência inválida).
148
+ #
149
+ # @param [String] digits
150
+ # @return [Boolean]
151
+ #
152
+ def invalid_sequence?(digits)
153
+ digits.chars.uniq.size == 1
154
+ end
155
+
156
+ # Calcula um dígito verificador usando módulo 11.
157
+ #
158
+ # @param [String] digits Os dígitos base
159
+ # @param [Array<Integer>] weights Os pesos para multiplicação
160
+ # @return [Integer] O dígito calculado
161
+ #
162
+ def calculate_digit(digits, weights)
163
+ sum = digits.chars.each_with_index.sum do |digit, index|
164
+ digit.to_i * weights[index]
165
+ end
166
+
167
+ remainder = sum % 11
168
+ remainder < 2 ? 0 : 11 - remainder
169
+ end
170
+
171
+ # Formata CPF com pontuação.
172
+ #
173
+ # @param [String] digits
174
+ # @return [String]
175
+ #
176
+ def format_cpf(digits)
177
+ "#{digits[0, 3]}.#{digits[3, 3]}.#{digits[6, 3]}-#{digits[9, 2]}"
178
+ end
179
+
180
+ # Formata CNPJ com pontuação.
181
+ #
182
+ # @param [String] digits
183
+ # @return [String]
184
+ #
185
+ def format_cnpj(digits)
186
+ "#{digits[0, 2]}.#{digits[2, 3]}.#{digits[5, 3]}/#{digits[8, 4]}-#{digits[12, 2]}"
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -1,33 +1,44 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module BoletoBancario
3
4
  module Calculos
4
5
  # Classe responsável pelo cálculo de Fator de Vencimento do boleto bancário.
5
6
  #
6
- # === Descricão
7
+ # === Descrição
7
8
  #
8
9
  # Conforme Carta-circular 002926 do Banco Central do Brasil, de 24/07/2000, recomenda-se a indicação do Fator de Vencimento no Código de Barras.
9
10
  # A partir de 02/04/2001, o Banco acolhedor/recebedor não será mais responsável por eventuais diferenças de recebimento de BOLETOs fora do prazo,
10
11
  # ou sem a indicação do fator de vencimento.
11
12
  #
13
+ # === Atualização FEBRABAN 2025
14
+ #
15
+ # Em 22/02/2025, o fator de vencimento atingiu o limite de 9999 (baseado em 07/10/1997).
16
+ # A partir desta data, o cálculo utiliza uma nova data base (29/05/2022) e reinicia em 1000.
17
+ #
12
18
  # === Forma para obtenção do Fator de Vencimento
13
19
  #
14
- # Calcula-se <b>o número de dias corridos</b> entre a data base (<b>“Fixada” em 07/10/1997</b>) e a do vencimento desejado:
20
+ # Calcula-se <b>o número de dias corridos</b> entre a data base e a do vencimento desejado:
21
+ #
22
+ # Para datas anteriores a 22/02/2025:
23
+ # Data base: 07/10/1997
24
+ # Vencimento: 04/07/2000 => Fator: 1001
15
25
  #
16
- # Vencimento desejado: 04/07/2000
17
- # Data base : - 07/10/1997
18
- # # => 1001
26
+ # Para datas a partir de 22/02/2025:
27
+ # Data base: 29/05/2022
28
+ # Fator inicial: 1000
29
+ # Vencimento: 22/02/2025 => Fator: 1000
19
30
  #
20
31
  # === Atenção
21
32
  #
22
- # Caso ocorra divergência entre a data impressa no campo data de vencimento e a constante no código de barras,
33
+ # Caso ocorra divergência entre a data impressa no campo "data de vencimento" e a constante no código de barras,
23
34
  # o recebimento se dará da seguinte forma:
24
35
  #
25
- # * Quando pago por sistemas eletrônicos (Home-Banking, Auto-Atendimento, Internet, SISPAG, telefone, etc.), prevalecerá à representada no código de barras”;
26
- # * Quando quitado na rede de agências, diretamente no caixa, será considerada a data impressa no campo vencimento do BOLETO.
36
+ # * Quando pago por sistemas eletrônicos (Home-Banking, Auto-Atendimento, Internet, SISPAG, telefone, etc.), prevalecerá à representada no "código de barras";
37
+ # * Quando quitado na rede de agências, diretamente no caixa, será considerada a data impressa no campo "vencimento" do BOLETO.
27
38
  #
28
39
  # @return [String] retorna o resultado do cálculo. <b>Deve conter 4 dígitos</b>.
29
40
  #
30
- # @example
41
+ # @example Datas anteriores à transição
31
42
  #
32
43
  # FatorVencimento.new(Date.parse("2012-12-02"))
33
44
  # #=> "5535"
@@ -35,51 +46,87 @@ module BoletoBancario
35
46
  # FatorVencimento.new(Date.parse("1997-10-08"))
36
47
  # #=> "0001"
37
48
  #
38
- # FatorVencimento.new(Date.parse("2012-12-16"))
39
- # #=> "5549"
49
+ # @example Datas após a transição FEBRABAN 2025
40
50
  #
41
- # FatorVencimento.new(Date.parse("2014-12-15"))
42
- # #=> "6278"
51
+ # FatorVencimento.new(Date.parse("2025-02-21"))
52
+ # #=> "9999"
53
+ #
54
+ # FatorVencimento.new(Date.parse("2025-02-22"))
55
+ # #=> "1000"
56
+ #
57
+ # FatorVencimento.new(Date.parse("2025-02-23"))
58
+ # #=> "1001"
43
59
  #
44
60
  class FatorVencimento < String
61
+ # Data base original utilizada até 21/02/2025
62
+ OLD_BASE_DATE = Date.new(1997, 10, 7).freeze
63
+
64
+ # Nova data base utilizada a partir de 22/02/2025
65
+ NEW_BASE_DATE = Date.new(2022, 5, 29).freeze
66
+
67
+ # Data de transição para o novo cálculo
68
+ TRANSITION_DATE = Date.new(2025, 2, 22).freeze
69
+
70
+ # Fator inicial para a nova data base
71
+ NEW_BASE_FACTOR = 1000
72
+
45
73
  attr_reader :base_date
46
- # @param [Date] expiration_date
47
- # @param [Date] base_date
74
+
75
+ # @param [Date] expiration_date Data de vencimento do boleto
76
+ # @param [Date] base_date Data base para cálculo (opcional, determinado automaticamente)
48
77
  # @return [String] retorna o resultado do cálculo. <b>Deve conter 4 dígitos</b>.
49
- # @example
50
- # FatorVencimento.new(Date.parse("2012-09-02"))
51
- # #=> "5444"
52
- #
53
- # FatorVencimento.new(Date.parse("1999-10-01"))
54
- # #=> "0724"
55
78
  #
56
- # FatorVencimento.new(Date.parse("2022-12-16"))
57
- # #=> "9201"
79
+ # @example
80
+ # FatorVencimento.new(Date.parse("2025-03-01"))
81
+ # #=> "1007"
58
82
  #
59
- def initialize(expiration_date, base_date = Date.new(1997, 10, 7))
60
- @base_date = base_date
83
+ def initialize(expiration_date, base_date = nil)
61
84
  @expiration_date = expiration_date
85
+ @base_date = base_date || determine_base_date
62
86
 
63
87
  if @expiration_date.present?
64
88
  super(calculate)
89
+ else
90
+ super()
65
91
  end
66
92
  end
67
93
 
68
94
  # Cálculo da data de vencimento com a data base.
95
+ # Para ambos os períodos, o fator é simplesmente o número de dias desde a data base.
96
+ # A nova data base (29/05/2022) foi escolhida para que 22/02/2025 resulte em fator 1000.
69
97
  #
70
98
  # @return [String] exatamente 4 dígitos
71
99
  #
72
100
  def calculate
73
- expiration_date_minus_base_date.to_s.rjust(4, '0')
101
+ days_from_base.to_s.rjust(4, '0')
74
102
  end
75
103
 
76
- # @api private
104
+ private
105
+
106
+ # Determina qual data base usar com base na data de vencimento
77
107
  #
78
- # Cálculo da data de vencimento com a data base.
108
+ # @return [Date] a data base apropriada
109
+ #
110
+ def determine_base_date
111
+ return OLD_BASE_DATE unless @expiration_date
112
+
113
+ uses_new_calculation? ? NEW_BASE_DATE : OLD_BASE_DATE
114
+ end
115
+
116
+ # Verifica se deve usar o novo cálculo (pós-transição FEBRABAN)
117
+ #
118
+ # @return [Boolean]
119
+ #
120
+ def uses_new_calculation?
121
+ @expiration_date.is_a?(Date) && @expiration_date >= TRANSITION_DATE
122
+ end
123
+
124
+ # Calcula a diferença em dias entre a data de vencimento e a data base.
79
125
  # Chamando #to_i para não retornar um Float.
80
- # @return [Integer] diff between this two dates.
81
126
  #
82
- def expiration_date_minus_base_date
127
+ # @return [Integer] diferença em dias
128
+ #
129
+ def days_from_base
83
130
  (@expiration_date - @base_date).to_i
84
131
  end
85
132
  end
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module BoletoBancario
3
4
  module Core
4
5
  # @abstract Métodos { #codigo_banco, #digito_codigo_banco, #agencia_codigo_cedente, #nosso_numero, #codigo_de_barras_do_banco}
@@ -502,6 +503,34 @@ module BoletoBancario
502
503
  false
503
504
  end
504
505
 
506
+ # Renderiza o boleto em formato PDF.
507
+ #
508
+ # @return [String] Conteúdo binário do PDF
509
+ # @raise [ArgumentError] Se o boleto não for válido
510
+ #
511
+ def to_pdf
512
+ Renderers::PdfRenderer.new(self).render
513
+ end
514
+
515
+ # Renderiza o boleto em formato HTML.
516
+ #
517
+ # @return [String] Conteúdo HTML do boleto
518
+ # @raise [ArgumentError] Se o boleto não for válido
519
+ #
520
+ def to_html
521
+ Renderers::HtmlRenderer.new(self).render
522
+ end
523
+
524
+ # Renderiza o código de barras em formato PNG.
525
+ #
526
+ # @param [Hash] options Opções para o renderizador PNG
527
+ # @return [String] Conteúdo binário do PNG
528
+ # @raise [ArgumentError] Se o boleto não for válido
529
+ #
530
+ def to_png(options = {})
531
+ Renderers::PngRenderer.new(self, options).render
532
+ end
533
+
505
534
  # Método usado para verificar se deve realizar a validação de tamanho do campo 'agência'.
506
535
  # <b>Sobrescreva esse método na subclasse, caso você mesmo queira fazer as validações</b>.
507
536
  #
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoletoBancario
4
+ module Core
5
+ # Implementação de emissão de boleto bancário pelo C6 Bank.
6
+ #
7
+ # === Documentação Implementada
8
+ #
9
+ # A documentação na qual essa implementação foi baseada está localizada na pasta
10
+ # 'documentacoes_dos_boletos/c6_bank' dentro dessa biblioteca.
11
+ #
12
+ # === Contrato das classes de emissão de boletos
13
+ #
14
+ # Para ver o "<b>contrato</b>" da Emissão de Boletos veja a classe BoletoBancario::Core::Boleto.
15
+ #
16
+ # === Carteiras suportadas
17
+ #
18
+ # O C6 Bank trabalha com carteira de cobrança registrada.
19
+ #
20
+ # ___________________________________________________________________________
21
+ # | Carteira | Descrição | Testada/Homologada |
22
+ # | 1 | Cobrança Registrada | Esperando Contribuição |
23
+ # ----------------------------------------------------------------------------
24
+ #
25
+ class C6Bank < Boleto
26
+ # Tamanho máximo de uma conta corrente no C6 Bank.
27
+ #
28
+ # @return [Integer] 10
29
+ #
30
+ def self.tamanho_maximo_conta_corrente
31
+ 10
32
+ end
33
+
34
+ # Tamanho máximo de uma agência no C6 Bank.
35
+ #
36
+ # @return [Integer] 4
37
+ #
38
+ def self.tamanho_maximo_agencia
39
+ 4
40
+ end
41
+
42
+ # Tamanho máximo do número do documento.
43
+ #
44
+ # @return [Integer] 11
45
+ #
46
+ def self.tamanho_maximo_numero_documento
47
+ 11
48
+ end
49
+
50
+ # Tamanho máximo do código do cedente.
51
+ #
52
+ # @return [Integer] 10
53
+ #
54
+ def self.tamanho_maximo_codigo_cedente
55
+ 10
56
+ end
57
+
58
+ # Carteiras suportadas pelo C6 Bank.
59
+ #
60
+ # @return [Array]
61
+ #
62
+ def self.carteiras_suportadas
63
+ %w[1]
64
+ end
65
+
66
+ validates :agencia, :conta_corrente, presence: true
67
+ validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
68
+ validates :conta_corrente, length: { maximum: tamanho_maximo_conta_corrente }, if: :deve_validar_conta_corrente?
69
+ validates :agencia, length: { maximum: tamanho_maximo_agencia }, if: :deve_validar_agencia?
70
+ validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
71
+
72
+ # @return [String] Número do documento com 11 dígitos.
73
+ #
74
+ def numero_documento
75
+ @numero_documento.to_s.rjust(11, '0') if @numero_documento.present?
76
+ end
77
+
78
+ # @return [String] Agência com 4 dígitos.
79
+ #
80
+ def agencia
81
+ @agencia.to_s.rjust(4, '0') if @agencia.present?
82
+ end
83
+
84
+ # @return [String] Conta corrente com 10 dígitos.
85
+ #
86
+ def conta_corrente
87
+ @conta_corrente.to_s.rjust(10, '0') if @conta_corrente.present?
88
+ end
89
+
90
+ # @return [String] Código do cedente com 10 dígitos.
91
+ #
92
+ def codigo_cedente
93
+ @codigo_cedente.to_s.rjust(10, '0') if @codigo_cedente.present?
94
+ end
95
+
96
+ # Código do C6 Bank.
97
+ #
98
+ # @return [String] '336'
99
+ #
100
+ def codigo_banco
101
+ '336'
102
+ end
103
+
104
+ # Dígito do código do banco.
105
+ #
106
+ # @return [String] '5'
107
+ #
108
+ def digito_codigo_banco
109
+ '5'
110
+ end
111
+
112
+ # Dígito verificador da conta corrente.
113
+ #
114
+ # @return [String]
115
+ #
116
+ def digito_conta_corrente
117
+ Modulo10.new(conta_corrente.to_s)
118
+ end
119
+
120
+ # Agência e código do cedente formatados.
121
+ #
122
+ # @return [String]
123
+ #
124
+ def agencia_codigo_cedente
125
+ "#{agencia} / #{conta_corrente}-#{digito_conta_corrente}"
126
+ end
127
+
128
+ # Nosso Número formatado.
129
+ #
130
+ # @return [String]
131
+ #
132
+ def nosso_numero
133
+ "#{numero_documento}-#{digito_nosso_numero}"
134
+ end
135
+
136
+ # Dígito verificador do nosso número.
137
+ #
138
+ # @return [String]
139
+ #
140
+ def digito_nosso_numero
141
+ Modulo11FatorDe2a9.new(numero_documento.to_s)
142
+ end
143
+
144
+ # Segunda parte do código de barras (campo livre).
145
+ # 25 posições específicas do C6 Bank.
146
+ #
147
+ # @return [String]
148
+ #
149
+ def codigo_de_barras_do_banco
150
+ codigo = "#{agencia}#{carteira.to_s.rjust(1, '0')}#{numero_documento}#{conta_corrente.to_s[0, 9]}"
151
+ "#{codigo.ljust(25, '0')}"
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoletoBancario
4
+ module Core
5
+ # Implementação de emissão de boleto bancário pelo Banco Inter.
6
+ #
7
+ # === Documentação Implementada
8
+ #
9
+ # A documentação na qual essa implementação foi baseada está localizada na pasta
10
+ # 'documentacoes_dos_boletos/inter' dentro dessa biblioteca.
11
+ #
12
+ # === Contrato das classes de emissão de boletos
13
+ #
14
+ # Para ver o "<b>contrato</b>" da Emissão de Boletos veja a classe BoletoBancario::Core::Boleto.
15
+ #
16
+ # === Carteiras suportadas
17
+ #
18
+ # O Banco Inter trabalha com carteira de cobrança registrada.
19
+ #
20
+ # ___________________________________________________________________________
21
+ # | Carteira | Descrição | Testada/Homologada |
22
+ # | 112 | Cobrança Registrada | Esperando Contribuição |
23
+ # ----------------------------------------------------------------------------
24
+ #
25
+ class Inter < Boleto
26
+ # Tamanho máximo de uma conta corrente no Banco Inter.
27
+ #
28
+ # @return [Integer] 10
29
+ #
30
+ def self.tamanho_maximo_conta_corrente
31
+ 10
32
+ end
33
+
34
+ # Tamanho máximo de uma agência no Banco Inter.
35
+ #
36
+ # @return [Integer] 4
37
+ #
38
+ def self.tamanho_maximo_agencia
39
+ 4
40
+ end
41
+
42
+ # Tamanho máximo do número do documento.
43
+ #
44
+ # @return [Integer] 11
45
+ #
46
+ def self.tamanho_maximo_numero_documento
47
+ 11
48
+ end
49
+
50
+ # Tamanho máximo do código do cedente.
51
+ #
52
+ # @return [Integer] 10
53
+ #
54
+ def self.tamanho_maximo_codigo_cedente
55
+ 10
56
+ end
57
+
58
+ # Carteiras suportadas pelo Banco Inter.
59
+ #
60
+ # @return [Array]
61
+ #
62
+ def self.carteiras_suportadas
63
+ %w[112]
64
+ end
65
+
66
+ validates :agencia, :conta_corrente, presence: true
67
+ validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
68
+ validates :conta_corrente, length: { maximum: tamanho_maximo_conta_corrente }, if: :deve_validar_conta_corrente?
69
+ validates :agencia, length: { maximum: tamanho_maximo_agencia }, if: :deve_validar_agencia?
70
+ validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
71
+
72
+ # @return [String] Número do documento com 11 dígitos.
73
+ #
74
+ def numero_documento
75
+ @numero_documento.to_s.rjust(11, '0') if @numero_documento.present?
76
+ end
77
+
78
+ # @return [String] Agência com 4 dígitos.
79
+ #
80
+ def agencia
81
+ @agencia.to_s.rjust(4, '0') if @agencia.present?
82
+ end
83
+
84
+ # @return [String] Conta corrente com 10 dígitos.
85
+ #
86
+ def conta_corrente
87
+ @conta_corrente.to_s.rjust(10, '0') if @conta_corrente.present?
88
+ end
89
+
90
+ # @return [String] Código do cedente com 10 dígitos.
91
+ #
92
+ def codigo_cedente
93
+ @codigo_cedente.to_s.rjust(10, '0') if @codigo_cedente.present?
94
+ end
95
+
96
+ # Código do Banco Inter.
97
+ #
98
+ # @return [String] '077'
99
+ #
100
+ def codigo_banco
101
+ '077'
102
+ end
103
+
104
+ # Dígito do código do banco.
105
+ #
106
+ # @return [String] '9'
107
+ #
108
+ def digito_codigo_banco
109
+ '9'
110
+ end
111
+
112
+ # Dígito verificador da conta corrente.
113
+ #
114
+ # @return [String]
115
+ #
116
+ def digito_conta_corrente
117
+ Modulo10.new(conta_corrente.to_s)
118
+ end
119
+
120
+ # Agência e código do cedente formatados.
121
+ #
122
+ # @return [String]
123
+ #
124
+ def agencia_codigo_cedente
125
+ "#{agencia} / #{conta_corrente}-#{digito_conta_corrente}"
126
+ end
127
+
128
+ # Nosso Número formatado.
129
+ #
130
+ # @return [String]
131
+ #
132
+ def nosso_numero
133
+ "#{numero_documento}-#{digito_nosso_numero}"
134
+ end
135
+
136
+ # Dígito verificador do nosso número.
137
+ #
138
+ # @return [String]
139
+ #
140
+ def digito_nosso_numero
141
+ Modulo11FatorDe2a9.new(numero_documento.to_s)
142
+ end
143
+
144
+ # Segunda parte do código de barras (campo livre).
145
+ # 25 posições específicas do Banco Inter.
146
+ #
147
+ # @return [String]
148
+ #
149
+ def codigo_de_barras_do_banco
150
+ codigo = "#{agencia}#{carteira}#{numero_documento}#{conta_corrente.to_s[0, 7]}"
151
+ "#{codigo.ljust(25, '0')}"
152
+ end
153
+ end
154
+ end
155
+ end