brcobranca 2.0.6 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.document +5 -0
  2. data/.gitignore +30 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.lock +48 -0
  5. data/History.txt +13 -1
  6. data/LICENSE +20 -0
  7. data/README.rdoc +12 -5
  8. data/Rakefile +33 -37
  9. data/VERSION +1 -0
  10. data/brcobranca.gemspec +26 -35
  11. data/lib/brcobranca/arquivos/logos/{bb.jpg → bancobrasil.jpg} +0 -0
  12. data/lib/brcobranca/arquivos/logos/banespa.jpg +0 -0
  13. data/lib/brcobranca/arquivos/logos/caixa.jpg +0 -0
  14. data/lib/brcobranca/boleto/banco_brasil.rb +150 -77
  15. data/lib/brcobranca/boleto/base.rb +146 -75
  16. data/lib/brcobranca/boleto/bradesco.rb +69 -0
  17. data/lib/brcobranca/boleto/caixa.rb +100 -0
  18. data/lib/brcobranca/boleto/hsbc.rb +95 -0
  19. data/lib/brcobranca/boleto/itau.rb +133 -0
  20. data/lib/brcobranca/boleto/real.rb +74 -0
  21. data/lib/brcobranca/boleto/template/base.rb +13 -0
  22. data/lib/brcobranca/boleto/template/rghost.rb +136 -62
  23. data/lib/brcobranca/boleto/unibanco.rb +115 -0
  24. data/lib/brcobranca/calculo.rb +132 -0
  25. data/lib/brcobranca/calculo_data.rb +42 -0
  26. data/lib/brcobranca/currency.rb +3 -4
  27. data/lib/brcobranca/formatacao.rb +102 -0
  28. data/lib/brcobranca/limpeza.rb +19 -0
  29. data/lib/brcobranca/retorno/base.rb +1 -2
  30. data/lib/brcobranca/retorno/retorno_cbr643.rb +42 -40
  31. data/lib/brcobranca/version.rb +3 -0
  32. data/lib/brcobranca.rb +93 -16
  33. data/spec/brcobranca/banco_bradesco_spec.rb +63 -50
  34. data/spec/brcobranca/banco_brasil_spec.rb +102 -136
  35. data/spec/brcobranca/banco_caixa_spec.rb +166 -0
  36. data/spec/brcobranca/banco_hsbc_spec.rb +83 -76
  37. data/spec/brcobranca/banco_real_spec.rb +54 -37
  38. data/spec/brcobranca/banco_unibanco_spec.rb +69 -52
  39. data/spec/brcobranca/base_spec.rb +24 -79
  40. data/spec/brcobranca/boletos_em_lote_spec.rb +46 -0
  41. data/spec/brcobranca/core_ext_spec.rb +24 -114
  42. data/spec/brcobranca/currency_spec.rb +1 -0
  43. data/spec/brcobranca/{banco_itau_spec.rb → itau_spec.rb} +112 -67
  44. data/spec/brcobranca/retorno_cbr643_spec.rb +13 -12
  45. data/spec/brcobranca/rghost_spec.rb +8 -7
  46. data/spec/brcobranca_spec.rb +16 -6
  47. data/spec/spec_helper.rb +11 -8
  48. metadata +107 -58
  49. data/Manifest.txt +0 -51
  50. data/PostInstall.txt +0 -4
  51. data/lib/brcobranca/boleto/banco_banespa.rb +0 -85
  52. data/lib/brcobranca/boleto/banco_bradesco.rb +0 -44
  53. data/lib/brcobranca/boleto/banco_hsbc.rb +0 -77
  54. data/lib/brcobranca/boleto/banco_itau.rb +0 -115
  55. data/lib/brcobranca/boleto/banco_real.rb +0 -70
  56. data/lib/brcobranca/boleto/banco_unibanco.rb +0 -79
  57. data/lib/brcobranca/boleto/template/util.rb +0 -32
  58. data/lib/brcobranca/config.rb +0 -9
  59. data/lib/brcobranca/core_ext.rb +0 -279
  60. data/spec/brcobranca/banco_banespa_spec.rb +0 -195
  61. data/spec/brcobranca/template/rghost_spec.rb +0 -65
  62. data/spec/brcobranca/template/util_spec.rb +0 -42
  63. data/spec/rcov.opts +0 -2
  64. data/spec/spec.opts +0 -6
  65. data/tasks/rcov.rake +0 -12
  66. data/tasks/rspec.rake +0 -21
