brcobranca 4.1.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -1
- data/.rspec +1 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +2 -1
- data/Gemfile +4 -4
- data/Gemfile.lock +65 -53
- data/README.md +18 -5
- data/brcobranca.gemspec +8 -6
- data/lib/brcobranca/boleto/banco_brasil.rb +25 -27
- data/lib/brcobranca/boleto/base.rb +13 -6
- data/lib/brcobranca/boleto/bradesco.rb +4 -1
- data/lib/brcobranca/boleto/caixa.rb +14 -4
- data/lib/brcobranca/boleto/hsbc.rb +26 -26
- data/lib/brcobranca/boleto/santander.rb +6 -3
- data/lib/brcobranca/boleto/sicredi.rb +3 -5
- data/lib/brcobranca/boleto/template/rghost.rb +7 -5
- data/lib/brcobranca/boleto/template/rghost_carne.rb +1 -2
- data/lib/brcobranca/calculo.rb +19 -93
- data/lib/brcobranca/formatacao_string.rb +21 -0
- data/lib/brcobranca/remessa/base.rb +59 -0
- data/lib/brcobranca/remessa/cnab240/banco_brasil.rb +117 -0
- data/lib/brcobranca/remessa/cnab240/base.rb +379 -0
- data/lib/brcobranca/remessa/cnab240/caixa.rb +103 -0
- data/lib/brcobranca/remessa/cnab400/base.rb +112 -0
- data/lib/brcobranca/remessa/cnab400/bradesco.rb +128 -0
- data/lib/brcobranca/remessa/cnab400/itau.rb +149 -0
- data/lib/brcobranca/remessa/pagamento.rb +159 -0
- data/lib/brcobranca/retorno/base.rb +1 -0
- data/lib/brcobranca/retorno/retorno_cnab400.rb +0 -2
- data/lib/brcobranca/version.rb +1 -1
- data/lib/brcobranca.rb +33 -17
- data/spec/brcobranca/banco_bradesco_spec.rb +0 -2
- data/spec/brcobranca/banco_brasil_spec.rb +0 -2
- data/spec/brcobranca/banco_caixa_spec.rb +0 -2
- data/spec/brcobranca/banco_hsbc_spec.rb +0 -3
- data/spec/brcobranca/banco_itau_spec.rb +0 -1
- data/spec/brcobranca/banco_santander_spec.rb +14 -14
- data/spec/brcobranca/banco_sicredi_spec.rb +0 -2
- data/spec/brcobranca/base_spec.rb +11 -0
- data/spec/brcobranca/boletos_em_lote_spec.rb +0 -2
- data/spec/brcobranca/core_ext_spec.rb +104 -58
- data/spec/brcobranca/remessa/base_spec.rb +87 -0
- data/spec/brcobranca/remessa/cnab240/banco_brasil_spec.rb +200 -0
- data/spec/brcobranca/remessa/cnab240/base_spec.rb +88 -0
- data/spec/brcobranca/remessa/cnab240/caixa_spec.rb +137 -0
- data/spec/brcobranca/remessa/cnab400/base_spec.rb +51 -0
- data/spec/brcobranca/remessa/cnab400/bradesco_spec.rb +174 -0
- data/spec/brcobranca/remessa/cnab400/itau_spec.rb +160 -0
- data/spec/brcobranca/remessa/pagamento_spec.rb +197 -0
- data/spec/brcobranca/retorno_cbr643_spec.rb +0 -2
- data/spec/brcobranca/rghost_spec.rb +0 -2
- data/spec/shared_examples/cnab240.rb +206 -0
- data/spec/shared_examples/cnab400.rb +85 -0
- metadata +34 -4
@@ -102,7 +102,6 @@ module Brcobranca
|
|
102
102
|
fail 'Não foi possível encontrar o template. Verifique o caminho' unless File.exist?(template_path)
|
103
103
|
|
104
104
|
boletos.each_with_index do |boleto, index|
|
105
|
-
|
106
105
|
modelo_generico_template(doc, boleto, template_path)
|
107
106
|
modelo_generico_cabecalho(doc, boleto)
|
108
107
|
modelo_generico_rodape(doc, boleto)
|
@@ -111,7 +110,6 @@ module Brcobranca
|
|
111
110
|
doc.barcode_interleaved2of5(boleto.codigo_barras, width: '10.3 cm', height: '1.3 cm', x: '0.7 cm', y: '5.8 cm') if boleto.codigo_barras
|
112
111
|
# Cria nova página se não for o último boleto
|
113
112
|
doc.next_page unless index == boletos.length - 1
|
114
|
-
|
115
113
|
end
|
116
114
|
# Gerando stream
|
117
115
|
formato = (options.delete(:formato) || Brcobranca.configuration.formato)
|
@@ -177,10 +175,14 @@ module Brcobranca
|
|
177
175
|
doc.show boleto.local_pagamento
|
178
176
|
doc.moveto x: '16.5 cm', y: '16 cm'
|
179
177
|
doc.show boleto.data_vencimento.to_s_br if boleto.data_vencimento
|
180
|
-
doc.moveto x: '1.9 cm', y: '15.5 cm'
|
181
|
-
doc.show boleto.cedente
|
182
178
|
doc.moveto x: '0.7 cm', y: '15.2 cm'
|
183
|
-
|
179
|
+
if boleto.cedente_endereco
|
180
|
+
doc.show boleto.cedente_endereco
|
181
|
+
doc.moveto x: '1.9 cm', y: '15.5 cm'
|
182
|
+
doc.show boleto.cedente
|
183
|
+
else
|
184
|
+
doc.show boleto.cedente
|
185
|
+
end
|
184
186
|
doc.moveto x: '16.5 cm', y: '15.2 cm'
|
185
187
|
doc.show boleto.agencia_conta_boleto
|
186
188
|
doc.moveto x: '0.7 cm', y: '14.4 cm'
|
@@ -104,7 +104,7 @@ module Brcobranca
|
|
104
104
|
modelo_carne_define_tags(doc)
|
105
105
|
|
106
106
|
boletos.each_with_index do |boleto, index|
|
107
|
-
curr_page_position
|
107
|
+
curr_page_position += 1
|
108
108
|
|
109
109
|
margin_bottom = initial_margin_bottom + (heigth_template * (max_per_page - curr_page_position)) # onde o boleto sera impresso na pagina A4
|
110
110
|
|
@@ -122,7 +122,6 @@ module Brcobranca
|
|
122
122
|
|
123
123
|
curr_page_position = 0 # reinicia contador por página
|
124
124
|
end
|
125
|
-
|
126
125
|
end
|
127
126
|
|
128
127
|
# Gerando stream
|
data/lib/brcobranca/calculo.rb
CHANGED
@@ -22,91 +22,21 @@ module Brcobranca
|
|
22
22
|
valor == 10 ? 0 : valor
|
23
23
|
end
|
24
24
|
|
25
|
-
# Calcula módulo 11
|
25
|
+
# Calcula o módulo 11 segundo a BACEN
|
26
26
|
#
|
27
27
|
# @return [Integer]
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
# @return [Integer]
|
37
|
-
def modulo11_2to9
|
38
|
-
total = multiplicador([2, 3, 4, 5, 6, 7, 8, 9])
|
39
|
-
|
40
|
-
valor = (11 - (total % 11))
|
41
|
-
[0, 10, 11].include?(valor) ? 1 : valor
|
42
|
-
end
|
43
|
-
|
44
|
-
# Calcula módulo 11 com multiplicadores de 2 a 9 e 2 a 5 (Utilizado pelo Santander).
|
45
|
-
#
|
46
|
-
# @return [Integer]
|
47
|
-
def modulo11_santander
|
48
|
-
return 0 if self.to_i == 0
|
49
|
-
|
50
|
-
somatorio = 0
|
51
|
-
multiplicadores = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5]
|
52
|
-
base = "#{self.rjust(12, '0')}".reverse
|
53
|
-
index = 0
|
54
|
-
|
55
|
-
base.each_char do |char|
|
56
|
-
somatorio += base[index].to_i * multiplicadores[index].to_i
|
57
|
-
index += 1
|
58
|
-
end
|
59
|
-
|
60
|
-
resto = somatorio % 11
|
61
|
-
return 1 if resto == 10
|
62
|
-
return 0 if resto == 1 || resto == 0
|
63
|
-
return 11 - resto
|
64
|
-
end
|
65
|
-
|
66
|
-
# Calcula módulo 11 com multiplicadores de 2, 7 a 2, e 7 a 2 (Utilizado pelo Bradesco).
|
67
|
-
#
|
68
|
-
# @return [Integer, String] Caso o resto seja 1, retorna P
|
69
|
-
|
70
|
-
def modulo11_bradesco
|
71
|
-
somatorio = 0
|
72
|
-
multiplicadores = [2, 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2]
|
73
|
-
index = 0
|
74
|
-
|
75
|
-
self.each_char do |char|
|
76
|
-
somatorio += self[index].to_i * multiplicadores[index]
|
77
|
-
index += 1
|
78
|
-
end
|
79
|
-
|
80
|
-
resto = somatorio % 11
|
81
|
-
return 0 if resto == 0
|
82
|
-
return 'P' if resto == 1
|
83
|
-
return 11 - resto
|
84
|
-
end
|
85
|
-
|
86
|
-
# Calcula módulo 11 com multiplicaroes de 2 a 9 (Utilizado pela CAIXA - boletos SIGCB).
|
87
|
-
#
|
88
|
-
# @return [Integer]
|
89
|
-
def modulo11_2to9_caixa
|
90
|
-
total = multiplicador([2, 3, 4, 5, 6, 7, 8, 9])
|
91
|
-
total = (total % 11) unless total < 11
|
92
|
-
valor = (11 - total)
|
93
|
-
valor > 9 ? 0 : valor
|
94
|
-
end
|
28
|
+
# @raise [ArgumentError] Caso não seja um número inteiro.
|
29
|
+
# @param [Hash] options Opções para o cálculo do módulo
|
30
|
+
# @option options [Hash] :mapeamento Mapeamento do valor final. Ex: { 10 => "X" }. Padrão: {}
|
31
|
+
# @option options [Array] :multiplicador Números a serem utilizados na multiplicação da direita para a esquerda. Padrão: [9 até 2]
|
32
|
+
def modulo11(options = {}, &_block)
|
33
|
+
options[:mapeamento] ||= {}
|
34
|
+
options[:multiplicador] ||= [9, 8, 7, 6, 5, 4, 3, 2]
|
95
35
|
|
96
|
-
|
97
|
-
|
98
|
-
# @return [Integer, String] Caso resultado for 10, retorna X.
|
99
|
-
def modulo11_9to2_10_como_x
|
100
|
-
valor = modulo11_9to2
|
101
|
-
valor == 10 ? 'X' : valor
|
102
|
-
end
|
36
|
+
total = multiplicador(options[:multiplicador])
|
37
|
+
valor = block_given? ? yield(total) : (total % 11)
|
103
38
|
|
104
|
-
|
105
|
-
#
|
106
|
-
# @return [Integer]
|
107
|
-
def modulo11_9to2_10_como_zero
|
108
|
-
valor = modulo11_9to2
|
109
|
-
valor == 10 ? 0 : valor
|
39
|
+
options[:mapeamento][valor] || valor
|
110
40
|
end
|
111
41
|
|
112
42
|
# Verifica se String só contem caracteres numéricos.
|
@@ -125,13 +55,13 @@ module Brcobranca
|
|
125
55
|
# 13 (1+3) #=> 4
|
126
56
|
def soma_digitos
|
127
57
|
total = case to_i
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
58
|
+
when (0..9)
|
59
|
+
self
|
60
|
+
else
|
61
|
+
numero = to_s
|
62
|
+
total = 0
|
63
|
+
0.upto(numero.size - 1) { |digito| total += numero[digito, 1].to_i }
|
64
|
+
total
|
135
65
|
end
|
136
66
|
total.to_i
|
137
67
|
end
|
@@ -149,11 +79,7 @@ module Brcobranca
|
|
149
79
|
|
150
80
|
to_s.split(//).reverse!.each do |caracter|
|
151
81
|
fator = fatores[multiplicador_posicao]
|
152
|
-
total +=
|
153
|
-
yield(caracter, fator)
|
154
|
-
else
|
155
|
-
(caracter.to_i * fator)
|
156
|
-
end
|
82
|
+
total += block_given? ? yield(caracter, fator) : (caracter.to_i * fator)
|
157
83
|
multiplicador_posicao = (multiplicador_posicao < (fatores.size - 1)) ? (multiplicador_posicao + 1) : 0
|
158
84
|
end
|
159
85
|
total
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Brcobranca
|
2
|
+
# Métodos auxiliares de formatação de strings
|
3
|
+
module FormatacaoString
|
4
|
+
# Formata o tamanho da string
|
5
|
+
# para o tamanho passado
|
6
|
+
# se a string for menor, adiciona espacos a direita
|
7
|
+
# se a string for maior, trunca para o num. de caracteres
|
8
|
+
#
|
9
|
+
def format_size(size)
|
10
|
+
if self.size > size
|
11
|
+
return truncate(size, omission: '')
|
12
|
+
else
|
13
|
+
return ljust(size, ' ')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
[String].each do |klass|
|
20
|
+
klass.class_eval { include Brcobranca::FormatacaoString }
|
21
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Brcobranca
|
3
|
+
module Remessa
|
4
|
+
class Base
|
5
|
+
# pagamentos da remessa (cada pagamento representa um registro detalhe no arquivo)
|
6
|
+
attr_accessor :pagamentos
|
7
|
+
# empresa mae (razao social)
|
8
|
+
attr_accessor :empresa_mae
|
9
|
+
# agencia (sem digito verificador)
|
10
|
+
attr_accessor :agencia
|
11
|
+
# numero da conta corrente
|
12
|
+
attr_accessor :conta_corrente
|
13
|
+
# digito verificador da conta corrente
|
14
|
+
attr_accessor :digito_conta
|
15
|
+
# carteira do cedente
|
16
|
+
attr_accessor :carteira
|
17
|
+
# sequencial remessa (num. sequencial que nao pode ser repetido nem zerado)
|
18
|
+
attr_accessor :sequencial_remessa
|
19
|
+
# aceite (A = ACEITO/N = NAO ACEITO)
|
20
|
+
attr_accessor :aceite
|
21
|
+
|
22
|
+
# Validações do Rails 3
|
23
|
+
include ActiveModel::Validations
|
24
|
+
|
25
|
+
validates_presence_of :pagamentos, :empresa_mae, :agencia, :conta_corrente, message: 'não pode estar em branco.'
|
26
|
+
validates_length_of :empresa_mae, maximum: 30, message: 'deve ser menor ou igual a 30 caracteres.'
|
27
|
+
|
28
|
+
validates_each :pagamentos do |record, attr, value|
|
29
|
+
if value.is_a? Array
|
30
|
+
record.errors.add(attr, 'não pode estar vazio.') if value.empty?
|
31
|
+
value.each do |pagamento|
|
32
|
+
if pagamento.is_a? Brcobranca::Remessa::Pagamento
|
33
|
+
if pagamento.invalid?
|
34
|
+
pagamento.errors.full_messages.each { |msg| record.errors.add(attr, msg) }
|
35
|
+
end
|
36
|
+
else
|
37
|
+
record.errors.add(attr, 'cada item deve ser um objeto Pagamento.')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
record.errors.add(attr, 'deve ser uma coleção (Array).')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Nova instancia da classe
|
46
|
+
#
|
47
|
+
# @param campos [Hash]
|
48
|
+
#
|
49
|
+
def initialize(campos = {})
|
50
|
+
campos = { aceite: 'N' }.merge!(campos)
|
51
|
+
campos.each do |campo, valor|
|
52
|
+
send "#{campo}=", valor
|
53
|
+
end
|
54
|
+
|
55
|
+
yield self if block_given?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Brcobranca
|
3
|
+
module Remessa
|
4
|
+
module Cnab240
|
5
|
+
class BancoBrasil < Brcobranca::Remessa::Cnab240::Base
|
6
|
+
# variacao da carteira
|
7
|
+
attr_accessor :variacao
|
8
|
+
# identificacao da emissao do boleto (attr na classe base)
|
9
|
+
# campo nao tratado pelo sistema do Banco do Brasil
|
10
|
+
# identificacao da distribuicao do boleto (attr na classe base)
|
11
|
+
# campo nao tratado pelo sistema do Banco do Brasil
|
12
|
+
|
13
|
+
validates_presence_of :carteira, :variacao, message: 'não pode estar em branco.'
|
14
|
+
validates_length_of :conta_corrente, is: 5, message: 'deve ter 5 dígitos.'
|
15
|
+
validates_length_of :agencia, is: 4, message: 'deve ter 4 dígitos.'
|
16
|
+
validates_length_of :carteira, is: 2, message: 'deve ter 2 dígitos.'
|
17
|
+
validates_length_of :variacao, is: 3, message: 'deve ter 3 dígitos.'
|
18
|
+
validates_length_of :convenio, in: 4..7, message: 'não existente para este banco.'
|
19
|
+
|
20
|
+
def initialize(campos = {})
|
21
|
+
campos = { emissao_boleto: '0',
|
22
|
+
distribuicao_boleto: '0',
|
23
|
+
especie_titulo: '02' }.merge!(campos)
|
24
|
+
super(campos)
|
25
|
+
end
|
26
|
+
|
27
|
+
def cod_banco
|
28
|
+
'001'
|
29
|
+
end
|
30
|
+
|
31
|
+
def nome_banco
|
32
|
+
'BANCO DO BRASIL S.A.'.ljust(30, ' ')
|
33
|
+
end
|
34
|
+
|
35
|
+
def versao_layout
|
36
|
+
'000'
|
37
|
+
end
|
38
|
+
|
39
|
+
def digito_agencia
|
40
|
+
# utilizando a agencia com 4 digitos
|
41
|
+
# para calcular o digito
|
42
|
+
agencia.modulo11(mapeamento: { 10 => 'X' }).to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
def digito_conta
|
46
|
+
# utilizando a conta corrente com 5 digitos
|
47
|
+
# para calcular o digito
|
48
|
+
conta_corrente.modulo11(mapeamento: { 10 => 'X' }).to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
def codigo_convenio
|
52
|
+
# CAMPO TAMANHO
|
53
|
+
# num. convenio 9
|
54
|
+
# cobranca cedente 4
|
55
|
+
# carteira 2
|
56
|
+
# variacao carteira 3
|
57
|
+
# campo reservado 2
|
58
|
+
"#{convenio.rjust(9, '0')}0014#{carteira}#{variacao} "
|
59
|
+
end
|
60
|
+
alias_method :convenio_lote, :codigo_convenio
|
61
|
+
|
62
|
+
def info_conta
|
63
|
+
# CAMPO TAMANHO
|
64
|
+
# agencia 5
|
65
|
+
# digito agencia 1
|
66
|
+
# conta corrente 12
|
67
|
+
# digito conta 1
|
68
|
+
# digito agencia/conta 1
|
69
|
+
"#{agencia.rjust(5, '0')}#{digito_agencia}#{conta_corrente.rjust(12, '0')}#{digito_conta} "
|
70
|
+
end
|
71
|
+
|
72
|
+
def complemento_header
|
73
|
+
''.rjust(29, ' ')
|
74
|
+
end
|
75
|
+
|
76
|
+
def complemento_trailer
|
77
|
+
''.rjust(217, ' ')
|
78
|
+
end
|
79
|
+
|
80
|
+
def complemento_p(pagamento)
|
81
|
+
# CAMPO TAMANHO
|
82
|
+
# conta corrente 12
|
83
|
+
# digito conta 1
|
84
|
+
# digito agencia/conta 1
|
85
|
+
# ident. titulo no banco 20
|
86
|
+
"#{conta_corrente.rjust(12, '0')}#{digito_conta} #{identificador_titulo(pagamento.nosso_numero)}"
|
87
|
+
end
|
88
|
+
|
89
|
+
# Retorna o nosso numero mais o digito verificador
|
90
|
+
#
|
91
|
+
# @return [String]
|
92
|
+
#
|
93
|
+
def formata_nosso_numero(nosso_numero)
|
94
|
+
quantidade = case convenio.to_s.size
|
95
|
+
# convenio de 4 posicoes com nosso numero de 7
|
96
|
+
when 4 then 7
|
97
|
+
# convenio de 6 posicoes com nosso numero de 5
|
98
|
+
when 6 then 5
|
99
|
+
# convenio de 7 posicoes com nosso numero de 10
|
100
|
+
when 7 then 10
|
101
|
+
else
|
102
|
+
fail Brcobranca::NaoImplementado.new('Tipo de convênio não implementado.')
|
103
|
+
end
|
104
|
+
nosso_numero = nosso_numero.to_s.rjust(quantidade, '0')
|
105
|
+
|
106
|
+
# calcula o digito do nosso numero (menos para quando nosso numero tiver 10 posicoes)
|
107
|
+
digito = "#{convenio}#{nosso_numero}".modulo11(mapeamento: { 10 => 'X' }) unless quantidade == 10
|
108
|
+
"#{nosso_numero}#{digito}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def identificador_titulo(nosso_numero)
|
112
|
+
"#{convenio}#{formata_nosso_numero(nosso_numero)}".ljust(20, ' ')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|