br_boleto 1.2.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.markdown +278 -98
  5. data/br_boleto.gemspec +5 -3
  6. data/lib/br_boleto/active_model_base.rb +1 -1
  7. data/lib/br_boleto/association/have_conta.rb +109 -0
  8. data/lib/br_boleto/association/have_pagador.rb +38 -0
  9. data/lib/br_boleto/association/have_pagamentos.rb +44 -0
  10. data/lib/br_boleto/boleto/base.rb +50 -379
  11. data/lib/br_boleto/boleto/caixa.rb +28 -143
  12. data/lib/br_boleto/boleto/sicoob.rb +24 -144
  13. data/lib/br_boleto/conta/base.rb +288 -0
  14. data/lib/br_boleto/conta/caixa.rb +109 -0
  15. data/lib/br_boleto/conta/sicoob.rb +64 -0
  16. data/lib/br_boleto/helper/default_codes.rb +33 -0
  17. data/lib/br_boleto/helper/format_value.rb +1 -0
  18. data/lib/br_boleto/helper/number.rb +30 -0
  19. data/lib/br_boleto/pagador.rb +82 -0
  20. data/lib/br_boleto/remessa/base.rb +28 -50
  21. data/lib/br_boleto/remessa/cnab240/base.rb +22 -131
  22. data/lib/br_boleto/remessa/cnab240/caixa.rb +16 -62
  23. data/lib/br_boleto/remessa/cnab240/helper/header_arquivo.rb +7 -7
  24. data/lib/br_boleto/remessa/cnab240/helper/header_lote.rb +6 -6
  25. data/lib/br_boleto/remessa/cnab240/helper/segmento_p.rb +22 -22
  26. data/lib/br_boleto/remessa/cnab240/helper/segmento_q.rb +16 -16
  27. data/lib/br_boleto/remessa/cnab240/helper/segmento_r.rb +3 -3
  28. data/lib/br_boleto/remessa/cnab240/helper/segmento_s.rb +3 -3
  29. data/lib/br_boleto/remessa/cnab240/helper/trailer_arquivo.rb +3 -3
  30. data/lib/br_boleto/remessa/cnab240/helper/trailer_lote.rb +3 -3
  31. data/lib/br_boleto/remessa/cnab240/sicoob.rb +36 -73
  32. data/lib/br_boleto/remessa/cnab400/base.rb +95 -0
  33. data/lib/br_boleto/remessa/cnab400/helper/detalhe.rb +136 -0
  34. data/lib/br_boleto/remessa/cnab400/helper/header.rb +114 -0
  35. data/lib/br_boleto/remessa/cnab400/helper/trailer.rb +50 -0
  36. data/lib/br_boleto/remessa/cnab400/sicoob.rb +249 -0
  37. data/lib/br_boleto/remessa/lote.rb +1 -23
  38. data/lib/br_boleto/remessa/pagamento.rb +188 -51
  39. data/lib/br_boleto/retorno/base.rb +9 -0
  40. data/lib/br_boleto/retorno/cnab240/base.rb +2 -10
  41. data/lib/br_boleto/retorno/cnab400/base.rb +48 -0
  42. data/lib/br_boleto/retorno/cnab400/sicoob.rb +42 -0
  43. data/lib/br_boleto/retorno/pagamento.rb +12 -6
  44. data/lib/br_boleto/string_methods.rb +8 -2
  45. data/lib/br_boleto/validations.rb +19 -0
  46. data/lib/br_boleto/version.rb +3 -3
  47. data/lib/br_boleto.rb +38 -8
  48. data/lib/config/locales/br-boleto-en.yml +89 -0
  49. data/lib/config/locales/br-boleto-pt-BR.yml +89 -0
  50. data/test/br_boleto/association/have_conta_test.rb +319 -0
  51. data/test/br_boleto/association/have_pagador_test.rb +110 -0
  52. data/test/br_boleto/association/have_pagamentos_test.rb +113 -0
  53. data/test/br_boleto/boleto/base_test.rb +127 -201
  54. data/test/br_boleto/boleto/caixa_test.rb +58 -72
  55. data/test/br_boleto/boleto/sicoob_test.rb +88 -147
  56. data/test/br_boleto/conta/base_test.rb +490 -0
  57. data/test/br_boleto/conta/caixa_test.rb +154 -0
  58. data/test/br_boleto/conta/sicoob_test.rb +144 -0
  59. data/test/br_boleto/helper/number_test.rb +29 -0
  60. data/test/br_boleto/pagador_test.rb +158 -0
  61. data/test/br_boleto/remessa/base_test.rb +37 -62
  62. data/test/br_boleto/remessa/cnab240/base_test.rb +75 -95
  63. data/test/br_boleto/remessa/cnab240/caixa_test.rb +61 -96
  64. data/test/br_boleto/remessa/cnab240/helper/header_arquivo_test.rb +11 -11
  65. data/test/br_boleto/remessa/cnab240/helper/header_lote_test.rb +8 -8
  66. data/test/br_boleto/remessa/cnab240/helper/segmento_p_test.rb +17 -15
  67. data/test/br_boleto/remessa/cnab240/helper/segmento_q_test.rb +13 -13
  68. data/test/br_boleto/remessa/cnab240/helper/segmento_r_test.rb +2 -2
  69. data/test/br_boleto/remessa/cnab240/helper/segmento_s_test.rb +3 -3
  70. data/test/br_boleto/remessa/cnab240/helper/trailer_arquivo_test.rb +1 -1
  71. data/test/br_boleto/remessa/cnab240/helper/trailer_lote_test.rb +1 -1
  72. data/test/br_boleto/remessa/cnab240/sicoob_test.rb +136 -131
  73. data/test/br_boleto/remessa/cnab400/base_test.rb +263 -0
  74. data/test/br_boleto/remessa/cnab400/sicoob_test.rb +179 -0
  75. data/test/br_boleto/remessa/lote_test.rb +2 -41
  76. data/test/br_boleto/remessa/pagamento_test.rb +186 -188
  77. data/test/br_boleto/retorno/base_test.rb +0 -1
  78. data/test/br_boleto/retorno/cnab240/base_test.rb +12 -11
  79. data/test/br_boleto/retorno/cnab240/caixa_test.rb +11 -11
  80. data/test/br_boleto/retorno/cnab240/sicoob_test.rb +11 -11
  81. data/test/br_boleto/retorno/cnab400/sicoob_test.rb +227 -0
  82. data/test/br_boleto/retorno/pagamento_test.rb +6 -6
  83. data/test/factories/boleto/base.rb +9 -7
  84. data/test/factories/boleto/boleto_caixa.rb +2 -9
  85. data/test/factories/boleto/boleto_sicoob.rb +10 -8
  86. data/test/factories/conta/base.rb +10 -0
  87. data/test/factories/conta/caixa.rb +15 -0
  88. data/test/factories/conta/sicoob.rb +16 -0
  89. data/test/factories/pagador.rb +15 -0
  90. data/test/factories/remessa/base.rb +0 -6
  91. data/test/factories/remessa/cnab240/base.rb +0 -10
  92. data/test/factories/remessa/cnab240/caixa.rb +1 -6
  93. data/test/factories/remessa/cnab240/sicoob.rb +1 -10
  94. data/test/factories/remessa/cnab400/base.rb +8 -0
  95. data/test/factories/remessa/cnab400/sicoob.rb +8 -0
  96. data/test/factories/remessa/pagamento.rb +8 -7
  97. data/test/fixtures/remessa/cnab240/sicoob.rem +8 -0
  98. data/test/{files → fixtures}/retorno/cnab240/caixa.ret +0 -0
  99. data/test/{files → fixtures}/retorno/cnab240/padrao240.ret +0 -0
  100. data/test/fixtures/retorno/cnab400/sicoob.ret +7 -0
  101. data/test/inheritance/boleto_test.rb +4 -1
  102. data/test/inheritance/sicoob_test.rb +23 -7
  103. data/test/test_helper.rb +70 -0
  104. metadata +63 -6