@@ -0,0 +1,74 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Brcobranca
3
+ module Boleto
4
+ class Real < Base # Banco REAL
5
+
6
+ validates_length_of :agencia, :maximum => 4, :message => "deve ser menor ou igual a 4 dígitos."
7
+ validates_length_of :conta_corrente, :maximum => 7, :message => "deve ser menor ou igual a 7 dígitos."
8
+
9
+ validates_each :numero_documento do |record, attr, value|
10
+ record.errors.add attr, 'deve ser menor ou igual a 13 dígitos.' if (value.to_s.size > 13) && (record.carteira.to_i == 57)
11
+ record.errors.add attr, 'deve ser menor ou igual a 7 dígitos.' if (value.to_s.size > 7) && (record.carteira.to_i != 57)
12
+ end
13
+
14
+ ## Nova instancia do Real
15
+ # @param (see Brcobranca::Boleto::Base#initialize)
16
+ def initialize(campos={})
17
+ campos = {:carteira => "57"}.merge!(campos)
18
+ super(campos)
19
+ end
20
+
21
+ # Codigo do banco emissor (3 dígitos sempre)
22
+ def banco
23
+ "356"
24
+ end
25
+
26
+ # Número seqüencial utilizado para identificar o boleto.
27
+ #
28
+ # NUMERO DO BANCO : COM 7 DIGITOS P/ COBRANCA REGISTRADA e ATE 13 DIGITOS P/ COBRANCA SEM REGISTRO
29
+ #
30
+ # @return [String] 7 ou 13 caracteres numéricos.
31
+ def numero_documento
32
+ quantidade = (self.carteira.to_i == 57) ? 13 : 7
33
+ @numero_documento.to_s.rjust(quantidade,'0')
34
+ end
35
+
36
+ # Nosso número para exibir no boleto.
37
+ # @return [String]
38
+ # @example
39
+ # boleto.nosso_numero_boleto #=> "4000403005-6"
40
+ def nosso_numero_boleto
41
+ "#{self.numero_documento}-#{self.nosso_numero_dv}"
42
+ end
43
+
44
+ # Número do convênio/contrato do cliente para exibir no boleto.
45
+ # @return [String]
46
+ # @example
47
+ # boleto.agencia_conta_boleto #=> "0548-7 / 0001448-6"
48
+ def agencia_conta_boleto
49
+ "#{self.agencia}-#{self.agencia_dv} / #{self.conta_corrente}-#{self.conta_corrente_dv}"
50
+ end
51
+
52
+ # Dígito verificador do nosso número.
53
+ # @return [String] 1 caracteres numéricos.
54
+ def agencia_conta_corrente_nosso_numero_dv
55
+ "#{self.numero_documento}#{self.agencia}#{self.conta_corrente}".modulo10
56
+ end
57
+
58
+ # Segunda parte do código de barras.
59
+ #
60
+ # Montagem é baseada no tipo de carteira, com registro e sem registro(57)
61
+ #
62
+ # @return [String] 25 caracteres numéricos.
63
+ def codigo_barras_segunda_parte
64
+ case self.carteira.to_i
65
+ when 57
66
+ "#{self.agencia}#{self.conta_corrente}#{self.agencia_conta_corrente_nosso_numero_dv}#{self.numero_documento}"
67
+ else
68
+ # TODO verificar com o banco, pois não consta na documentação
69
+ "000000#{self.agencia}#{self.conta_corrente}#{self.agencia_conta_corrente_nosso_numero_dv}#{self.numero_documento}"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ module Brcobranca
2
+ module Boleto
3
+ module Template
4
+ module Base
5
+ extend self
6
+
7
+ def define_template(template)
8
+ (template == :rghost) ? Brcobranca::Boleto::Template::Rghost : Brcobranca::Boleto::Template::Rghost
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+
1
3
  begin
2
4
  require 'rghost'
3
5
  rescue LoadError
@@ -19,135 +21,207 @@ module Brcobranca
19
21
  module Template
20
22
  # Templates para usar com Rghost
21
23
  module Rghost
24
+ extend self
22
25
  include RGhost unless self.include?(RGhost)
23
26
 
24
27
  # Gera o boleto em usando o formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc]
25
- # Veja mais formatos na documentação do rghost: http://wiki.github.com/shairontoledo/rghost/supported-devices-drivers-and-formats
26
- # TODO - Usar define_method para criar um metodo em tempo real to_{pdf,jpg}
27
- def to(formato=Brcobranca::Config::OPCOES[:tipo])
28
- modelo_generico(:tipo => formato)
28
+ #
29
+ # @return [Stream]
30
+ # @see http://wiki.github.com/shairontoledo/rghost/supported-devices-drivers-and-formats Veja mais formatos na documentação do rghost.
31
+ # @see Rghost#modelo_generico Recebe os mesmos parâmetros do Rghost#modelo_generico.
32
+ def to(formato, options={})
33
+ modelo_generico(self, options.merge!({:formato => formato}))
34
+ end
35
+
36
+ # Gera o boleto em usando o formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc]
37
+ #
38
+ # @return [Stream]
39
+ # @see http://wiki.github.com/shairontoledo/rghost/supported-devices-drivers-and-formats Veja mais formatos na documentação do rghost.
40
+ # @see Rghost#modelo_generico Recebe os mesmos parâmetros do Rghost#modelo_generico.
41
+ def lote(boletos, options={})
42
+ modelo_generico_multipage(boletos, options)
29
43
  end
