br_boleto 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/Gemfile.lock +3 -3
- data/README.markdown +196 -11
- data/Rakefile +5 -0
- data/br_boleto.gemspec +1 -1
- data/lib/br_boleto.rb +30 -12
- data/lib/br_boleto/{core/boleto.rb → boleto/base.rb} +83 -5
- data/lib/br_boleto/boleto/sicoob.rb +211 -0
- data/lib/br_boleto/calculos/modulo11_fator3197.rb +5 -5
- data/lib/br_boleto/helper/cpf_cnpj.rb +60 -0
- data/lib/br_boleto/helper/number.rb +15 -0
- data/lib/br_boleto/remessa/base.rb +89 -0
- data/lib/br_boleto/remessa/cnab240/base.rb +328 -0
- data/lib/br_boleto/remessa/cnab240/helper/header_arquivo.rb +186 -0
- data/lib/br_boleto/remessa/cnab240/helper/header_lote.rb +180 -0
- data/lib/br_boleto/remessa/cnab240/helper/segmento_p.rb +349 -0
- data/lib/br_boleto/remessa/cnab240/helper/segmento_q.rb +206 -0
- data/lib/br_boleto/remessa/cnab240/helper/segmento_r.rb +261 -0
- data/lib/br_boleto/remessa/cnab240/helper/segmento_s.rb +193 -0
- data/lib/br_boleto/remessa/cnab240/helper/trailer_arquivo.rb +88 -0
- data/lib/br_boleto/remessa/cnab240/helper/trailer_lote.rb +75 -0
- data/lib/br_boleto/remessa/cnab240/sicoob.rb +246 -0
- data/lib/br_boleto/remessa/lote.rb +52 -0
- data/lib/br_boleto/remessa/pagamento.rb +238 -0
- data/lib/br_boleto/string_methods.rb +21 -0
- data/lib/br_boleto/version.rb +2 -2
- data/test/br_boleto/{core/boleto_test.rb → boleto/base_test.rb} +107 -11
- data/test/br_boleto/{core → boleto}/sicoob_test.rb +60 -2
- data/test/br_boleto/remessa/base_test.rb +80 -0
- data/test/br_boleto/remessa/cnab240/base_test.rb +405 -0
- data/test/br_boleto/remessa/cnab240/helper/header_arquivo_test.rb +208 -0
- data/test/br_boleto/remessa/cnab240/helper/header_lote_test.rb +200 -0
- data/test/br_boleto/remessa/cnab240/helper/segmento_p_test.rb +390 -0
- data/test/br_boleto/remessa/cnab240/helper/segmento_q_test.rb +223 -0
- data/test/br_boleto/remessa/cnab240/helper/segmento_r_test.rb +260 -0
- data/test/br_boleto/remessa/cnab240/helper/segmento_s_test.rb +217 -0
- data/test/br_boleto/remessa/cnab240/helper/trailer_arquivo_test.rb +82 -0
- data/test/br_boleto/remessa/cnab240/helper/trailer_lote_test.rb +67 -0
- data/test/br_boleto/remessa/cnab240/sicoob_test.rb +347 -0
- data/test/br_boleto/remessa/lote_test.rb +49 -0
- data/test/br_boleto/remessa/pagamento_test.rb +339 -0
- data/test/factories/{boleto.rb → boleto/base.rb} +1 -1
- data/test/factories/{boleto_sicoob.rb → boleto/boleto_sicoob.rb} +1 -1
- data/test/factories/remessa/base.rb +13 -0
- data/test/factories/remessa/cnab240/base.rb +18 -0
- data/test/factories/remessa/cnab240/sicoob.rb +18 -0
- data/test/factories/remessa/lote.rb +7 -0
- data/test/factories/remessa/pagamento.rb +16 -0
- data/test/inheritance/boleto_test.rb +1 -1
- data/test/inheritance/sicoob_test.rb +1 -1
- metadata +65 -13
- data/lib/br_boleto/core/sicoob.rb +0 -169
@@ -0,0 +1,211 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module BrBoleto
|
3
|
+
module Boleto
|
4
|
+
# Implementação de emissão de boleto bancário pelo Banco Sicoob.
|
5
|
+
#
|
6
|
+
# === Documentação Implementada
|
7
|
+
#
|
8
|
+
# A documentação na qual essa implementação foi baseada está localizada na pasta
|
9
|
+
# 'documentacoes_dos_boletos/sicoob' dentro dessa biblioteca.
|
10
|
+
#
|
11
|
+
class Sicoob < Base
|
12
|
+
# === Carteira/Modalidade:
|
13
|
+
#
|
14
|
+
# '1/01' - Simples com registro
|
15
|
+
# '1/02' - Simples sem registro
|
16
|
+
# '3/03' - Garantida Caucionada
|
17
|
+
#
|
18
|
+
attr_accessor :modalidade_cobranca
|
19
|
+
|
20
|
+
def modalidade_cobranca
|
21
|
+
if @modalidade_cobranca.present?
|
22
|
+
@modalidade_cobranca.to_s.rjust(2, '0')
|
23
|
+
else
|
24
|
+
'01'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#Modalidades de cobranças válidas conforme a documentação
|
29
|
+
def self.modalidade_cobranca_validas
|
30
|
+
%{'01' '02' '03'}
|
31
|
+
end
|
32
|
+
|
33
|
+
def deve_validar_modalidade_cobranca?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Quantidade de parcelas que o boleto possui
|
38
|
+
# Liberando a possibilidade de edição
|
39
|
+
attr_accessor :parcelas
|
40
|
+
def parcelas
|
41
|
+
if @parcelas.present?
|
42
|
+
@parcelas.to_s.rjust(3, '0')
|
43
|
+
else
|
44
|
+
'001'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
# Tamanho máximo de uma agência no Banco Sicoob.
|
50
|
+
# <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
|
51
|
+
#
|
52
|
+
# @return [Fixnum] 4
|
53
|
+
#
|
54
|
+
def self.tamanho_maximo_agencia
|
55
|
+
4
|
56
|
+
end
|
57
|
+
|
58
|
+
# Tamanho máximo do codigo cedente no Banco Sicoob.
|
59
|
+
# <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
|
60
|
+
#
|
61
|
+
# @return [Fixnum] 7
|
62
|
+
#
|
63
|
+
def self.tamanho_maximo_codigo_cedente
|
64
|
+
7
|
65
|
+
end
|
66
|
+
|
67
|
+
# Tamanho máximo do numero do documento no Boleto.
|
68
|
+
# <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
|
69
|
+
#
|
70
|
+
# @return [Fixnum] 6
|
71
|
+
#
|
72
|
+
def self.tamanho_maximo_numero_documento
|
73
|
+
7
|
74
|
+
end
|
75
|
+
|
76
|
+
# <b>Carteiras suportadas.</b>
|
77
|
+
#
|
78
|
+
# <b>Método criado para validar se a carteira informada é suportada.</b>
|
79
|
+
#
|
80
|
+
# @return [Array]
|
81
|
+
#
|
82
|
+
def self.carteiras_suportadas
|
83
|
+
%w[1 3]
|
84
|
+
end
|
85
|
+
|
86
|
+
# Validações para os campos abaixo:
|
87
|
+
#
|
88
|
+
# * Agencia
|
89
|
+
# * Codigo Cedente
|
90
|
+
# * Número do documento
|
91
|
+
#
|
92
|
+
# Se você quiser sobrescrever os metodos, <b>ficará a sua responsabilidade.</b>
|
93
|
+
# Basta você sobrescrever os métodos de validação:
|
94
|
+
#
|
95
|
+
# class Sicoob < BrBoleto::Core::Sicoob
|
96
|
+
# def self.tamanho_maximo_agencia
|
97
|
+
# 6
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# def self.tamanho_maximo_codigo_cedente
|
101
|
+
# 9
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# def self.tamanho_maximo_numero_documento
|
105
|
+
# 10
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# Obs.: Mudar as regras de validação podem influenciar na emissão do boleto em si.
|
110
|
+
# Talvez você precise analisar o efeito no #codigo_de_barras e na #linha_digitável (ambos podem ser
|
111
|
+
# sobreescritos também).
|
112
|
+
#
|
113
|
+
validates :agencia, :codigo_cedente, presence: true
|
114
|
+
|
115
|
+
validates :agencia, length: { maximum: tamanho_maximo_agencia }, if: :deve_validar_agencia?
|
116
|
+
validates :codigo_cedente, length: { maximum: tamanho_maximo_codigo_cedente }, if: :deve_validar_codigo_cedente?
|
117
|
+
validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
|
118
|
+
|
119
|
+
validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
|
120
|
+
validates :modalidade_cobranca, inclusion: { in: ->(object) { object.class.modalidade_cobranca_validas } }, if: :deve_validar_modalidade_cobranca?
|
121
|
+
|
122
|
+
# @return [String] 4 caracteres
|
123
|
+
#
|
124
|
+
def agencia
|
125
|
+
@agencia.to_s.rjust(4, '0') if @agencia.present?
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [String] 7 caracteres
|
129
|
+
# O Código do cedente é o mesmo que o codigo do beneficiário
|
130
|
+
def codigo_cedente
|
131
|
+
@codigo_cedente.to_s.rjust(7, '0') if @codigo_cedente.present?
|
132
|
+
end
|
133
|
+
|
134
|
+
# @return [String] 6 caracteres
|
135
|
+
#
|
136
|
+
def numero_documento
|
137
|
+
@numero_documento.to_s.rjust(7, '0') if @numero_documento.present?
|
138
|
+
end
|
139
|
+
|
140
|
+
# @return [String] Código do Banco descrito na documentação.
|
141
|
+
#
|
142
|
+
def codigo_banco
|
143
|
+
'756'
|
144
|
+
end
|
145
|
+
|
146
|
+
# @return [String] Dígito do código do banco descrito na documentação.
|
147
|
+
#
|
148
|
+
def digito_codigo_banco
|
149
|
+
'0'
|
150
|
+
end
|
151
|
+
|
152
|
+
# Campo Agência / Código do Cedente
|
153
|
+
#
|
154
|
+
# @return [String]
|
155
|
+
#
|
156
|
+
def agencia_codigo_cedente
|
157
|
+
"#{agencia} / #{codigo_cedente}"
|
158
|
+
end
|
159
|
+
|
160
|
+
# O nosso número descrino na documentação é formado pelo numero do documento mais o digito
|
161
|
+
# verificador no nosso_numero, que é um cálculo descrito na documentação.
|
162
|
+
#
|
163
|
+
# @return [String]
|
164
|
+
#
|
165
|
+
def nosso_numero
|
166
|
+
"#{numero_documento}-#{digito_verificador_nosso_numero}"
|
167
|
+
end
|
168
|
+
|
169
|
+
# Tipo de cobrança
|
170
|
+
# Ex: :com_registro, :sem_registro, :garantia_caucionada
|
171
|
+
#
|
172
|
+
# Obs: O VALOR DESSE METODO NÃO INFLUÊNCIA NA GERAÇÃO DO BOLETO
|
173
|
+
# É APENAS PARA QUESTÃO DE INFORMAÇÃO CASO PRECISE PARA OUTRAS COISAS.
|
174
|
+
#
|
175
|
+
def tipo_cobranca
|
176
|
+
case "#{modalidade_cobranca}".rjust(2, "0")
|
177
|
+
when '01'
|
178
|
+
:com_registro
|
179
|
+
when '02'
|
180
|
+
:sem_registro
|
181
|
+
when '03'
|
182
|
+
:garantia_caucionada
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
# === Código de barras do banco
|
188
|
+
#
|
189
|
+
# ___________________________________________________________
|
190
|
+
# | Posição | Tamanho | Descrição |
|
191
|
+
# |---------|---------|---------------------------------------|
|
192
|
+
# | 20 - 20 | 01 | Código da carteira |
|
193
|
+
# | 21 - 24 | 04 | Código da agência |
|
194
|
+
# | 25 - 26 | 02 | Código da modalidade de cobrança (01) |
|
195
|
+
# | 27 - 33 | 07 | Código do Cedente |
|
196
|
+
# | 34 - 41 | 08 | Nosso Número do título |
|
197
|
+
# | 42 - 44 | 03 | Número da Parcela do Título (001) |
|
198
|
+
# |___________________________________________________________|
|
199
|
+
#
|
200
|
+
# @return [String]
|
201
|
+
#
|
202
|
+
def codigo_de_barras_do_banco
|
203
|
+
"#{carteira}#{agencia}#{modalidade_cobranca}#{codigo_cedente}#{nosso_numero.gsub('-','')}#{parcelas}"
|
204
|
+
end
|
205
|
+
|
206
|
+
def digito_verificador_nosso_numero
|
207
|
+
BrBoleto::Calculos::Modulo11Fator3197.new("#{agencia}#{codigo_cedente.rjust(10, '0')}#{numero_documento}")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -49,19 +49,19 @@ module BrBoleto
|
|
49
49
|
#
|
50
50
|
# @example
|
51
51
|
#
|
52
|
-
# BrBoleto::Calculos::
|
52
|
+
# BrBoleto::Calculos::Modulo11Fator3197.new('20')
|
53
53
|
# # => '5'
|
54
54
|
#
|
55
|
-
# BrBoleto::Calculos::
|
55
|
+
# BrBoleto::Calculos::Modulo11Fator3197.new('64')
|
56
56
|
# # => '7'
|
57
57
|
#
|
58
|
-
# BrBoleto::Calculos::
|
58
|
+
# BrBoleto::Calculos::Modulo11Fator3197.new('26')
|
59
59
|
# # => '4'
|
60
60
|
#
|
61
|
-
# BrBoleto::Calculos::
|
61
|
+
# BrBoleto::Calculos::Modulo11Fator3197.new('6')
|
62
62
|
# # => 'P'
|
63
63
|
#
|
64
|
-
# BrBoleto::Calculos::
|
64
|
+
# BrBoleto::Calculos::Modulo11Fator3197.new('14')
|
65
65
|
# # => '0'
|
66
66
|
#
|
67
67
|
class Modulo11Fator3197 < Modulo11
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module BrBoleto
|
2
|
+
module Helper
|
3
|
+
class CpfCnpj
|
4
|
+
|
5
|
+
def initialize(cpf_cnpj)
|
6
|
+
@cpf_cnpj = ajusta_cpf_cnpj_com_zero("#{cpf_cnpj}")
|
7
|
+
end
|
8
|
+
|
9
|
+
def cpf?
|
10
|
+
cpf_ou_cnpj? == :cpf
|
11
|
+
end
|
12
|
+
|
13
|
+
def cnpj?
|
14
|
+
cpf_ou_cnpj? == :cnpj
|
15
|
+
end
|
16
|
+
|
17
|
+
def cpf_ou_cnpj?
|
18
|
+
@cpf_cnpj.size > 11 ? :cnpj : :cpf
|
19
|
+
end
|
20
|
+
|
21
|
+
def tipo_documento(tamanho = 2)
|
22
|
+
return '0' if sem_formatacao.blank?
|
23
|
+
sem_formatacao.size < 14 ? '1'.rjust(tamanho, '0') : '2'.rjust(tamanho, '0')
|
24
|
+
end
|
25
|
+
|
26
|
+
def sem_formatacao
|
27
|
+
@cpf_cnpj.gsub(/[\.]|[\-]|[\/]/,'')
|
28
|
+
end
|
29
|
+
|
30
|
+
def com_formatacao
|
31
|
+
cnpj? ? formata_cnpj : formata_cpf
|
32
|
+
end
|
33
|
+
|
34
|
+
def formatado_com_label
|
35
|
+
cnpj? ? "CNPJ #{formata_cnpj}" : "CPF #{formata_cpf}"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def ajusta_cpf_cnpj_com_zero(value)
|
41
|
+
return "" if value.blank?
|
42
|
+
if value.to_s.size <= 11
|
43
|
+
value.to_s.rjust(11, '0')
|
44
|
+
else
|
45
|
+
value.to_s.rjust(14, '0')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def formata_cpf
|
50
|
+
@cpf_cnpj.gsub!(/[\.]|[\-]|[\/]/,'')
|
51
|
+
"#{@cpf_cnpj[0..2]}.#{@cpf_cnpj[3..5]}.#{@cpf_cnpj[6..8]}-#{@cpf_cnpj[9..10]}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def formata_cnpj
|
55
|
+
@cpf_cnpj.gsub!(/[\.]|[\-]|[\/]/,'')
|
56
|
+
"#{@cpf_cnpj[0..1]}.#{@cpf_cnpj[2..4]}.#{@cpf_cnpj[5..7]}/#{@cpf_cnpj[8..11]}-#{@cpf_cnpj[12..13]}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module BrBoleto
|
2
|
+
module Helper
|
3
|
+
class Number
|
4
|
+
def initialize(numero)
|
5
|
+
@numero = numero
|
6
|
+
end
|
7
|
+
|
8
|
+
def formata_valor_monetario(size=13)
|
9
|
+
return ''.rjust(size, '0') if @numero.blank?
|
10
|
+
sprintf('%.2f', @numero).delete('.').rjust(size, '0')
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module BrBoleto
|
2
|
+
module Remessa
|
3
|
+
class Base
|
4
|
+
# Seguindo a interface do Active Model para:
|
5
|
+
# * Validações;
|
6
|
+
# * Internacionalização;
|
7
|
+
# * Nomes das classes para serem manipuladas;
|
8
|
+
#
|
9
|
+
include ActiveModel::Model
|
10
|
+
|
11
|
+
# variavel que terá os lotes no qual será gerado o arquivo de remessa
|
12
|
+
# um lote deve conter no minimo 1 pagamento
|
13
|
+
# Pode haver 1 ou vários lotes para o mesmo arquivo
|
14
|
+
attr_accessor :lotes
|
15
|
+
|
16
|
+
def self.class_for_lote
|
17
|
+
BrBoleto::Remessa::Lote
|
18
|
+
end
|
19
|
+
|
20
|
+
# Razão social da empresa
|
21
|
+
attr_accessor :nome_empresa
|
22
|
+
|
23
|
+
# agencia (sem digito verificador)
|
24
|
+
attr_accessor :agencia
|
25
|
+
|
26
|
+
# numero da conta corrente
|
27
|
+
attr_accessor :conta_corrente
|
28
|
+
|
29
|
+
# digito verificador da conta corrente
|
30
|
+
attr_accessor :digito_conta
|
31
|
+
|
32
|
+
# carteira do cedente
|
33
|
+
attr_accessor :carteira
|
34
|
+
|
35
|
+
# sequencial remessa (num. sequencial que nao pode ser repetido nem zerado)
|
36
|
+
attr_accessor :sequencial_remessa
|
37
|
+
|
38
|
+
# aceite (A = ACEITO/N = NAO ACEITO)
|
39
|
+
attr_accessor :aceite
|
40
|
+
|
41
|
+
def initialize(attributes = {})
|
42
|
+
self.lotes = [] # Para poder utilizar o << para adicionar lote
|
43
|
+
attributes = default_values.merge!(attributes)
|
44
|
+
assign_attributes(attributes)
|
45
|
+
yield self if block_given?
|
46
|
+
end
|
47
|
+
|
48
|
+
def assign_attributes(attributes)
|
49
|
+
attributes ||= {}
|
50
|
+
attributes.each do |name, value|
|
51
|
+
send("#{name}=", value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
validates :nome_empresa, presence: true
|
56
|
+
validates :aceite, inclusion: { in: %w(A a n N), message: "valor deve ser A(aceito) ou N(não ceito)" }
|
57
|
+
|
58
|
+
validates_each :lotes do |record, attr, value|
|
59
|
+
record.errors.add(attr, 'não pode estar vazio.') if value.empty?
|
60
|
+
value.each do |lote|
|
61
|
+
if lote.is_a? record.class.class_for_lote
|
62
|
+
if lote.invalid?
|
63
|
+
lote.errors.full_messages.each { |msg| record.errors.add(attr, msg) }
|
64
|
+
end
|
65
|
+
else
|
66
|
+
record.errors.add(attr, 'cada item deve ser um objeto Lote.')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# O atributo lotes sempre irá retornar umm Array
|
72
|
+
def lotes
|
73
|
+
@lotes = [@lotes].flatten
|
74
|
+
end
|
75
|
+
|
76
|
+
def default_values
|
77
|
+
{aceite: "N"}
|
78
|
+
end
|
79
|
+
|
80
|
+
def persisted?
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
def nome_empresa_formatada
|
85
|
+
"#{nome_empresa}".adjust_size_to(30)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'br_boleto/remessa/cnab240/helper/header_arquivo'
|
3
|
+
require 'br_boleto/remessa/cnab240/helper/header_lote'
|
4
|
+
require 'br_boleto/remessa/cnab240/helper/segmento_p'
|
5
|
+
require 'br_boleto/remessa/cnab240/helper/segmento_q'
|
6
|
+
require 'br_boleto/remessa/cnab240/helper/segmento_r'
|
7
|
+
require 'br_boleto/remessa/cnab240/helper/segmento_s'
|
8
|
+
require 'br_boleto/remessa/cnab240/helper/trailer_lote'
|
9
|
+
require 'br_boleto/remessa/cnab240/helper/trailer_arquivo'
|
10
|
+
|
11
|
+
module BrBoleto
|
12
|
+
module Remessa
|
13
|
+
module Cnab240
|
14
|
+
class Base < BrBoleto::Remessa::Base
|
15
|
+
|
16
|
+
# Utilizado para montar o header do arquivo
|
17
|
+
include BrBoleto::Remessa::Cnab240::Helper::HeaderArquivo
|
18
|
+
|
19
|
+
# Utilizado para montar o header do lote
|
20
|
+
include BrBoleto::Remessa::Cnab240::Helper::HeaderLote
|
21
|
+
|
22
|
+
# Utilizado para montar o segmento P
|
23
|
+
include BrBoleto::Remessa::Cnab240::Helper::SegmentoP
|
24
|
+
|
25
|
+
# Utilizado para montar o segmento Q
|
26
|
+
include BrBoleto::Remessa::Cnab240::Helper::SegmentoQ
|
27
|
+
|
28
|
+
# Utilizado para montar o segmento R
|
29
|
+
include BrBoleto::Remessa::Cnab240::Helper::SegmentoR
|
30
|
+
|
31
|
+
# Utilizado para montar o segmento S
|
32
|
+
include BrBoleto::Remessa::Cnab240::Helper::SegmentoS
|
33
|
+
|
34
|
+
# Utilizado para montar o trailer do lote
|
35
|
+
include BrBoleto::Remessa::Cnab240::Helper::TrailerLote
|
36
|
+
|
37
|
+
# Utilizado para montar o trailer do arquivo
|
38
|
+
include BrBoleto::Remessa::Cnab240::Helper::TrailerArquivo
|
39
|
+
|
40
|
+
# documento do cedente (CPF/CNPJ)
|
41
|
+
attr_accessor :documento_cedente
|
42
|
+
|
43
|
+
# convenio do cedente
|
44
|
+
attr_accessor :convenio
|
45
|
+
|
46
|
+
# mensagem 1
|
47
|
+
attr_accessor :mensagem_1
|
48
|
+
|
49
|
+
# mensagem 2
|
50
|
+
attr_accessor :mensagem_2
|
51
|
+
|
52
|
+
# Data e hora da geração do arquivo
|
53
|
+
attr_accessor :data_hora_arquivo
|
54
|
+
|
55
|
+
# codigo da carteira
|
56
|
+
# opcoes:
|
57
|
+
# 1 - cobranca simples
|
58
|
+
# 2 - cobranca caucionada
|
59
|
+
# 3 - cobranca descontada
|
60
|
+
# 7 – modalidade Simples quando carteira 17 (apenas Banco do Brasil)
|
61
|
+
attr_accessor :codigo_carteira
|
62
|
+
|
63
|
+
# forma de cadastramento dos titulos (campo nao tratado pelo Banco do Brasil)
|
64
|
+
# opcoes:
|
65
|
+
# 1 - com cadastramento (cobrança registrada)
|
66
|
+
# 2 - sem cadastramento (cobrança sem registro)
|
67
|
+
attr_accessor :forma_cadastramento
|
68
|
+
|
69
|
+
# identificacao da emissao do boleto (verificar opcoes nas classes referentes aos bancos)
|
70
|
+
attr_accessor :emissao_boleto
|
71
|
+
|
72
|
+
# identificacao da distribuicao do boleto (verificar opcoes nas classes referentes aos bancos)
|
73
|
+
attr_accessor :distribuicao_boleto
|
74
|
+
|
75
|
+
# especie do titulo (verificar o padrao nas classes referentes aos bancos)
|
76
|
+
attr_accessor :especie_titulo
|
77
|
+
|
78
|
+
|
79
|
+
def self.tamanho_codigo_carteira
|
80
|
+
1
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.tamanho_forma_cadastramento
|
84
|
+
1
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.tamanho_emissao_boleto
|
88
|
+
1
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.tamanho_distribuicao_boleto
|
92
|
+
1
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.tamanho_especie_titulo
|
96
|
+
2
|
97
|
+
end
|
98
|
+
|
99
|
+
def convenio_obrigatorio?
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
validates :convenio, presence: true, if: :convenio_obrigatorio?
|
104
|
+
validates :documento_cedente, presence: true
|
105
|
+
|
106
|
+
validates :codigo_carteira, length: {is: tamanho_codigo_carteira, message: "deve ter #{tamanho_codigo_carteira} dígito."}
|
107
|
+
validates :forma_cadastramento, length: {is: tamanho_forma_cadastramento, message: "deve ter #{tamanho_forma_cadastramento} dígito."}
|
108
|
+
validates :emissao_boleto, length: {is: tamanho_emissao_boleto, message: "deve ter #{tamanho_emissao_boleto} dígito."}
|
109
|
+
validates :distribuicao_boleto, length: {is: tamanho_distribuicao_boleto, message: "deve ter #{tamanho_distribuicao_boleto} dígito."}
|
110
|
+
validates :especie_titulo, length: {is: tamanho_especie_titulo, message: "deve ter #{tamanho_especie_titulo} dígitos."}
|
111
|
+
|
112
|
+
def default_values
|
113
|
+
super.merge({
|
114
|
+
codigo_carteira: '1',
|
115
|
+
forma_cadastramento: '1'
|
116
|
+
})
|
117
|
+
end
|
118
|
+
|
119
|
+
# Tipo de inscricao do cedente
|
120
|
+
# (pessoa fisica ou juridica)
|
121
|
+
#
|
122
|
+
# @return [String]
|
123
|
+
#
|
124
|
+
def tipo_inscricao
|
125
|
+
# Retorna 1 se CPF e 2 se CNPJ
|
126
|
+
BrBoleto::Helper::CpfCnpj.new(documento_cedente).tipo_documento(1)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Data de geracao do arquivo
|
130
|
+
#
|
131
|
+
# @return [String]
|
132
|
+
#
|
133
|
+
def data_geracao
|
134
|
+
data_hora_arquivo.to_date.strftime('%d%m%Y')
|
135
|
+
end
|
136
|
+
|
137
|
+
# Hora de geracao do arquivo
|
138
|
+
#
|
139
|
+
# @return [String]
|
140
|
+
#
|
141
|
+
def hora_geracao
|
142
|
+
data_hora_arquivo.strftime('%H%M%S')
|
143
|
+
end
|
144
|
+
|
145
|
+
def data_hora_arquivo
|
146
|
+
@data_hora_arquivo.to_time
|
147
|
+
rescue
|
148
|
+
return Time.now
|
149
|
+
end
|
150
|
+
|
151
|
+
# Monta um lote para o arquivo
|
152
|
+
#
|
153
|
+
# @param lote [BrBoleto::Remessa::Lote]
|
154
|
+
# objeto contendo os detalhes do boleto (valor, )
|
155
|
+
#
|
156
|
+
# @param nro_lote [Integer]
|
157
|
+
# numero do lote no arquivo
|
158
|
+
#
|
159
|
+
# @return [Array]
|
160
|
+
#
|
161
|
+
def monta_lote(lote, nro_lote)
|
162
|
+
return if lote.invalid?
|
163
|
+
|
164
|
+
|
165
|
+
# Metodo 'monta_header_lote' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::HeaderLote
|
166
|
+
itens_lote = [monta_header_lote(lote, nro_lote)]
|
167
|
+
|
168
|
+
#Nº Sequencial de Registros no Lote:
|
169
|
+
sequencial_do_lote = 0
|
170
|
+
|
171
|
+
lote.pagamentos.each do |pagamento|
|
172
|
+
# Metodo 'monta_segmento_p' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::SegmentoP
|
173
|
+
sequencial_do_lote += 1
|
174
|
+
itens_lote << monta_segmento_p(pagamento, nro_lote, sequencial_do_lote)
|
175
|
+
|
176
|
+
# Metodo 'monta_segmento_q' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::SegmentoQ
|
177
|
+
sequencial_do_lote += 1
|
178
|
+
itens_lote << monta_segmento_q(pagamento, nro_lote, sequencial_do_lote)
|
179
|
+
|
180
|
+
# Metodo 'monta_segmento_r' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::SegmentoR
|
181
|
+
sequencial_do_lote += 1
|
182
|
+
itens_lote << monta_segmento_r(pagamento, nro_lote, sequencial_do_lote)
|
183
|
+
|
184
|
+
# Metodo 'monta_segmento_s' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::SegmentoS
|
185
|
+
sequencial_do_lote += 1
|
186
|
+
itens_lote << monta_segmento_s(pagamento, nro_lote, sequencial_do_lote)
|
187
|
+
end
|
188
|
+
|
189
|
+
# total_de_registros_do_lote é a quantidade de registros(linhas) que constam em um lote
|
190
|
+
# Total de complementos do lote + o HEADER_LOTE + TRAILER_LOTE
|
191
|
+
# sequencial_do_lote + 1 + 1
|
192
|
+
total_de_registros_do_lote = sequencial_do_lote + 2
|
193
|
+
|
194
|
+
# Metodo 'monta_trailer_lote' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::TrailerLote
|
195
|
+
itens_lote << monta_trailer_lote(lote, nro_lote, total_de_registros_do_lote)
|
196
|
+
|
197
|
+
itens_lote
|
198
|
+
end
|
199
|
+
|
200
|
+
# Gera os dados para o arquivo remessa
|
201
|
+
#
|
202
|
+
# @return [String]
|
203
|
+
#
|
204
|
+
def dados_do_arquivo
|
205
|
+
return if self.invalid?
|
206
|
+
|
207
|
+
# contador dos registros do lote
|
208
|
+
contador = 1
|
209
|
+
|
210
|
+
# Metodo 'monta_header_arquivo' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::HeaderArquivo
|
211
|
+
arquivo = [monta_header_arquivo]
|
212
|
+
contador += 1
|
213
|
+
|
214
|
+
lotes.each_with_index do |lote, index|
|
215
|
+
novo_lote = monta_lote(lote, (index + 1))
|
216
|
+
arquivo.push novo_lote
|
217
|
+
novo_lote.each { |_lote| contador += 1 }
|
218
|
+
end
|
219
|
+
|
220
|
+
# Metodo 'monta_trailer_arquivo' implementado no module -> BrBoleto::Remessa::Cnab240::Helper::TrailerArquivo
|
221
|
+
arquivo << monta_trailer_arquivo(lotes.count, contador)
|
222
|
+
|
223
|
+
retorno = arquivo.join("\n")
|
224
|
+
ActiveSupport::Inflector.transliterate(retorno).upcase
|
225
|
+
end
|
226
|
+
|
227
|
+
# Número do Documento de Cobrança
|
228
|
+
# Cada banco tem sua maneira de identificar esse número, mas o padrão é o
|
229
|
+
# Valor que se encontra no nosso numero
|
230
|
+
# 15 posições
|
231
|
+
#
|
232
|
+
def segmento_p_numero_do_documento(pagamento)
|
233
|
+
pagamento.nosso_numero.to_s.rjust(15, '0')
|
234
|
+
end
|
235
|
+
|
236
|
+
# Complemento do registro
|
237
|
+
#
|
238
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
239
|
+
#
|
240
|
+
def complemento_header
|
241
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
242
|
+
end
|
243
|
+
|
244
|
+
# Numero da versao do layout do arquivo
|
245
|
+
#
|
246
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
247
|
+
#
|
248
|
+
def versao_layout_arquivo
|
249
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
250
|
+
end
|
251
|
+
|
252
|
+
# Numero da versao do layout do lote
|
253
|
+
#
|
254
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
255
|
+
#
|
256
|
+
def versao_layout_lote
|
257
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
258
|
+
end
|
259
|
+
|
260
|
+
# Informacoes do convenio para o lote
|
261
|
+
#
|
262
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
263
|
+
#
|
264
|
+
def convenio_lote(lote)
|
265
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
266
|
+
end
|
267
|
+
|
268
|
+
# Nome do banco
|
269
|
+
#
|
270
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
271
|
+
#
|
272
|
+
def nome_banco
|
273
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
274
|
+
end
|
275
|
+
|
276
|
+
# Codigo do banco
|
277
|
+
#
|
278
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
279
|
+
#
|
280
|
+
def codigo_banco
|
281
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
282
|
+
end
|
283
|
+
|
284
|
+
# Informacoes da conta do cedente
|
285
|
+
#
|
286
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
287
|
+
#
|
288
|
+
def informacoes_da_conta
|
289
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
290
|
+
end
|
291
|
+
|
292
|
+
# Codigo do convenio
|
293
|
+
#
|
294
|
+
# Este metodo deve ser sobrescrevido na classe do banco
|
295
|
+
#
|
296
|
+
def codigo_convenio
|
297
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
298
|
+
end
|
299
|
+
|
300
|
+
# Digito verificado da agência
|
301
|
+
# Normalmente calculado pelo Modulo 11
|
302
|
+
# Deve ser sobrescrito na classe do banco
|
303
|
+
#
|
304
|
+
def digito_agencia
|
305
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
306
|
+
end
|
307
|
+
|
308
|
+
# Complemento do segmento P
|
309
|
+
# Recebe um objeto da classe BrBoleto::Remessa::Pagamento
|
310
|
+
# Composto por 34 digitos
|
311
|
+
# Cada banco tem seu padrão
|
312
|
+
# Deve ser sobrescrito na classe do banco
|
313
|
+
#
|
314
|
+
def complemento_p(pagamento)
|
315
|
+
raise NotImplementedError.new('Sobreescreva este método na classe referente ao banco que você esta criando')
|
316
|
+
end
|
317
|
+
|
318
|
+
# Complemento final do trailer do lote
|
319
|
+
# Por padrão coloco 217 caracateres em branco pois é na maioria dos bancos
|
320
|
+
# Mas para alguns bancos isso pode mudar
|
321
|
+
#
|
322
|
+
def complemento_trailer_lote(lote, nr_lote)
|
323
|
+
''.rjust(217, ' ')
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|