@@ -2,7 +2,13 @@
2
2
  module BrBoleto
3
3
  module Remessa
4
4
  class Pagamento < BrBoleto::ActiveModelBase
5
+
6
+ # conté o metodo 'pagador'
7
+ # CNAB: 240 e 400
8
+ include BrBoleto::HavePagador
9
+
5
10
  # <b>REQUERIDO</b>: nosso numero
11
+ # CNAB: 240 e 400
6
12
  attr_accessor :nosso_numero
7
13
 
8
14
  # <b>OPCIONAL</b>: Número do Documento de Cobrança - Número adotado e controlado pelo Cliente,
@@ -10,38 +16,21 @@ module BrBoleto
10
16
  # Informação utilizada para referenciar a identificação do documento objeto de cobrança.
11
17
  # Poderá conter número de duplicata, no caso de cobrança de duplicatas; número da apólice,
12
18
  # no caso de cobrança de seguros, etc
19
+ # CNAB: 240 e 400
13
20
  attr_accessor :numero_documento
14
21
 
15
22
  # <b>REQUERIDO</b>: data do vencimento do boleto
23
+ # CNAB: 240 e 400
16
24
  attr_accessor :data_vencimento
17
25
 
18
26
  # <b>REQUERIDO</b>: data de emissao do boleto