30
44
 
31
- # Responsável por setar os valores necessários no template genérico
32
- # Retorna um stream pronto para gravaçào
45
+ # Cria o métodos dinâmicos (to_pdf, to_gif e etc) com todos os fomátos válidos.
33
46
  #
34
- # O tipo do arquivo gerado pode ser modificado incluindo a configuração a baixo dentro da sua aplicação:
35
- # Brcobranca::Config::OPCOES[:tipo] = 'pdf'
47
+ # @return [Stream]
48
+ # @see Rghost#modelo_generico Recebe os mesmos parâmetros do Rghost#modelo_generico.
49
+ # @example
50
+ # @boleto.to_pdf #=> boleto gerado no formato pdf
51
+ def method_missing(m, *args)
52
+ method = m.to_s
53
+ if method.start_with?("to_")
54
+ modelo_generico(self, (args.first || {}).merge!({:formato => method[3..-1]}))
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ # Retorna um stream pronto para gravação em arquivo.
63
+ #
64
+ # @return [Stream]
65
+ # @param [Boleto] Instância de uma classe de boleto.
66
+ # @param [Hash] options Opção para a criação do boleto.
67
+ # @option options [Symbol] :resolucao Resolução em pixels.
68
+ # @option options [Symbol] :formato Formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc]
69
+ def modelo_generico(boleto, options={})
70
+ doc=Document.new :paper => :A4 # 210x297
71
+
72
+ template_path = File.join(File.dirname(__FILE__),'..','..','arquivos','templates','modelo_generico.eps')
73
+
74
+ raise "Não foi possível encontrar o template. Verifique o caminho" unless File.exist?(template_path)
75
+
76
+ modelo_generico_template(doc, boleto, template_path)
77
+ modelo_generico_cabecalho(doc, boleto)
78
+ modelo_generico_rodape(doc, boleto)
79
+
80
+ #Gerando codigo de barra com rghost_barcode
81
+ 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
82
+
83
+ # Gerando stream
84
+ formato = (options.delete(:formato) || Brcobranca.configuration.formato)
85
+ resolucao = (options.delete(:resolucao) || Brcobranca.configuration.resolucao)
86
+ doc.render_stream(formato.to_sym, :resolution => resolucao)
87
+ end
88
+
89
+ # Retorna um stream para multiplos boletos pronto para gravação em arquivo.
36
90
  #
37
- # Ou pode ser passado como paramentro:
38
- # :tipo => 'pdf'
39
- def modelo_generico(options={})
91
+ # @return [Stream]
92
+ # @param [Array] Instâncias de classes de boleto.
93
+ # @param [Hash] options Opção para a criação do boleto.
94
+ # @option options [Symbol] :resolucao Resolução em pixels.
95
+ # @option options [Symbol] :formato Formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc]
96
+ def modelo_generico_multipage(boletos, options={})
40
97
  doc=Document.new :paper => :A4 # 210x297
41
98
 
42
99
  template_path = File.join(File.dirname(__FILE__),'..','..','arquivos','templates','modelo_generico.eps')
43
100
 
44
101
  raise "Não foi possível encontrar o template. Verifique o caminho" unless File.exist?(template_path)
45
102
 
103
+ boletos.each_with_index do |boleto, index|
104
+
105
+ modelo_generico_template(doc, boleto, template_path)
106
+ modelo_generico_cabecalho(doc, boleto)
107
+ modelo_generico_rodape(doc, boleto)
108
+
109
+ #Gerando codigo de barra com rghost_barcode
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
111
+ #Cria nova página se não for o último boleto
112
+ doc.next_page unless index == boletos.length-1
113
+
114
+ end
115
+ # Gerando stream
116
+ formato = (options.delete(:formato) || Brcobranca.configuration.formato)
117
+ resolucao = (options.delete(:resolucao) || Brcobranca.configuration.resolucao)
118
+ doc.render_stream(formato.to_sym, :resolution => resolucao)
119
+ end
120
+
121
+ # Define o template a ser usado no boleto
122
+ def modelo_generico_template(doc, boleto, template_path)
46
123
  doc.define_template(:template, template_path, :x => '0.3 cm', :y => "0 cm")
47
124
  doc.use_template :template
48
125
 
49
126
  doc.define_tags do
50
127
  tag :grande, :size => 13
51
128
  end
129
+ end
52
130
 
53
- # Busca logo automaticamente
54
- logo = monta_logo
55
-
131
+ # Monta o cabeçalho do layout do boleto
132
+ def modelo_generico_cabecalho(doc, boleto)
56
133
  #INICIO Primeira parte do BOLETO
