br_boleto 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +145 -0
  4. data/History.txt +4 -0
  5. data/LICENSE +20 -0
  6. data/README.markdown +156 -0
  7. data/Rakefile +8 -0
  8. data/br_boleto.gemspec +26 -0
  9. data/lib/br_boleto.rb +87 -0
  10. data/lib/br_boleto/calculos/digitos.rb +35 -0
  11. data/lib/br_boleto/calculos/fator_vencimento.rb +129 -0
  12. data/lib/br_boleto/calculos/fatores_de_multiplicacao.rb +67 -0
  13. data/lib/br_boleto/calculos/linha_digitavel.rb +158 -0
  14. data/lib/br_boleto/calculos/modulo10.rb +83 -0
  15. data/lib/br_boleto/calculos/modulo11.rb +54 -0
  16. data/lib/br_boleto/calculos/modulo11_fator3197.rb +88 -0
  17. data/lib/br_boleto/calculos/modulo11_fator_de2a7.rb +97 -0
  18. data/lib/br_boleto/calculos/modulo11_fator_de2a9.rb +83 -0
  19. data/lib/br_boleto/calculos/modulo11_fator_de2a9_resto_zero.rb +29 -0
  20. data/lib/br_boleto/calculos/modulo11_fator_de9a2.rb +65 -0
  21. data/lib/br_boleto/calculos/modulo11_fator_de9a2_resto_x.rb +55 -0
  22. data/lib/br_boleto/calculos/modulo_numero_de_controle.rb +117 -0
  23. data/lib/br_boleto/core/boleto.rb +558 -0
  24. data/lib/br_boleto/core/sicoob.rb +169 -0
  25. data/lib/br_boleto/version.rb +8 -0
  26. data/test/br_boleto/calculos/digitos_test.rb +15 -0
  27. data/test/br_boleto/calculos/fator_vencimento_test.rb +56 -0
  28. data/test/br_boleto/calculos/fatores_de_multiplicacao_test.rb +66 -0
  29. data/test/br_boleto/calculos/linha_digitavel_test.rb +58 -0
  30. data/test/br_boleto/calculos/modulo10_test.rb +54 -0
  31. data/test/br_boleto/calculos/modulo11_fator3197_test.rb +43 -0
  32. data/test/br_boleto/calculos/modulo11_fator_de2a7_test.rb +44 -0
  33. data/test/br_boleto/calculos/modulo11_fator_de2a9_resto_zero_test.rb +40 -0
  34. data/test/br_boleto/calculos/modulo11_fator_de2a9_test.rb +68 -0
  35. data/test/br_boleto/calculos/modulo11_fator_de9a2_resto_x_test.rb +38 -0
  36. data/test/br_boleto/calculos/modulo11_fator_de9a2_test.rb +32 -0
  37. data/test/br_boleto/calculos/modulo11_test.rb +28 -0
  38. data/test/br_boleto/calculos/modulo_numero_de_controle_test.rb +38 -0
  39. data/test/br_boleto/core/boleto_test.rb +221 -0
  40. data/test/br_boleto/core/sicoob_test.rb +138 -0
  41. data/test/factories/boleto.rb +22 -0
  42. data/test/factories/boleto_sicoob.rb +23 -0
  43. data/test/inheritance/boleto_test.rb +15 -0
  44. data/test/inheritance/sicoob_test.rb +25 -0
  45. data/test/test_helper.rb +37 -0
  46. metadata +151 -0