27
+ # CNAB: 240 e 400
19
28
  attr_accessor :data_emissao
20
29
 
21
30
  # <b>REQUERIDO</b>: valor_documento do boleto
31
+ # CNAB: 240 e 400
22
32
  attr_accessor :valor_documento
23
33
 
24
- # <b>REQUERIDO</b>: documento do sacado (cliente)
25
- attr_accessor :documento_sacado
26
-
27
- # <b>REQUERIDO</b>: nome do sacado (cliente)
28
- attr_accessor :nome_sacado
29
-
30
- # <b>REQUERIDO</b>: endereco do sacado (cliente)
31
- attr_accessor :endereco_sacado
32
-
33
- # <b>REQUERIDO</b>: bairro do sacado (cliente)
34
- attr_accessor :bairro_sacado
35
-
36
- # <b>REQUERIDO</b>: CEP do sacado (cliente)
37
- attr_accessor :cep_sacado
38
-
39
- # <b>REQUERIDO</b>: cidade do sacado (cliente)
40
- attr_accessor :cidade_sacado
41
-
42
- # <b>REQUERIDO</b>: UF do sacado (cliente)
43
- attr_accessor :uf_sacado
44
-
45
34
  # <b>REQUERIDO</b>: Tipor de impressão
46
35
  # 1 - Frente do Bloqueto
47
36
  # 2 - Verso do Bloauqto
@@ -49,12 +38,6 @@ module BrBoleto
49
38
  #
50
39
  attr_accessor :tipo_impressao # Default '1'
51
40
 
52
- # <b>OPCIONAL</b>: nome do avalista
53
- attr_accessor :nome_avalista
54
-
55
- # <b>OPCIONAL</b>: documento do avalista
56
- attr_accessor :documento_avalista
57
-
58
41
  # <b>OPCIONAL</b>: codigo da 1a instrucao
59
42
  attr_accessor :cod_primeira_instrucao
60
43
 
@@ -62,12 +45,16 @@ module BrBoleto
62
45
  attr_accessor :cod_segunda_instrucao
63
46
 
64
47
  # <b>OPCIONAL</b>: valor da mora ao dia
48
+ # Dependendo do banco será o valor percentual ou valor em reais
49
+ # CNAB: 240 e 400
65
50
  attr_accessor :valor_mora
66
51
 
67
52
  # <b>OPCIONAL</b>: data limite para o desconto
53
+ # CNAB: 240 e 400
68
54
  attr_accessor :data_desconto
69
55
 
70
56
  # <b>OPCIONAL</b>: valor a ser concedido de desconto
57
+ # CNAB: 240 e 400
71
58
  attr_accessor :valor_desconto
72
59
 
73
60
  # <b>OPCIONAL</b>: codigo do desconto (para CNAB240)
@@ -91,7 +78,12 @@ module BrBoleto
91
78
  # - '2' Taxa Mensal
92
79
  # - '3' Isento
93
80
  # - E Ainda alguns bancos como o SICOOB não conseguem seguir o padrão e usam o cód '0' para Isento
94
- attr_accessor :codigo_multa, :data_multa, :valor_multa
81
+ attr_accessor :codigo_multa, :data_multa
82
+ #CNAB 240 e 400
83
+ attr_accessor :valor_multa # Valor R$
84
+ def percentual_multa # Valor % Ex: 2.5% = 2.5
85
+ BrBoleto::Helper::Number.new(valor_multa).get_percent_by_total(valor_documento)
86
+ end
95
87
 
96
88
  # <b>OPCIONAL</b>: Informações para Juros
97
89
  # Código do juros pode ser:
@@ -99,22 +91,149 @@ module BrBoleto
99
91
  # - '2' Taxa Mensal
100
92
  # - '3' Isento
101
93
  # - E Ainda alguns bancos como o SICOOB não conseguem seguir o padrão e usam o cód '0' para Isento