57
134
  # LOGOTIPO do BANCO
58
- doc.image(logo, :x => '0.5 cm', :y => '23.85 cm', :zoom => 80) if logo
135
+ doc.image(boleto.logotipo, :x => '0.5 cm', :y => '23.85 cm', :zoom => 80)
59
136
  # Dados
60
137
  doc.moveto :x => '5.2 cm' , :y => '23.85 cm'
61
- doc.show "#{self.banco}-#{self.banco_dv}", :tag => :grande
138
+ doc.show "#{boleto.banco}-#{boleto.banco_dv}", :tag => :grande
62
139
  doc.moveto :x => '7.5 cm' , :y => '23.85 cm'
63
- doc.show self.codigo_barras.linha_digitavel, :tag => :grande
140
+ doc.show boleto.codigo_barras.linha_digitavel, :tag => :grande
64
141
  doc.moveto :x => '0.7 cm' , :y => '23 cm'
65
- doc.show self.cedente
142
+ doc.show boleto.cedente
66
143
  doc.moveto :x => '11 cm' , :y => '23 cm'
67
- doc.show self.agencia_conta_boleto
144
+ doc.show boleto.agencia_conta_boleto
68
145
  doc.moveto :x => '14.2 cm' , :y => '23 cm'
69
- doc.show self.especie
146
+ doc.show boleto.especie
70
147
  doc.moveto :x => '15.7 cm' , :y => '23 cm'
71
- doc.show self.quantidade
148
+ doc.show boleto.quantidade
72
149
  doc.moveto :x => '0.7 cm' , :y => '22.2 cm'
73
- doc.show self.numero_documento
150
+ doc.show boleto.numero_documento
74
151
  doc.moveto :x => '7 cm' , :y => '22.2 cm'
75
- doc.show "#{self.documento_cedente.formata_documento}"
152
+ doc.show "#{boleto.documento_cedente.formata_documento}"
76
153
  doc.moveto :x => '12 cm' , :y => '22.2 cm'
77
- doc.show self.data_vencimento.to_s_br
154
+ doc.show boleto.data_vencimento.to_s_br
78
155
  doc.moveto :x => '16.5 cm' , :y => '23 cm'
79
- doc.show self.nosso_numero_boleto
156
+ doc.show boleto.nosso_numero_boleto
80
157
  doc.moveto :x => '16.5 cm' , :y => '22.2 cm'
81
- doc.show self.valor_documento.to_currency
158
+ doc.show boleto.valor_documento.to_currency
82
159
  doc.moveto :x => '1.4 cm' , :y => '20.9 cm'
83
- doc.show "#{self.sacado} - #{self.sacado_documento.formata_documento}"
160
+ doc.show "#{boleto.sacado} - #{boleto.sacado_documento.formata_documento}"
84
161
  doc.moveto :x => '1.4 cm' , :y => '20.6 cm'
85
- doc.show "#{self.sacado_endereco}"
162
+ doc.show "#{boleto.sacado_endereco}"
86
163
  #FIM Primeira parte do BOLETO
164
+ end
87
165
 
166
+ # Monta o corpo e rodapé do layout do boleto
167
+ def modelo_generico_rodape(doc, boleto)
88
168
  #INICIO Segunda parte do BOLETO BB
89
169
  # LOGOTIPO do BANCO
90
- doc.image(logo, :x => '0.5 cm', :y => '16.8 cm', :zoom => 80) if logo
170
+ doc.image(boleto.logotipo, :x => '0.5 cm', :y => '16.8 cm', :zoom => 80)
91
171
  doc.moveto :x => '5.2 cm' , :y => '16.8 cm'
92
- doc.show "#{self.banco}-#{self.banco_dv}", :tag => :grande if self.banco && self.banco_dv
172
+ doc.show "#{boleto.banco}-#{boleto.banco_dv}", :tag => :grande
93
173
  doc.moveto :x => '7.5 cm' , :y => '16.8 cm'
94
- doc.show self.codigo_barras.linha_digitavel, :tag => :grande if self.codigo_barras && self.codigo_barras.linha_digitavel
174
+ doc.show boleto.codigo_barras.linha_digitavel, :tag => :grande
95
175
  doc.moveto :x => '0.7 cm' , :y => '16 cm'
96
- doc.show self.local_pagamento if self.local_pagamento
176
+ doc.show boleto.local_pagamento
97
177
  doc.moveto :x => '16.5 cm' , :y => '16 cm'
98
- doc.show self.data_vencimento.to_s_br if self.data_vencimento
178
+ doc.show boleto.data_vencimento.to_s_br if boleto.data_vencimento
99
179
  doc.moveto :x => '0.7 cm' , :y => '15.2 cm'