@@ -0,0 +1,117 @@
1
+ module BrBoleto
2
+ module Calculos
3
+ # === Cálculo do Módulo do Número de Controle (2 dígitos)
4
+ #
5
+ # Tipo de cálculo usado pelo Banco Banrisul.
6
+ #
7
+ # === Cálculo do Primeiro Dígito
8
+ #
9
+ # 1) Multiplica-se cada algarismo do campo pela seqüência de multiplicadores <b>2, 1, 2, 1, 2, 1 ...</b>, posicionados da direita para a esquerda.
10
+ #
11
+ # 2) Some individualmente, os algarismos dos resultados dos produtos, obtendo-se o total (N).
12
+ #
13
+ # 3) Divida o total encontrado (N) por 10, e determine o resto da divisão como MOD 10 (N).
14
+ #
15
+ # 4) Encontre o DAC através da seguinte expressão:
16
+ #
17
+ # DAC = 10 - Mod 10 (n)
18
+ #
19
+ # === Cálculo do segundo dígito
20
+ #
21
+ # # 1) Tomando-se os algarismos multiplique-os, iniciando-se da direita para a esquerda,
22
+ # pela seqüência numérica de 2 a 7 (2, 3, 4, 5, 6, 7 ... e assim por diante).
23
+ #
24
+ # 2) Some o resultado de cada produto efetuado e determine o total como (N).
25
+ #
26
+ # 3) Divida o total (N) por 11 e determine o resto obtido da divisão como Mod 11(N).
27
+ #
28
+ # 4) Calcule o dígito verificador (DAC) através da expressão:
29
+ #
30
+ # DIGIT = 11 - Mod 11 (n)
31
+ #
32
+ # <b>Observações:</b>
33
+ #
34
+ # Caso o 'resto' obtido no cálculo do módulo '11' seja igual a '1', considera-se o DV inválido.
35
+ # Soma-se, então, "1" ao DV obtido do módulo "10" e refaz-se o cálculo do módulo “11”.
36
+ # Se o dígito obtido pelo módulo “10” era igual a "9", considera-se então (9+1=10) DV inválido.
37
+ # Neste caso, o DV do módulo "10" automaticamente será igual a "0" e procede-se assim
38
+ # novo cálculo pelo módulo "11".
39
+ #
40
+ # === Exemplo com Primeiro Dígito Inválido
41
+ #
42
+ # Dado o número '00009194':
43
+ #
44
+ # O somatório do primeiro cálculo é igual a '28' e o Resto é igual a '8'.
45
+ # Portanto, o primeiro DV é igual a 10 - 8 ou DV = 2.
46
+ #
47
+ # O somatório do segundo cálculo é igual a '111' e o Resto é, neste caso, igual a '1'.
48
+ # Portanto, o segundo DV é inválido (11 - 1 = 10).
49
+ #
50
+ # Neste caso, soma-se '1' ao DV obtido do primeiro cálculo:
51
+ #
52
+ # 2 + 1
53
+ # # ======> 3 # Primeiro dígito do número de controle
54
+ #
55
+ # Agora, efetua-se novo cálculo do módulo 11, agora com o novo número, ou seja, 000091943:
56
+ #
57
+ # A somatório do segundo cálculo é igual a '113' e o Resto igual a '3'.
58
+ # Portanto, o segundo DV é igual a:
59
+ #
60
+ # 11 - 3
61
+ # # ====> 8 # Segundo dígito do número de controle
62
+ #
63
+ # Neste exemplo, o número de controle será '38'.
64
+ #
65
+ class ModuloNumeroDeControle < String
66
+ attr_reader :number, :first_digit, :second_digit
67
+
68
+ def initialize(number)
69
+ @number = number
70
+ @first_digit = calculate_first_digit
71
+ @second_digit = calculate_second_digit
72
+
73
+ super(calculate)
74
+ end
75
+
76
+ # Retorna 2 dígitos verificando o segundo dígito se é válido ou não.
77
+ #
78
+ # @return [String]
79
+ #
80
+ def calculate
81
+ if second_digit_result.equal?(10)
82
+ @first_digit = first_digit.to_i + 1
83
+ @first_digit = 0 if @first_digit.equal?(10)
84
+ @second_digit = calculate_second_digit
85
+ end
86
+
87
+ "#{first_digit}#{second_digit}"
88
+ end
89
+
90
+ # Retorna a subtração de 11 pelo resto da divisão por 11 do segundo dígito.
91
+ #
92
+ # @return [Integer]
93
+ #
94
+ def second_digit_result
95
+ 11 - @second_digit.mod_division
96
+ end
97
+
98
+ # Calcula o primeiro dígito pelo módulo 10.
99
+ # Para mais detalhes veja a classe Modulo10.
100
+ #
101
+ # @return [String]
102
+ #
103
+ def calculate_first_digit
104
+ Modulo10.new(number)
105
+ end
106
+
107
+ # Calcula o segundo dígito pelo módulo 11 usando os fatores de 2 a 7.
108
+ # Para mais detalhes veja a classe Modulo11FatorDe2a7.
109
+ #
110
+ # @return [String]
111
+ #
112
+ def calculate_second_digit
113
+ Modulo11FatorDe2a7.new("#{number}#{first_digit}")
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,558 @@
1
+ # encoding: utf-8
2
+ module BrBoleto
3
+ module Core
4
+ # @abstract Métodos { #codigo_banco, #digito_codigo_banco, #agencia_codigo_cedente, #nosso_numero, #codigo_de_barras_do_banco}
5
+ # Métodos para serem escritos nas subclasses (exitem outros opcionais, conforme visto nessa documentação).
6
+ #
7
+ class Boleto
8
+ include BrBoleto::Calculos
9
+
10
+ # Seguindo a interface do Active Model para:
11
+ # * Validações;
12
+ # * Internacionalização;
13
+ # * Nomes das classes para serem manipuladas;
14
+ #
15
+ include ActiveModel::Model
16
+
17
+ # Nome/Razão social que aparece no campo 'Cedente' no boleto.
18
+ #
19
+ attr_accessor :cedente
20
+
21
+ # <b>Código do Cedente é o código do cliente, fornecido pelo banco.</b>
22
+ #
23
+ # Alguns bancos, dependendo do banco e da carteira, precisam desse campo preenchido.
24
+ # Em compensação, outros bancos (a minoria) não fazem utilização desse campo.
25
+ #
26
+ attr_accessor :codigo_cedente
27
+
28
+ # Documento do Cedente (CPF ou CNPJ).
29
+ # <b>OBS.: Esse campo não possui validação do campo. Caso você precise imeplemente na subclasse.</b>
30
+ #
31
+ # Esse campo serve apenas para mostrar no boleto no campo "CPF/CNPJ".
32
+ #
33
+ attr_accessor :documento_cedente
34
+
35
+ # Deve ser informado o endereço completo do Cedente.
36
+ # Se o título possuir a figura de Sacador Avalista o endereço informado
37
+ # deverá ser do Sacador Avalista, conforme Lei Federal 12.039 de 01/10/2009.
38
+ #
39
+ # <b>Campo Obrigatório</b>
40
+ #
41
+ attr_accessor :endereco_cedente
42
+
43
+ # Data do vencimento do boleto. Campo auto explicativo.
44
+ #
45
+ # <b>Campo Obrigatório</b>
46
+ #
47
+ attr_accessor :data_vencimento
48
+
49
+ # Número do documento que será mostrado no boleto.
50
+ # Campo de resposabilidade do Cedente e cada banco possui um tamanho esperado.
51
+ #
52
+ attr_accessor :numero_documento
53
+
54
+ # Valor total do documento. Campo auto explicativo.
55
+ #
56
+ # <b>Campo Obrigatório</b>.
57
+ #
58
+ attr_accessor :valor_documento
59
+
60
+ # Uma carteira de cobrança define o modo como o boleto é tratado pelo banco.
61
+ # Existem duas grandes divisões: carteiras não registradas e carteiras registradas.
62
+ #
63
+ # === Carteiras Não Registradas
64
+ #
65
+ # Significa que não há registro no banco sobre os boletos gerados, ou seja, você não precisa
66
+ # notificar o banco a cada boleto gerado.
67
+ # Neste caso a cobrança de taxa bancária é feita por boleto pago.
68
+ #
69
+ # === Carteiras Registradas
70
+ #
71
+ # Você precisa notificar o banco sobre todos os boletos gerados, em geral enviando um
72
+ # arquivo chamado "arquivo de remessa".
73
+ # Neste caso, normalmente existe uma taxa bancária por boleto gerado, independentemente de ele ser pago.
74
+ # Nestas carteiras também se encaixam serviços bancários adicionais, como protesto em caso de não pagamento.
75
+ #
76
+ # <b>Campo Obrigatório</b>
77
+ #
78
+ attr_accessor :carteira
79
+
80
+ # Número da agência. Campo auto explicativo.
81
+ #
82
+ attr_accessor :agencia
83
+
84
+ # Número da Conta corrente. Campo auto explicativo.
85
+ #
86
+ attr_accessor :conta_corrente
87
+
88
+ # Código da moeda. Campo auto explicativo.
89
+ # Padrão '9' (Real).
90
+ #
91
+ attr_accessor :codigo_moeda
92
+
93
+ # Essencial para identificação da moeda em que a operação foi efetuada.
94
+ #
95
+ # Padrão 'R$' (Real).
96
+ #
97
+ attr_accessor :especie
98
+
99
+ # Normalmente se vê neste campo a informação "DM" que quer dizer duplicata mercantil,
100
+ # mas existem inúmeros tipos de espécie, <b>neste caso é aconselhável discutir com o banco
101
+ # qual a espécie de documento será utilizada</b>, a identificação incorreta da espécie do documento
102
+ # não vai impedir que o boleto seja pago e nem que o credito seja efetuado na conta do cliente,
103
+ # mas <b>pode ocasionar na impossibilidade de se protestar o boleto caso venha a ser necessário.</b>
104
+ #
105
+ # Segue a sigla e descrição do campo especie do documento:
106
+ #
107
+ # ---------------------------------
108
+ # | Sigla | Descrição |
109
+ # ----------------------------------
110
+ # | NP | Nota Promissória |
111
+ # | NS | Nota de Seguro |
112
+ # | CS | Cobrança Seriada |
113
+ # | REC | Recibo |
114
+ # | LC | Letras de Câmbio |
115
+ # | ND | Notas de débito |
116
+ # | DS | Duplicata de Serviços |
117
+ # | DM | Duplicata Mercantil |
118
+ # ---------------------------------|
119
+ #
120
+ # Padrão 'DM' (Duplicata Mercantil)
121
+ #
122
+ attr_accessor :especie_documento
123
+
124
+ # Data em que o documento foi gerado. Campo auto explicativo.
125
+ #
126
+ attr_accessor :data_documento
127
+
128
+ # Nome do sacado.
129
+ #
130
+ # O sacado é a pessoa para o qual o boleto está sendo emitido, podemos resumir dizendo
131
+ # que o sacado é o cliente do Cedente, ou aquele para o qual uma determina mercadoria
132
+ # foi vendida e o pagamento desta será efetuado por meio de boleto de cobrança.
133
+ #
134
+ # <b>Campo Obrigatório</b>.
135
+ #
136
+ attr_accessor :sacado
137
+
138
+ # Documento do sacado.
139
+ #
140
+ # <b>OBS.: Esse campo não possui validação do campo. Caso você precise imeplemente na subclasse.</b>
141
+ #
142
+ # Esse campo serve apenas para mostrar no boleto no campo "CPF/CNPJ".
143
+ #
144
+ attr_accessor :documento_sacado
145
+
146
+ # Endereço do sacado.
147
+ #
148
+ # <b>OBS.: Esse campo não possui validação do campo. Caso você precise imeplemente na subclasse.</b>
149
+ #
150
+ # Esse campo serve apenas para mostrar no boleto no campo "Sacado".
151
+ #
152
+ attr_accessor :endereco_sacado
153
+
154
+ # Descrição do local do pagamento.
155
+ #
156
+ attr_accessor :local_pagamento
157
+
158
+ # Aceitar após o vencimento.
159
+ # Nessa gem utilizamos o campo aceite como Boolean.
160
+ # Obviamente, true para 'S' e false/nil para 'N'.
161
+ #
162
+ attr_accessor :aceite
163
+
164
+ # Campos de instruções.
165
+ # São permitidas até seis linhas de instruções a serem mostradas no boleto
166
+
167
+ attr_accessor :instrucoes1,
168
+ :instrucoes2,
169
+ :instrucoes3,
170
+ :instrucoes4,
171
+ :instrucoes5,
172
+ :instrucoes6
173
+
174
+ # Caminho do logo do banco.
175
+ #
176
+ attr_accessor :logo
177
+
178
+ # Tamanho maximo do valor do documento do boleto.
179
+ # Acredito que não existirá valor de documento nesse valor,
180
+ # <b>porém a biblioteca precisa manter a consistência</b>.
181
+ #
182
+ # No código de barras o valor do documento precisa
183
+ # ter um tamanho de 8 caracteres para os reais (acrescentando zeros à esquerda),
184
+ # e 2 caracteres nos centavos (acrescentando zeros à esquerda).
185
+ #
186
+ # @return [Float] 99999999.99
187
+ #
188
+ def self.valor_documento_tamanho_maximo
189
+ 99999999.99
190
+ end
191
+
192
+ # Validações de todos os boletos
193
+ #
194
+ validates :carteira, :valor_documento, :numero_documento, :data_vencimento, presence: true
195
+ validates :cedente, :endereco_cedente, presence: true
196
+ validates :sacado, :documento_sacado, presence: true
197
+ validates :valor_documento, numericality: { less_than_or_equal_to: ->(object) { object.class.valor_documento_tamanho_maximo } }
198
+ validate :data_vencimento_deve_ser_uma_data
199
+
200
+ # Passing the attributes as Hash or block
201
+ #
202
+ # @overload initialize(options = {}, &block)
203
+ # @param [Hash] options Passing a hash accessing the attributes of the self.
204
+ # @option options [String] :cedente
205
+ # @option options [String] :codigo_cedente
206
+ # @option options [String] :documento_cedente
207
+ # @option options [String] :endereco_cedente
208
+ # @option options [String] :conta_corrente
209
+ # @option options [String] :agencia
210
+ # @option options [Date] :data_vencimento
211
+ # @option options [String] :numero_documento
212
+ # @option options [Float] :valor_documento
213
+ # @option options [String] :codigo_moeda
214
+ # @option options [String] :especie
215
+ # @option options [String] :especie_documento
216
+ # @option options [String] :sacado
217
+ # @option options [String] :documento_sacado
218
+ #
219
+ # @param [Proc] block Optional params. Passing a block accessing the attributes of the self.
220
+ #
221
+ # For the options, waiting for the ActiveModel 4 and the ActiveModel::Model. :)
222
+ #
223
+ # === Exemplos
224
+ #
225
+ # O recomendado é usar os boletos herdando de seu respectivo banco. Por exemplo:
226
+ #
227
+ # class Itau < BrBoleto::Itau
228
+ # end
229
+ #
230
+ # Agora você pode emitir um boleto usando a classe criada acima:
231
+ #
232
+ # Itau.new(conta_corrente: '89755', agencia: '0097', :carteira => '195')
233
+ #
234
+ # Você pode usar blocos se quiser:
235
+ #
236
+ # Itau.new do |boleto|
237
+ # boleto.conta_corrente = '89755'
238
+ # boleto.agencia = '0097'
239
+ # boleto.carteira = '198'
240
+ # boleto.numero_documento = '12345678'
241
+ # boleto.codigo_cedente = '909014'
242
+ # end
243
+ #
244
+ def initialize(options={}, &block)
245
+ default_options.merge(options).each do |attribute, value|
246
+ send("#{attribute}=", value) if respond_to?("#{attribute}=")
247
+ end
248
+
249
+ yield(self) if block_given?
250
+ end
251
+
252
+ # Opções default.
253
+ #
254
+ # Caso queira sobrescrever as opções, você pode simplesmente instanciar o objeto passando a opção desejada:
255
+ #
256
+ # class Bradesco < BrBoleto::Bradesco
257
+ # end
258
+ #
259
+ # Bradesco.new do |bradesco|
260
+ # bradesco.codigo_moeda = 'outro_codigo_da_moeda'
261
+ # bradesco.especie = 'outra_especie_que_nao_seja_em_reais'
262
+ # bradesco.especie_documento = 'outra_especie_do_documento'
263
+ # bradesco.data_documento = Date.tomorrow
264
+ # bradesco.aceite = false
265
+ # end
266
+ #
267
+ # @return [Hash] Código da Moeda sendo '9' (real). Espécie sendo 'R$' (real).
268
+ #
269
+ def default_options
270
+ {
271
+ :codigo_moeda => '9',
272
+ :especie => 'R$',
273
+ :especie_documento => 'DM',
274
+ :local_pagamento => 'PAGÁVEL EM QUALQUER BANCO ATÉ O VENCIMENTO',
275
+ :data_documento => Date.today,
276
+ :aceite => true
277
+ }
278
+ end
279
+
280
+ # Código do Banco.
281
+ # <b>Esse campo é específico para cada banco</b>.
282
+ #
283
+ # @return [String] Corresponde ao código do banco.
284
+ #
285
+ # @raise [NotImplementedError] Precisa implementar nas subclasses.
286
+ #
287
+ def codigo_banco
288
+ raise NotImplementedError.new("Not implemented #codigo_banco in #{self}.")
289
+ end
290
+
291
+ # Dígito do código do banco.
292
+ # <b>Esse campo é específico para cada banco</b>.
293
+ #
294
+ # @return [String] Corresponde ao dígito do código do banco.
295
+ # @raise [NotImplementedError] Precisa implementar nas subclasses.
296
+ #
297
+ def digito_codigo_banco
298
+ raise NotImplementedError.new("Not implemented #digito_codigo_banco in #{self}.")
299
+ end
300
+
301
+ # Formata o código do banco com o dígito do código do banco.
302
+ # Método usado para o campo de código do banco localizado no cabeçalho do boleto.
303
+ #
304
+ # @return [String]
305
+ #
306
+ def codigo_banco_formatado
307
+ "#{codigo_banco}-#{digito_codigo_banco}"
308
+ end
309
+
310
+ # Agência, código do cedente ou nosso número.
311
+ # <b>Esse campo é específico para cada banco</b>.
312
+ #
313
+ # @return [String] - Corresponde aos campos "Agencia / Codigo do Cedente".
314
+ # @raise [NotImplementedError] Precisa implementar nas subclasses.
315
+ #
316
+ def agencia_codigo_cedente
317
+ raise NotImplementedError.new("Not implemented #agencia_codigo_cedente in #{self}.")
318
+ end
319
+
320
+ # O Nosso Número é o número que identifica unicamente um boleto para uma conta.
321
+ # O tamanho máximo do Nosso Número depende do banco e carteira.
322
+ #
323
+ # <b>Para carteiras registradas, você deve solicitar ao seu banco um intervalo de números para utilização.</b>
324
+ # Quando estiver perto do fim do intervalo, deve solicitar um novo intervalo.
325
+ #
326
+ # <b>Para carteiras não registradas o Nosso Número é livre</b>.
327
+ # Ao receber o retorno do banco, é através do Nosso Número que será possível identificar os boletos pagos.
328
+ #
329
+ # <b>Esse campo é específico para cada banco</b>.
330
+ #
331
+ # @return [String] Corresponde ao formato específico de cada banco.
332
+ # @raise [NotImplementedError] Precisa implementar nas subclasses.
333
+ #
334
+ def nosso_numero
335
+ raise NotImplementedError.new("Not implemented #nosso_numero in #{self}.")
336
+ end
337
+
338
+ # Formata o valor do documentado para ser mostrado no código de barras
339
+ # e na linha digitável com 08 dígitos na casa dos Reais e 02 dígitos nas casas dos centavos.
340
+ #
341
+ # @example
342
+ #
343
+ # Bradesco.new(:valor_documento => 123.45).valor_formatado_para_codigo_de_barras
344
+ # # => "0000012345"
345
+ #
346
+ # @return [String] Precisa retornar 10 dígitos para o código de barras (incluindo os centavos).
347
+ #
348
+ def valor_formatado_para_codigo_de_barras
349
+ valor_documento_formatado = (Integer(valor_documento.to_f * 100) / Float(100))
350
+ real, centavos = valor_documento_formatado.to_s.split(/\./)
351
+ "#{real.rjust(8, '0')}#{centavos.ljust(2, '0')}"
352
+ end
353
+
354
+ # Força a carteira a retornar o valor como string
355
+ #
356
+ # @return [String]
357
+ #
358
+ def carteira
359
+ @carteira.to_s if @carteira.present?
360
+ end
361
+
362
+ # Embora o padrão seja mostrar o número da carteira no boleto,
363
+ # <b>alguns bancos</b> requerem que seja mostrado um valor diferente na carteira.
364
+ # <b>Para essas exceções, sobrescreva esse método na subclasse.</b>
365
+ #
366
+ # @return [String] retorna o número da carteira
367
+ #
368
+ def carteira_formatada
369
+ carteira
370
+ end
371
+
372
+ # Se o aceite for 'true', retorna 'S'.
373
+ # Retorna 'N', caso contrário.
374
+ #
375
+ # @return [String]
376
+ #
377
+ def aceite_formatado
378
+ if @aceite.present?
379
+ 'S'
380
+ else
381
+ 'N'
382
+ end
383
+ end
384
+
385
+ # Fator de vencimento que é calculado a partir de uma data base.
386
+ # Veja <b>FatorVencimento</b> para mais detalhes.
387
+ #
388
+ # @return [String] 4 caracteres.
389
+ #
390
+ def fator_de_vencimento
391
+ FatorVencimento.new(data_vencimento)
392
+ end
393
+
394
+ # === Código de Barras
395
+ #
396
+ # O código de barras contêm exatamente 44 posições nessa sequência:
397
+ #
398
+ # ____________________________________________________________
399
+ # | Posição | Tamanho | Descrição |
400
+ # |----------|---------|--------------------------------------|
401
+ # | 01-03 | 03 | Código do banco |
402
+ # | 04 | 01 | Código da moeda |
403
+ # | 05 | 01 | Dígito do código de barras (DAC) |
404
+ # | 06-09 | 04 | Fator de vencimento |
405
+ # | 10-19 | 10 | Valor do documento |
406
+ # | 20-44 | 25 | Critério de cada Banco (Campo livre) |
407
+ # -------------------------------------------------------------
408
+ #
409
+ # @return [String] Código de barras com 44 posições.
410
+ #
411
+ def codigo_de_barras
412
+ "#{codigo_de_barras_padrao}#{codigo_de_barras_do_banco}".insert(4, digito_codigo_de_barras)
413
+ end
414
+
415
+ # Primeira parte do código de barras.
416
+ # <b>Essa parte do código de barras é padrão para todos os bancos.</b>.
417
+ #
418
+ # @return [String] Primeiras 18 posições do código de barras (<b>Não retorna o DAC do código de barras</b>).
419
+ #
420
+ def codigo_de_barras_padrao
421
+ "#{codigo_banco}#{codigo_moeda}#{fator_de_vencimento}#{valor_formatado_para_codigo_de_barras}"
422
+ end
423
+
424
+ # Segunda parte do código de barras.
425
+ # <b>Esse campo é específico para cada banco</b>.
426
+ #
427
+ # @return [String] 25 últimas posições do código de barras.
428
+ # @raise [NotImplementedError] Precisa implementar nas subclasses.
429
+ #
430
+ def codigo_de_barras_do_banco
431
+ raise NotImplementedError.new("Not implemented #codigo_de_barras_do_banco in #{self}.")
432
+ end
433
+
434
+ # Dígito verificador do código de barras (DAC).
435
+ #
436
+ # Por definição da FEBRABAN e do Banco Central do Brasil,
437
+ # na <b>5º posição do Código de Barras</b>, deve ser indicado obrigatoriamente
438
+ # o “dígito verificador” (DAC), calculado através do módulo 11.
439
+ #
440
+ # <b>OBS.:</b> Para mais detalhes deste cálculo,
441
+ # veja a descrição em <b>BrBoleto::Calculos::Modulo11FatorDe2a9</b>.
442
+ #
443
+ # @return [String] Dígito calculado do código de barras.
444
+ #
445
+ def digito_codigo_de_barras
446
+ Modulo11FatorDe2a9.new("#{codigo_de_barras_padrao}#{codigo_de_barras_do_banco}")
447
+ end
448
+
449
+ # Representação numérica do código de barras, mais conhecida como linha digitável! :p
450
+ #
451
+ # A representação numérica do código de barras é composta, por cinco campos.
452
+ # Sendo os três primeiros campos, amarrados por DAC's (dígitos verificadores),
453
+ # todos calculados pelo módulo 10.
454
+ #
455
+ # <b>OBS.:</b> Para mais detalhes deste cálculo, veja a descrição em Modulo10.
456
+ #
457
+ # === Linha Digitável
458
+ #
459
+ # A linha digitável contêm exatamente 47 posições nessa sequência:
460
+ #
461
+ # _______________________________________________________________________________________________________
462
+ # |Campo | Posição | Tamanho | Descrição |
463
+ # |------|----------|---------|--------------------------------------------------------------------------|
464
+ # | 1º | 01-03 | 03 | Código do banco (posições 1 a 3 do código de barras) |
465
+ # | | 04 | 01 | Código da moeda (posição 4 do código de barras) |
466
+ # | | 05-09 | 5 | Cinco posições do campo livre (posições 20 a 24 do código de barras) |
467
+ # | | 10 | 1 | Dígito verificador do primeiro campo (Módulo10) |
468
+ # |------------------------------------------------------------------------------------------------------|
469
+ # | 2º | 11-20 | 10 | 6º a 15º posições do campo livre (posições 25 a 34 do código de barras) |
470
+ # | | 21 | 01 | Dígito verificador do segundo campo (Módulo10) |
471
+ # |------------------------------------------------------------------------------------------------------|
472
+ # | 3º | 22-31 | 10 | 16º a 25º posições do campo livre (posições 35 a 44 do código de barras) |
473
+ # | | 32 | 01 | Dígito verificador do terceiro campo (Módulo10) |
474
+ # |------------------------------------------------------------------------------------------------------|
475
+ # | 4º | 33 | 01 | Dígito verificador do código de barras (posição 5 do código de barras) |
476
+ # |------------------------------------------------------------------------------------------------------|
477
+ # | 5ª | 34-37 | 04 | Fator de vencimento (posições 6 a 9 do código de barras) |
478
+ # | | 38-47 | 10 | Valor nominal do documento (posições 10 a 19 do código de barras) |
479
+ # -------------------------------------------------------------------------------------------------------|
480
+ #
481
+ # @return [String] Contêm a representação numérica do código de barras formatado com pontos e espaços.
482
+ #
483
+ def linha_digitavel
484
+ LinhaDigitavel.new(codigo_de_barras)
485
+ end
486
+
487
+ # Returns a string that <b>identifying the render path associated with the object</b>.
488
+ #
489
+ # <b>ActionPack uses this to find a suitable partial to represent the object.</b>
490
+ #
491
+ # @return [String]
492
+ #
493
+ def to_partial_path
494
+ "br_boleto/#{self.class.name.demodulize.underscore}"
495
+ end
496
+
497
+ # Seguindo a interface do Active Model.
498
+ #
499
+ # @return [False]
500
+ #
501
+ def persisted?
502
+ false
503
+ end
504
+
505
+ # Método usado para verificar se deve realizar a validação de tamanho do campo 'agência'.
506
+ # <b>Sobrescreva esse método na subclasse, caso você mesmo queira fazer as validações</b>.
507
+ #
508
+ # @return [True]
509
+ #
510
+ def deve_validar_agencia?
511
+ true
512
+ end
513
+
514
+ # Método usado para verificar se deve realizar a validação de tamanho do campo 'conta_corrente'.
515
+ # <b>Sobrescreva esse método na subclasse, caso você mesmo queira fazer as validações</b>.
516
+ #
517
+ # @return [True]
518
+ #
519
+ def deve_validar_conta_corrente?
520
+ true
521
+ end
522
+
523
+ # Método usado para verificar se deve realizar a validação de tamanho do campo 'codigo_cedente'.
524
+ # <b>Sobrescreva esse método na subclasse, caso você mesmo queira fazer as validações</b>.
525
+ #
526
+ # @return [True]
527
+ #
528
+ def deve_validar_codigo_cedente?
529
+ true
530
+ end
531
+
532
+ # Método usado para verificar se deve realizar a validação de tamanho do campo 'numero_documento'.
533
+ # <b>Sobrescreva esse método na subclasse, caso você mesmo queira fazer as validações</b>.
534
+ #
535
+ # @return [True]
536
+ #
537
+ def deve_validar_numero_documento?
538
+ true
539
+ end
540
+
541
+ # Método usado para verificar se deve realizar a validação do campo 'carteira'.
542
+ # <b>Sobrescreva esse método na subclasse, caso você mesmo queira fazer as validações</b>.
543
+ #
544
+ # @return [True]
545
+ #
546
+ def deve_validar_carteira?
547
+ true
548
+ end
549
+
550
+ # Verifica e valida se a data do vencimento deve ser uma data válida.
551
+ # <b>Precisa ser uma data para o cálculo do fator do vencimento.</b>
552
+ #
553
+ def data_vencimento_deve_ser_uma_data
554
+ errors.add(:data_vencimento, :invalid) unless data_vencimento.kind_of?(Date)
555
+ end
556
+ end
557
+ end
558
+ end