102
- attr_accessor :codigo_juros, :data_juros, :valor_juros
94
+ attr_accessor :codigo_juros, :data_juros
95
+ attr_accessor :valor_juros # Valor R$
96
+ # É calculado em base no valor do juros
97
+ def percentual_juros # Valor % Ex: 2.5% = 2.5
98
+ BrBoleto::Helper::Number.new(valor_juros).get_percent_by_total(valor_documento)
99
+ end
100
+
101
+ # <b>OPCIONAL</b>: Número da parquela que o pagamento representa
102
+ # Padrão: 1
103
+ # CNAB: 240 e 400
104
+ attr_accessor :parcela
105
+
106
+ # Tipo de Emissão: 1-Banco/Cooperativa 2-Cliente
107
+ # Banco Sicoob utiliza
108
+ # CNAB: 240 e 400
109
+ attr_accessor :tipo_emissao
110
+
111
+ # Comando/Identificação da cobrança/Movimento
112
+ # Default: '01'
113
+ # Exemplos de valores
114
+ # 01 - Registro de títulos
115
+ # 02 - Solicitação de baixa
116
+ # 03 - Pedido de débito em conta
117
+ # 04 - Concessão de abatimento
118
+ # 05 - Cancelamento de abatimento
119
+ # 06 - Alteração de vencimento de título
120
+ # 07 - Alteração do número de controle do participante
121
+ # 08 - Alteração do número do titulo dado pelo cedente
122
+ # 09 - Instrução para protestar (Nota 09)
123
+ # 10 - Instrução para sustar protesto
124
+ # 11 - Instrução para dispensar juros
125
+ # 12 - Alteração de nome e endereço do Sacado
126
+ # 16 – Alterar Juros de Mora (Vide Observações)
127
+ # 31 - Conceder desconto
128
+ # 32 - Não conceder desconto
129
+ # 33 - Retificar dados da concessão de desconto
130
+ # 34 - Alterar data para concessão de desconto
131
+ # 35 - Cobrar multa (Nota 11)
132
+ # 36 - Dispensar multa (Nota 11)
133
+ # 37 - Dispensar indexador
134
+ # 38 - Dispensar prazo limite de recebimento (Nota 11)
135
+ # 39 - Alterar prazo limite de recebimento (Nota 11)
136
+ # 40 – Alterar modalidade (Vide Observações)
137
+ # CNAB: 400
138
+ attr_accessor :identificacao_ocorrencia
139
+
140
+ # Espécie do Título:
141
+ # Default: 01
142
+ # 01 = Duplicata Mercantil
143
+ # 02 = Nota Promissória
144
+ # 03 = Nota de Seguro
145
+ # 05 = Recibo
146
+ # 06 = Duplicata Rural
147
+ # 08 = Letra de Câmbio
148
+ # 09 = Warrant
149
+ # 10 = Cheque
150
+ # 12 = Duplicata de Serviço
151
+ # 13 = Nota de Débito
152
+ # 14 = Triplicata Mercantil
153
+ # 15 = Triplicata de Serviço
154
+ # 18 = Fatura
155
+ # 20 = Apólice de Seguro
156
+ # 21 = Mensalidade Escolar
157
+ # 22 = Parcela de Consórcio
158
+ # 99 = Outros
159
+ # CNAB: 240 e 400
160
+ attr_accessor :especie_titulo
161
+
162
+ # Aceite título
163
+ # "0" = Sem aceite / "1" = Com aceite" / Depende de
164
+ # "N" = Sem aceite / "S" = Com aceite" \ cada banco
165
+ # "N" = Sem aceite / "A" = Com aceite" \
166
+ # CNAB: 240 e 400
167
+ # Setar true para Aceite e false para Não aceite
168
+ attr_accessor :aceite
169
+
170
+ # Moeda
171
+ # '9' = Real
172
+ # CNAB: 400
173
+ attr_accessor :codigo_moeda
174
+
175
+ # forma de cadastramento dos titulos (campo nao tratado pelo Banco do Brasil)
176
+ # opcoes:
177
+ # 1 - com cadastramento (cobrança registrada)
178
+ # 2 - sem cadastramento (cobrança sem registro)
179
+ attr_accessor :forma_cadastramento
180
+
181
+ # Identificação da Emissão do Boleto de Pagamento
182
+ # Código adotado pela FEBRABAN para identificar o responsável e a forma de emissão do
183
+ # Boleto de Pagamento.
184
+ # Domínio:
185
+ # '1' = Banco Emite
186
+ # '2' = Cliente Emite
187
+ # '3' = Banco Pré-emite e Cliente Complementa
188
+ # '4' = Banco Reemite
189
+ # '5' = Banco Não Reemite
190
+ # '7' = Banco Emitente - Aberta
191
+ # '8' = Banco Emitente - Auto-envelopável
192
+ # Os códigos '4' e '5' só serão aceitos para código de movimento para remessa '31'
193
+ attr_accessor :emissao_boleto
194
+
195
+ # Identificação da Distribuição
196
+ # Código adotado pela FEBRABAN para identificar o responsável pela distribuição do
197
+ # Boleto de Pagamento.
198
+ # Domínio:
199
+ # '1' = Banco Distribui
200
+ # '2' = Cliente Distribui
201
+ # ‘3’ = Banco envia e-mail
202
+ # ‘4’ = Banco envia SMS
203
+ attr_accessor :distribuicao_boleto
204
+
205
+ ######################## VALIDAÇÕES PERSONALIZADAS ########################
206
+ attr_accessor :valid_tipo_impressao_required
207
+ validates :tipo_impressao, presence: true, if: :valid_tipo_impressao_required
208
+
209
+ attr_accessor :valid_cod_desconto_length
210
+ validates :cod_desconto, custom_length: {is: :valid_cod_desconto_length}, if: :valid_cod_desconto_length
211
+
212
+ attr_accessor :valid_emissao_boleto_length
213
+ validates :emissao_boleto, custom_length: {is: :valid_emissao_boleto_length}, if: :valid_emissao_boleto_length
214
+
215
+ attr_accessor :valid_distribuicao_boleto_length
216
+ validates :distribuicao_boleto, custom_length: {is: :valid_distribuicao_boleto_length}, if: :valid_distribuicao_boleto_length
217
+ #############################################################################
218
+
219
+ def moeda_real?
220
+ "#{codigo_moeda}" == '9'
221
+ end
222
+ def codigo_moeda
223
+ @codigo_moeda = '9' if @codigo_moeda.blank?
224
+ @codigo_moeda
225
+ end
103
226
 