100
- doc.show self.cedente if self.cedente
180
+ doc.show boleto.cedente
101
181
  doc.moveto :x => '16.5 cm' , :y => '15.2 cm'
102
- doc.show self.agencia_conta_boleto
182
+ doc.show boleto.agencia_conta_boleto
103
183
  doc.moveto :x => '0.7 cm' , :y => '14.4 cm'
104
- doc.show self.data_documento.to_s_br if self.data_documento
184
+ doc.show boleto.data_documento.to_s_br if boleto.data_documento
105
185
  doc.moveto :x => '4.2 cm' , :y => '14.4 cm'
106
- doc.show self.numero_documento if self.numero_documento
186
+ doc.show boleto.numero_documento
107
187
  doc.moveto :x => '10 cm' , :y => '14.4 cm'
108
- doc.show self.especie if self.especie
188
+ doc.show boleto.especie
109
189
  doc.moveto :x => '11.7 cm' , :y => '14.4 cm'
110
- doc.show self.aceite if self.aceite
190
+ doc.show boleto.aceite
111
191
  doc.moveto :x => '13 cm' , :y => '14.4 cm'
112
- doc.show self.data_processamento.to_s_br if self.data_processamento
192
+ doc.show boleto.data_processamento.to_s_br if boleto.data_processamento
113
193
  doc.moveto :x => '16.5 cm' , :y => '14.4 cm'
114
- doc.show self.nosso_numero_boleto
194
+ doc.show boleto.nosso_numero_boleto
115
195
  doc.moveto :x => '4.4 cm' , :y => '13.5 cm'
116
- doc.show self.carteira if self.carteira
196
+ doc.show boleto.carteira
117
197
  doc.moveto :x => '6.4 cm' , :y => '13.5 cm'
118
- doc.show self.moeda if self.moeda
198
+ doc.show boleto.moeda
119
199
  doc.moveto :x => '8 cm' , :y => '13.5 cm'
120
- doc.show self.quantidade if self.quantidade
200
+ doc.show boleto.quantidade
121
201
  doc.moveto :x => '11 cm' , :y => '13.5 cm'
122
- doc.show self.valor.to_currency if self.valor
202
+ doc.show boleto.valor.to_currency
123
203
  doc.moveto :x => '16.5 cm' , :y => '13.5 cm'
124
- doc.show self.valor_documento.to_currency if self.valor_documento
204
+ doc.show boleto.valor_documento.to_currency
125
205
  doc.moveto :x => '0.7 cm' , :y => '12.7 cm'
126
- doc.show self.instrucao1 if self.instrucao1
206
+ doc.show boleto.instrucao1
127
207
  doc.moveto :x => '0.7 cm' , :y => '12.3 cm'
128
- doc.show self.instrucao2 if self.instrucao2
208
+ doc.show boleto.instrucao2
129
209
  doc.moveto :x => '0.7 cm' , :y => '11.9 cm'
130
- doc.show self.instrucao3 if self.instrucao3
210
+ doc.show boleto.instrucao3
131
211
  doc.moveto :x => '0.7 cm' , :y => '11.5 cm'
132
- doc.show self.instrucao4 if self.instrucao4
212
+ doc.show boleto.instrucao4
133
213
  doc.moveto :x => '0.7 cm' , :y => '11.1 cm'
134
- doc.show self.instrucao5 if self.instrucao5
214
+ doc.show boleto.instrucao5
135
215
  doc.moveto :x => '0.7 cm' , :y => '10.7 cm'
136
- doc.show self.instrucao6 if self.instrucao6
216
+ doc.show boleto.instrucao6
137
217
  doc.moveto :x => '1.2 cm' , :y => '8.8 cm'
138
- doc.show "#{self.sacado} - #{self.sacado_documento.formata_documento}" if self.sacado && self.sacado_documento
218
+ doc.show "#{boleto.sacado} - #{boleto.sacado_documento.formata_documento}" if boleto.sacado && boleto.sacado_documento
139
219
  doc.moveto :x => '1.2 cm' , :y => '8.4 cm'
140
- doc.show "#{self.sacado_endereco}" if self.sacado_endereco
220
+ doc.show "#{boleto.sacado_endereco}"
141
221
  #FIM Segunda parte do BOLETO
142
-
143
- #Gerando codigo de barra com rghost_barcode
144
- doc.barcode_interleaved2of5(self.codigo_barras, :width => '10.3 cm', :height => '1.3 cm', :x => '0.7 cm', :y => '5.8 cm' ) if self.codigo_barras
145
-
146
- # Gerando stream
147
- options[:tipo] = options[:tipo].to_sym unless options[:tipo].kind_of?(Symbol)
148
- doc.render_stream(options[:tipo])
149
222
  end
150
- end
223
+
224
+ end #Base
151
225
  end
152
226
  end
153
227
  end
