br_boleto 1.2.2 → 2.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 (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
  #