104
- def cep_sacado
105
- "#{@cep_sacado}".gsub(/[^0-9]/, "")
227
+ def parcela
228
+ @parcela = '1' if @parcela.blank?
229
+ @parcela
106
230
  end
107
231
 
108
232
  def nosso_numero
109
233
  "#{@nosso_numero}".gsub(/[^0-9]/, "")
110
234
  end
111
235
 
112
- validates :nosso_numero, :data_vencimento, :valor_documento, :documento_sacado, :nome_sacado,
113
- :endereco_sacado, :cep_sacado, :cidade_sacado, :uf_sacado, :bairro_sacado, :tipo_impressao,
114
- presence: true
115
-
116
- validates :cep_sacado, length: {is: 8, message: 'deve ter 8 dígitos.'}
117
- validates :cod_desconto, length: {is: 1, message: 'deve ter 1 dígito.'}
236
+ validates :nosso_numero, :data_vencimento, :valor_documento, presence: true
118
237
 
119
238
  def default_values
120
239
  {
@@ -123,7 +242,6 @@ module BrBoleto
123
242
  valor_desconto: 0.0,
124
243
  valor_iof: 0.0,
125
244
  valor_abatimento: 0.0,
126
- nome_avalista: '',
127
245
  cod_desconto: '0',
128
246
  desconto_2_codigo: '0',
129
247
  desconto_2_valor: 0.0,
@@ -133,10 +251,25 @@ module BrBoleto
133
251
  codigo_juros: '3', # Isento
134
252
  valor_multa: 0.0,
135
253
  valor_juros: 0.0,
136
- tipo_impressao: '1'
254
+ parcela: '1',
255
+ tipo_impressao: '1',
256
+ tipo_emissao: '2',
257
+ identificacao_ocorrencia: '01',
258
+ especie_titulo: '01',
259
+ codigo_moeda: '9',
260
+ forma_cadastramento: '0',
261
+ emissao_boleto: '2',
262
+ distribuicao_boleto: '2',
137
263
  }
138
264
  end
139
265
 
266
+ def data_vencimento_formatado(formato='%d%m%Y')
267
+ formata_data(data_vencimento, formato)
268
+ end
269
+ def data_emissao_formatado(formato='%d%m%Y')
270
+ formata_data(data_emissao, formato)
271
+ end
272
+
140
273
  # Formata a data de descontos de acordo com o formato passado
141
274
  #
142
275
  # @return [String]
@@ -215,26 +348,30 @@ module BrBoleto
215
348
  #
216
349
  # @param tamanho [Integer]
217
350
  # quantidade de caracteres a ser retornado
218
- #
351
+ # CNAB: 240 e 400
219
352
  def valor_abatimento_formatado(tamanho = 13)
220
353
  BrBoleto::Helper::Number.new(valor_abatimento).formata_valor_monetario(tamanho)
221
354
  end
222
355
 
223
- # Retorna a identificacao do pagador
224
- # Se for pessoa fisica (CPF com 11 digitos) é 1
225
- # Se for juridica (CNPJ com 14 digitos) é 2
356
+ # Formata o valor percentual da multa
357
+ # Ex:
358
+ # 2.5% = 2.5 = 025000
359
+ # 21.567% = 21.5 = 215670
226
360
  #