@@ -0,0 +1,115 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Brcobranca
3
+ module Boleto
4
+ class Unibanco < Base # Banco UNIBANCO
5
+
6
+ # Com Registro 4
7
+ # Sem Registro 5
8
+ validates_inclusion_of :carteira, :in => %w( 5 4 ), :message => "não existente para este banco."
9
+ validates_length_of :agencia, :maximum => 4, :message => "deve ser menor ou igual a 4 dígitos."
10
+ validates_length_of :convenio, :maximum => 7, :message => "deve ser menor ou igual a 7 dígitos."
11
+ validates_length_of :conta_corrente, :maximum => 7, :message => "deve ser menor ou igual a 7 dígitos."
12
+
13
+ validates_each :numero_documento do |record, attr, value|
14
+ record.errors.add attr, 'deve ser menor ou igual a 14 dígitos.' if (value.to_s.size > 14) && (record.carteira.to_i == 5)
15
+ record.errors.add attr, 'deve ser menor ou igual a 11 dígitos.' if (value.to_s.size > 11) && (record.carteira.to_i == 4)
16
+ end
17
+
18
+ # Nova instancia do Unibanco
19
+ # @param (see Brcobranca::Boleto::Base#initialize)
20
+ def initialize(campos={})
21
+ campos = {:carteira => "5"}.merge!(campos)
22
+ super(campos)
23
+ end
24
+
25
+ # Codigo do banco emissor (3 dígitos sempre)
26
+ #
27
+ # @return [String] 3 caracteres numéricos.
28
+ def banco
29
+ "409"
30
+ end
31
+
32
+ # Número do convênio/contrato do cliente junto ao banco.
33
+ # @return [String] 7 caracteres numéricos.
34
+ def convenio=(valor)
35
+ @convenio = valor.to_s.rjust(7,'0') unless valor.nil?
36
+ end
37
+
38
+ # Número seqüencial utilizado para identificar o boleto.
39
+ #
40
+ # Carteira 5 = 14 caracteres numéricos.<br/>
41
+ # Carteira 4 = 11 caracteres numéricos.
42
+ #
43
+ # @return [String]
44
+ def numero_documento
45
+ case self.carteira.to_i
46
+ when 5
47
+ @numero_documento.to_s.rjust(14,'0')
48
+ else #4
49
+ @numero_documento.to_s.rjust(11,'0')
50
+ end
51
+ end
52
+
53
+ # Dígito verificador do nosso número.
54
+ # @return [String] 1 caracteres numéricos.
55
+ def nosso_numero_dv
56
+ self.numero_documento.modulo11_2to9
57
+ end
58
+
59
+ # Nosso número para exibir no boleto.
60
+ # @return [String]
61
+ # @example
62
+ # boleto.nosso_numero_boleto #=> "00085068014982-9"
63
+ def nosso_numero_boleto
64
+ "#{self.numero_documento}-#{self.nosso_numero_dv}"
65
+ end
66
+
67
+ # Número do convênio/contrato do cliente para exibir no boleto.
68
+ # @return [String]
69
+ # @example
70
+ # boleto.agencia_conta_boleto #=> "0123 / 0100618-5"
71
+ def agencia_conta_boleto
72
+ "#{self.agencia} / #{self.conta_corrente}-#{self.conta_corrente_dv}"
73
+ end
74
+
75
+ # Segunda parte do código de barras.
76
+ #
77
+ # Cobrança sem registro (CÓDIGO DE BARRAS)<br/>
78
+ # Posição | Tamanho | Descrição<br/>
79
+ # 1 a 3 | 3 | número de identificação do Unibanco: 409 (número FIXO)<br/>
80
+ # 4 | 1 | código da moeda. Real (R$)=9 (número FIXO)<br/>
81
+ # 5 | 1 | dígito verificador do CÓDIGO DE BARRAS<br/>
82
+ # 6 a 9 | 4 | fator de vencimento<br/>
83
+ # 10 a 19 | 10 | valor do título com zeros à esquerda<br/>
84
+ # 20 | 1 | código para transação CVT: 5 (número FIXO)(5=7744-5)<br/>
85
+ # 21 a 27 | 7 | número do cliente no CÓDIGO DE BARRAS + dígito verificador<br/>
86
+ # 28 a 29 | 2 | vago. Usar 00 (número FIXO)<br/>
87
+ # 30 a 43 | 14 | Número de referência do cliente<br/>
88
+ # 44 | 1 | Dígito verificador<br/>
89
+ #
90
+ # Cobrança com registro (CÓDIGO DE BARRAS)<br/>
91
+ # Posição | Tamanho | Descrição<br/>
92
+ # 1 a 3 | 3 | Número de identificação do Unibanco: 409 (número FIXO)<br/>
93
+ # 4 | 1 | Código da moeda. Real (R$)=9 (número FIXO)<br/>
94
+ # 5 | 1 | dígito verificador do CÓDIGO DE BARRAS<br/>
95
+ # 6 a 9 | 4 | fator de vencimento em 4 algarismos, conforme tabela da página 14<br/>
96
+ # 10 a 19 | 10 | valor do título com zeros à esquerda<br/>
97
+ # 20 a 21 | 2 | Código para transação CVT: 04 (número FIXO) (04=5539-5)<br/>
98
+ # 22 a 27 | 6 | data de vencimento (AAMMDD)<br/>
99
+ # 28 a 32 | 5 | Código da agência + dígito verificador<br/>
100
+ # 33 a 43 | 11 | “Nosso Número” (NNNNNNNNNNN)<br/>
101
+ # 44 | 1 Super dígito do “Nosso Número” (calculado com o MÓDULO 11 (de 2 a 9))<br/>
102
+ #
103
+ # @return [String] 25 caracteres numéricos.
104
+ def codigo_barras_segunda_parte
105
+ case self.carteira.to_i
106
+ when 5
107
+ "#{self.carteira}#{self.convenio}00#{self.numero_documento}#{self.nosso_numero_dv}"
108
+ else # 4
109
+ data = self.data_vencimento.strftime('%y%m%d')
110
+ "0#{self.carteira}#{data}#{self.agencia}#{self.agencia_dv}#{self.numero_documento}#{self.nosso_numero_dv}"
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,132 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # @author Kivanio Barbosa
3
+ module Brcobranca
4
+ # Métodos auxiliares de cálculos
5
+ module Calculo
6
+ # Calcula módulo 10 segundo a BACEN.
7
+ #
8
+ # @return [Integer]
9
+ # @raise [ArgumentError] Caso não seja um número inteiro.
10
+ def modulo10
11
+ raise ArgumentError, "Número inválido" unless self.is_number?
12
+
13
+ total = 0
14
+ multiplicador = 2
15
+
16
+ self.to_s.split(//).reverse!.each do |caracter|
17
+ total += (caracter.to_i * multiplicador).soma_digitos
18
+ multiplicador = multiplicador == 2 ? 1 : 2
19
+ end
20
+
21
+ valor = (10 - (total % 10))
22
+ valor == 10 ? 0 : valor
23
+ end
24
+
25
+ # Calcula módulo 10 do Banespa.
26
+ #
27
+ # @return [Integer]
28
+ # @raise [ArgumentError] Caso não seja um número inteiro.
29
+ def modulo_10_banespa
30
+ raise ArgumentError, "Número inválido" unless self.is_number?
31
+
32
+ fatores = [7,3,1,9,7,3,1,9,7,3]
33
+ total = 0
34
+ posicao = 0
35
+ self.to_s.split(//).each do |digito|
36
+ total += (digito.to_i * fatores[posicao]).to_s.split(//)[-1].to_i
37
+ posicao = (posicao < (fatores.size - 1)) ? (posicao + 1) : 0
38
+ end
39
+ dv = 10 - total.to_s.split(//)[-1].to_i
40
+ dv == 10 ? 0 : dv
41
+ end
42
+
43
+ # Calcula módulo 11 com multiplicaroes de 9 a 2 segundo a BACEN.
44
+ #
45
+ # @return [Integer]
46
+ def modulo11_9to2
47
+ total = self.multiplicador([9,8,7,6,5,4,3,2])
48
+
49
+ return (total % 11 )
50
+ end
51
+
52
+ # Calcula módulo 11 com multiplicaroes de 2 a 9 segundo a BACEN.
53
+ #
54
+ # @return [Integer]
55
+ def modulo11_2to9
56
+ total = self.multiplicador([2,3,4,5,6,7,8,9])
57
+
58
+ valor = (11 - (total % 11))
59
+ return [0,10,11].include?(valor) ? 1 : valor
60
+ end
61
+
62
+ # Calcula módulo 11 com multiplicaroes de 9 a 2 trocando retorno <b>10 por X</b>.
63
+ #
64
+ # @return [Integer, String] Caso resultado for 10, retorna X.
65
+ def modulo11_9to2_10_como_x
66
+ valor = self.modulo11_9to2
67
+ valor == 10 ? "X" : valor
68
+ end
69
+
70
+ # Calcula módulo 11 com multiplicaroes de 9 a 2 trocando retorno <b>10 por 0</b>.
71
+ #
72
+ # @return [Integer]
73
+ def modulo11_9to2_10_como_zero
74
+ valor = self.modulo11_9to2
75
+ valor == 10 ? 0 : valor
76
+ end
77
+
78
+ # Verifica se String só contem caracteres numéricos.
79
+ #
80
+ # @return [Boolean]
81
+ def is_number?
82
+ self.to_s.empty? ? false : (self.to_s =~ (/\D/)).nil?
83
+ end
84
+
85
+ # Soma dígitos de números inteiros positivos com 2 dígitos ou mais.
86
+ #
87
+ # @return [Integer]
88
+ # @example
89
+ # 1 #=> 1
90
+ # 11 (1+1) #=> 2
91
+ # 13 (1+3) #=> 4
92
+ def soma_digitos
93
+ total = case self.to_i
94
+ when (0..9)
95
+ self
96
+ else
97
+ numero = self.to_s
98
+ total = 0
99
+ 0.upto(numero.size-1) {|digito| total += numero[digito,1].to_i }
100
+ total
101
+ end
102
+ total.to_i
103
+ end
104
+
105
+ # Faz a multiplicação de um número pelos fatores passados como parâmetro.
106
+ #
107
+ # @param [Array]
108
+ # @return [Integer]
109
+ # @raise [ArgumentError] Caso não seja um número inteiro.
110
+ def multiplicador(fatores, &block)
111
+ raise ArgumentError, "Número inválido" unless self.is_number?
112
+
113
+ total = 0
114
+ multiplicador_posicao = 0
115
+
116
+ self.to_s.split(//).reverse!.each do |caracter|
117
+ fator = fatores[multiplicador_posicao]
118
+ total += if block_given?
119
+ yield(caracter, fator)
120
+ else
121
+ (caracter.to_i * fator)
122
+ end
123
+ multiplicador_posicao = (multiplicador_posicao < (fatores.size - 1)) ? (multiplicador_posicao + 1) : 0
124
+ end
125
+ total
126
+ end
127
+ end
128
+ end
129
+
130
+ [ String, Numeric ].each do |klass|
131
+ klass.class_eval { include Brcobranca::Calculo }
132
+ end
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # @author Kivanio Barbosa
3
+ module Brcobranca
4
+ # Métodos auxiliares de cálculos envolvendo Datas.
5
+ module CalculoData
6
+ # Calcula o número de dias corridos entre a <b>data base ("Fixada" em 07.10.1997)</b> e a <b>data de vencimento</b> desejada.
7
+ # @return [String] Contendo 4 dígitos
8
+ # @example
9
+ # Date.parse(2000-07-04).fator_vencimento #=> 1001
10
+ def fator_vencimento
11
+ data_base = Date.parse "1997-10-07"
12
+ Integer(self - data_base).to_s.rjust(4,'0')
13
+ end
14
+
15
+ # Mostra a data em formato <b>dia/mês/ano</b>
16
+ # @return [String]
17
+ # @example
18
+ # Date.today.to_s_br #=> 20/01/2010
19
+ def to_s_br
20
+ self.strftime('%d/%m/%Y')
21
+ end
22
+ # Calcula número de dias julianos.
23
+ #
24
+ # O cálculo é feito subtraindo-se a data atual, pelo último dia válido do ano anterior,
25
+ # acrescentando-se o último algarismo do ano atual na quarta posição.
26
+ #
27
+ # @return [String] contendo 4 dígitos
28
+ #
29
+ # @example
30
+ # Date.parse(2009-02-11).to_juliano #=> "0429"
31
+ def to_juliano
32
+ ultima_data = Date.parse("#{self.year - 1}-12-31")
33
+ ultimo_digito_ano = self.to_s[3..3]
34
+ dias = Integer(self - ultima_data)
35
+ (dias.to_s + ultimo_digito_ano).rjust(4,'0')
36
+ end
37
+ end
38
+ end
39
+
40
+ [ Date ].each do |klass|
41
+ klass.class_eval { include Brcobranca::CalculoData }
42
+ end
@@ -1,7 +1,8 @@
1
- # Implementação feita por Nando Vieira do http://simplesideias.com.br
2
- # post http://simplesideias.com.br/usando-number_to_currency-em-modelos-no-rails
1
+ # @author Fernando Vieira do http://simplesideias.com.br
3
2
  module Brcobranca #:nodoc:[all]
4
3
  module Currency #:nodoc:[all]
4
+ # Implementação feita por Fernando Vieira do http://simplesideias.com.br
5
+ # post http://simplesideias.com.br/usando-number_to_currency-em-modelos-no-rails
5
6
  BRL = {:delimiter => ".", :separator => ",", :unit => "R$", :precision => 2, :position => "before"}
6
7
  USD = {:delimiter => ',', :separator => ".", :unit => "US$", :precision => 2, :position => "before"}
7
8
  DEFAULT = BRL.merge(:unit => "")
@@ -56,8 +57,6 @@ module Brcobranca #:nodoc:[all]
56
57
  end
57
58
  end
58
59
 
59
- # TODO - porque não incluir somente na Numeric?
60
- # [ Fixnum, Bignum, Float ].each do |klass|
61
60
  [ Numeric].each do |klass|
62
61
  klass.class_eval { include Brcobranca::Currency::Number }
63
62
  end