227
- def tipo_documento_sacado(tamanho = 2)
228
- BrBoleto::Helper::CpfCnpj.new(documento_sacado).tipo_documento(tamanho)
361
+ def percentual_multa_formatado(tamanho = 6)
362
+ BrBoleto::Helper::Number.new(percentual_multa).formata_valor_percentual(tamanho).adjust_size_to(tamanho, '0')
229
363
  end
230
-
231
- # Retorna a identificacao do avalista
232
- # Se for pessoa fisica (CPF com 11 digitos) é 1
233
- # Se for juridica (CNPJ com 14 digitos) é 2
364
+
365
+ # Formata o valor percentual do juros
366
+ # Ex:
367
+ # 2.5% = 2.5 = 025000
368
+ # 21.567% = 21.5 = 215670
234
369
  #
235
- def tipo_documento_avalista(tamanho = 2)
236
- BrBoleto::Helper::CpfCnpj.new(documento_avalista).tipo_documento(tamanho)
370
+ def percentual_juros_formatado(tamanho = 6)
371
+ BrBoleto::Helper::Number.new(percentual_juros).formata_valor_percentual(tamanho).adjust_size_to(tamanho, '0')
237
372
  end
373
+
374
+
238
375
  private
239
376
 
240
377
  def formata_data(value, formato="%d%m%Y")
@@ -29,6 +29,15 @@ module BrBoleto
29
29
  def read_file!
30
30
  raise NotImplementedError.new('Sobreescreva este método na classe referente ao CNAB 240 ou 400')
31
31
  end
32
+
33
+ # Resolve problema quando existe algum caractere com acentuação e encode UTF-16
34
+ # converte esse caractere para ? e converte para o encode UTF-8.
35
+ # Fix issue #5
36
+ #
37
+ def adjust_encode(line)
38
+ line.encode!("UTF-16be", invalid: :replace, replace: "?").encode!('UTF-8')
39
+ end
40
+
32
41
  end
33
42
  end
34
43
  end
@@ -82,8 +82,8 @@ module BrBoleto
82
82
  valor_iof: 63..77,
83
83
  valor_pago: 78..92,
84
84
  valor_liquido: 93..107,
85
- valor_coutras_despesas: 108..122,
86
- valor_coutros_creditos: 123..137,
85
+ valor_outras_despesas: 108..122,
86
+ valor_outros_creditos: 123..137,
87
87
  data_ocorrencia: 138..145,
88
88
  data_credito: 146..153,
89
89
  codigo_ocorrencia_sacado: 154..157,
@@ -95,14 +95,6 @@ module BrBoleto
95
95
  }
96
96
  end
97
97
 
98
- # Resolve problema quando existe algum caractere com acentuação e encode UTF-16
99
- # converte esse caractere para ? e converte para o encode UTF-8.
100
- # Fix issue #5
101
- #
102
- def adjust_encode(line)
103
- line.encode!("UTF-16be", invalid: :replace, replace: "?").encode!('UTF-8')
104
- end
105
-
106
98
  end
107
99
  end
108
100
  end
@@ -0,0 +1,48 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BrBoleto
3
+ module Retorno
4
+ module Cnab400
5
+ class Base < BrBoleto::Retorno::Base
6
+ # É necessário sobrescrever o método `detalhe_fields` para cada banco, pois o CNAB 400
7
+ # Não apresenta um padrão definido.
8
+ #
9
+ private
10
+
11
+ # É feito um loop em todas as linhas do arquivo considerando apenas as linhas de detalhe
12
+ # Cada linha representa um pagamento.
13
+ #
14
+ def read_file! #:doc:
15
+ lines = File.readlines(file).map{|l| adjust_encode(l)}
16
+ set_codigo_banco(lines)
17
+ # Ignora a 1ª Linha (Header) e a Última linha (Trailer)
18
+ lines[1..lines.size-2].each do |line|
19
+ instnce_payment(line)
20
+ end
21
+ pagamentos
22
+ end
23
+
24
+ # Intsnacia um pagamento através do texto da linha recebida or parâmetro
25
+ # e adiciona o mesmo no Array de pagamentos
26
+ #
27
+ def instnce_payment(detalhe) #:doc:
28
+ payment = BrBoleto::Retorno::Pagamento.new
29
+ detalhe_fields.each do |column, position |
30
+ payment.send("#{column}=", "_#{detalhe}"[position].try(:strip))
31
+ end
32
+ self.pagamentos << payment
33
+ end
34
+
35
+ def detalhe_fields #:doc:
36
+ raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
37
+ end
38
+
39
+ # Pega o código do banco que está presente no Header do arquivo, onde que por
40
+ # padrão é encontrado nas posições 77,78 e 79.
41
+ def set_codigo_banco(lines)
42
+ return if lines.blank?
43
+ self.codigo_banco = "_#{lines[0]}"[77..79]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BrBoleto
3
+ module Retorno
4
+ module Cnab400
5
+ class Sicoob < BrBoleto::Retorno::Cnab400::Base
6
+ private
7
+ def detalhe_fields #:doc:
8
+ { # ATRIBUTO POSIÇÃO DA LINHA
9
+ agencia_sem_dv: 18..21,
10
+ agencia_com_dv: 18..22,
11
+ numero_conta_com_dv: 23..31,
12
+ numero_conta_sem_dv: 23..30,
13
+ nosso_numero: 63..74,
14
+ parcela: 75..76,
15
+ modalidade: 107..108,
16
+ carteira: 108,
17
+ data_ocorrencia: 111..116,
18
+ data_ocorrencia_sacado: 111..116,
19
+ numero_documento: 117..131,
20
+ data_vencimento: 147..152,
21
+ valor_titulo: 153..165,
22
+ banco_recebedor: 166..168,
23
+ agencia_recebedora_com_dv: 169..173,
24
+ especie_titulo: 174..175,
25
+ data_credito: 176..181,
26
+ valor_tarifa: 182..188,
27
+ valor_outras_despesas: 189..201,
28
+ valor_juros_multa: 267..279,
29
+ valor_iof: 215..227,
30
+ valor_abatimento: 228..240,
31
+ valor_desconto: 241..253,
32
+ valor_pago: 254..266,
33
+ valor_ocorrencia_sacado: 254..266,
34
+ valor_liquido: 254..266,
35
+ valor_outros_creditos: 280..292,
36
+ sacado_documento: 343..356,
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -134,15 +134,15 @@ module BrBoleto
134
134
  # 15 93-107
135
135
  attr_accessor :valor_liquido
136
136
 
137
- # VALRO COM COUTRAS DESPESAS
137
+ # VALRO COM outras DESPESAS
138
138
  # Tamanho Posição
139
139
  # 15 108-122
140
- attr_accessor :valor_coutras_despesas
140
+ attr_accessor :valor_outras_despesas
141
141
 
142
- # VALRO COM COUTROS CRÉDITOS
142
+ # VALRO COM outros CRÉDITOS
143
143
  # Tamanho Posição
144
144
  # 15 123-137
145
- attr_accessor :valor_coutros_creditos
145
+ attr_accessor :valor_outros_creditos
146
146
 
147
147
  # DATA OCORRÊNCIA
148
148
  # Tamanho Posição
@@ -190,6 +190,12 @@ module BrBoleto
190
190
  # É implementado apenas para os bancos que não conseguem seguir um padrão estabelecido
191
191
  attr_accessor :modalidade
192
192
 
193
+
194
+ attr_accessor :parcela
195
+
196
+ # Prefixo do Título: Informa Espécie do Título
197
+ attr_accessor :especie_titulo
198
+
193
199
  def initialize(attributes = {})
194
200
  define_formatted_methods!
195
201
  super
@@ -209,8 +215,8 @@ module BrBoleto
209
215
  valor_iof: {type: :float},
210
216
  valor_pago: {type: :float},
211
217
  valor_liquido: {type: :float},
212
- valor_coutras_despesas: {type: :float},
213
- valor_coutros_creditos: {type: :float},
218
+ valor_outras_despesas: {type: :float},
219
+ valor_outros_creditos: {type: :float},
214
220
  valor_ocorrencia_sacado: {type: :float},
215
221
  }
216
222
  end
@@ -6,13 +6,19 @@ module BrBoleto
6
6
  # se a string for menor, adiciona espacos a direita
7
7
  # se a string for maior, trunca para o num. de caracteres
8
8
  #
9
- def adjust_size_to(size, adjust=" ")
9
+ def adjust_size_to(size, adjust=" ", orientation=:left)
10
10
  if self.size > size
11
11
  truncate(size, omission: '')
12
- else
12
+ elsif orientation == :left
13
13
  ljust(size, adjust)
14
+ else
15
+ rjust(size, adjust)
14
16
  end
15
17
  end
18
+
19
+ def only_numbers
20
+ self.gsub(/[^\d]/, '')
21
+ end
16
22
  end
17
23
  end
18
24
 
@@ -0,0 +1,19 @@
1
+ class CustomLengthValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ is_value = max_value = min_value = nil
4
+ max_value = options[:maximum].is_a?(Symbol) ? record.send(options[:maximum]).to_i : options[:maximum]
5
+ min_value = options[:minimum].is_a?(Symbol) ? record.send(options[:minimum]).to_i : options[:minimum]
6
+ is_value = options[:is].is_a?(Symbol) ? record.send(options[:is]).to_i : options[:is]
7
+ record.errors.add(attribute, :custom_length_maximum, count: max_value) if max_value && "#{record.try(attribute)}".strip.size > max_value
8
+ record.errors.add(attribute, :custom_length_minimum, count: min_value) if min_value && "#{record.try(attribute)}".strip.size < min_value
9
+ record.errors.add(attribute, :custom_length_is, count: is_value ) if is_value && "#{record.try(attribute)}".strip.size != is_value
10
+ end
11
+ end
12
+
13
+ class CustomInclusionValidator < ActiveModel::EachValidator
14
+ def validate_each(record, attribute, value)
15
+ in_values = [options[:in].is_a?(Symbol) ? record.send(options[:in]) : options[:in]].flatten.compact.map(&:to_s)
16
+ record.errors.add(attribute, :custom_inclusion, list: in_values.join(', ') ) if in_values.any? && !"#{record.try(attribute)}".strip.in?(in_values)
17
+ end
18
+ end
19
+
@@ -1,8 +1,8 @@
1
1
  module BrBoleto
2
2
  module Version
3
- MAJOR = 1 #inclui alterações de API e pode quebrar compatibilidade com versões anteriores
4
- MINOR = 2 #inclui novas funcionalidades, sem quebrar APIs existentes
5
- PATCH = 2 #corrige bugs ou traz melhorias em implementações já existentes
3
+ MAJOR = 2 #inclui alterações de API e pode quebrar compatibilidade com versões anteriores
4
+ MINOR = 0 #inclui novas funcionalidades, sem quebrar APIs existentes
5
+ PATCH = 0 #corrige bugs ou traz melhorias em implementações já existentes
6
6
  CURRENT = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
8
8
  end
data/lib/br_boleto.rb CHANGED
@@ -7,6 +7,11 @@ require 'active_support/core_ext/object'
7
7
  require 'active_support/core_ext/string'
8
8
 
9
9
  require 'br_boleto/string_methods'
10
+ require 'br_boleto/validations'
11
+
12
+ require 'br_boleto/association/have_conta'
13
+ require 'br_boleto/association/have_pagador'
14
+ require 'br_boleto/association/have_pagamentos'
10
15
 
11
16
  # Copyright (C) 2015 Bruno M. Mergen <http://duobr.com.br>
12
17
  #
@@ -40,14 +45,35 @@ require 'br_boleto/string_methods'
40
45
  # bundle install
41
46
  #
42
47
  module BrBoleto
43
-
44
48
  def self.root
45
49
  File.expand_path '../..', __FILE__
46
50
  end
47
51
 
52
+ I18n.load_path += Dir[BrBoleto.root+'/lib/config'+ '/locales'+'/**'+'/*.{rb,yml}']
53
+
48
54
  extend ActiveSupport::Autoload
49
55
  autoload :ActiveModelBase
50
56
 
57
+ module Helper
58
+ extend ActiveSupport::Autoload
59
+
60
+ autoload :DefaultCodes
61
+ autoload :CpfCnpj
62
+ autoload :Number
63
+ autoload :FormatValue
64
+ end
65
+
66
+
67
+ autoload :Pagador
68
+
69
+
70
+ module Conta
71
+ extend ActiveSupport::Autoload
72
+ autoload :Base
73
+ autoload :Sicoob
74
+ autoload :Caixa
75
+ end
76
+
51
77
  module Boleto
52
78
  extend ActiveSupport::Autoload
53
79
 
@@ -69,6 +95,11 @@ module BrBoleto
69
95
  autoload :Sicoob
70
96
  autoload :Caixa
71
97
  end
98
+ module Cnab400
99
+ extend ActiveSupport::Autoload
100
+ autoload :Base
101
+ autoload :Sicoob
102
+ end
72
103
  end
73
104
 
74
105
  module Retorno
@@ -81,15 +112,14 @@ module BrBoleto
81
112
  autoload :Sicoob
82
113
  autoload :Caixa
83
114
  end
115
+ module Cnab400
116
+ extend ActiveSupport::Autoload
117
+ autoload :Base
118
+ autoload :Sicoob
119
+ end
84
120
  end
85
121
 
86
- module Helper
87
- extend ActiveSupport::Autoload
88
-
89
- autoload :CpfCnpj
90
- autoload :Number
91
- autoload :FormatValue
92
- end
122
+
93
123
 
94
124
  # Módulo que possui classes que realizam os cálculos dos campos que serão mostrados nos boletos.
95
125
  #