tulios-brcobranca-rails2 2.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +29 -0
  2. data/Manifest.txt +54 -0
  3. data/PostInstall.txt +4 -0
  4. data/README.rdoc +75 -0
  5. data/Rakefile +41 -0
  6. data/brcobranca.gemspec +43 -0
  7. data/lib/brcobranca/arquivos/logos/banespa.jpg +0 -0
  8. data/lib/brcobranca/arquivos/logos/bb.jpg +0 -0
  9. data/lib/brcobranca/arquivos/logos/bradesco.jpg +0 -0
  10. data/lib/brcobranca/arquivos/logos/caixa.jpg +0 -0
  11. data/lib/brcobranca/arquivos/logos/hsbc.jpg +0 -0
  12. data/lib/brcobranca/arquivos/logos/itau.jpg +0 -0
  13. data/lib/brcobranca/arquivos/logos/real.jpg +0 -0
  14. data/lib/brcobranca/arquivos/logos/unibanco.jpg +0 -0
  15. data/lib/brcobranca/arquivos/templates/modelo_generico.eps +0 -0
  16. data/lib/brcobranca/boleto/banco_banespa.rb +85 -0
  17. data/lib/brcobranca/boleto/banco_bradesco.rb +44 -0
  18. data/lib/brcobranca/boleto/banco_brasil.rb +88 -0
  19. data/lib/brcobranca/boleto/banco_caixa.rb +118 -0
  20. data/lib/brcobranca/boleto/banco_hsbc.rb +77 -0
  21. data/lib/brcobranca/boleto/banco_itau.rb +115 -0
  22. data/lib/brcobranca/boleto/banco_real.rb +70 -0
  23. data/lib/brcobranca/boleto/banco_unibanco.rb +79 -0
  24. data/lib/brcobranca/boleto/base.rb +154 -0
  25. data/lib/brcobranca/boleto/template/rghost.rb +153 -0
  26. data/lib/brcobranca/boleto/template/util.rb +34 -0
  27. data/lib/brcobranca/config.rb +9 -0
  28. data/lib/brcobranca/core_ext.rb +287 -0
  29. data/lib/brcobranca/currency.rb +67 -0
  30. data/lib/brcobranca/retorno/base.rb +43 -0
  31. data/lib/brcobranca/retorno/retorno_cbr643.rb +44 -0
  32. data/lib/brcobranca.rb +43 -0
  33. data/spec/arquivos/CBR64310.RET +28 -0
  34. data/spec/brcobranca/banco_banespa_spec.rb +195 -0
  35. data/spec/brcobranca/banco_bradesco_spec.rb +179 -0
  36. data/spec/brcobranca/banco_brasil_spec.rb +353 -0
  37. data/spec/brcobranca/banco_caixa_spec.rb +192 -0
  38. data/spec/brcobranca/banco_hsbc_spec.rb +216 -0
  39. data/spec/brcobranca/banco_itau_spec.rb +202 -0
  40. data/spec/brcobranca/banco_real_spec.rb +145 -0
  41. data/spec/brcobranca/banco_unibanco_spec.rb +193 -0
  42. data/spec/brcobranca/base_spec.rb +240 -0
  43. data/spec/brcobranca/core_ext_spec.rb +275 -0
  44. data/spec/brcobranca/currency_spec.rb +81 -0
  45. data/spec/brcobranca/retorno_cbr643_spec.rb +69 -0
  46. data/spec/brcobranca/rghost_spec.rb +36 -0
  47. data/spec/brcobranca/template/rghost_spec.rb +65 -0
  48. data/spec/brcobranca/template/util_spec.rb +42 -0
  49. data/spec/brcobranca_spec.rb +8 -0
  50. data/spec/rcov.opts +2 -0
  51. data/spec/spec.opts +6 -0
  52. data/spec/spec_helper.rb +10 -0
  53. data/tasks/rcov.rake +12 -0
  54. data/tasks/rspec.rake +21 -0
  55. metadata +202 -0
@@ -0,0 +1,154 @@
1
+ module Brcobranca
2
+ module Boleto
3
+ # Classe base para todas as classes de boletos
4
+ class Base
5
+ # <b>REQUERIDO</b>: Codigo do banco emissor (3 dígitos sempre)
6
+ attr_accessor :banco
7
+ # <b>REQUERIDO</b>: Número do convênio/contrato do cliente junto ao banco emissor
8
+ attr_accessor :convenio
9
+ # <b>REQUERIDO</b>: Tipo de moeda utilizada (Real(R$) e igual a 9)
10
+ attr_accessor :moeda
11
+ # <b>REQUERIDO</b>: Carteira utilizada
12
+ attr_accessor :carteira
13
+ # <b>OPCIONAL</b>: Variacao da carteira(opcional para a maioria dos bancos)
14
+ attr_accessor :variacao
15
+ # <b>OPCIONAL</b>: Data de processamento do boleto, geralmente igual a data_documento
16
+ attr_accessor :data_processamento
17
+ # <b>REQUERIDO</b>: Número de dias a vencer
18
+ attr_accessor :dias_vencimento
19
+ # <b>REQUERIDO</b>: Quantidade de boleto(padrão = 1)
20
+ attr_accessor :quantidade
21
+ # <b>REQUERIDO</b>: Valor do boleto
22
+ attr_accessor :valor
23
+ # <b>REQUERIDO</b>: Número da agencia
24
+ attr_accessor :agencia
25
+ # <b>REQUERIDO</b>: Número da conta corrente
26
+ attr_accessor :conta_corrente
27
+ # <b>REQUERIDO</b>: Nome do proprietario da conta corrente
28
+ attr_accessor :cedente
29
+ # <b>REQUERIDO</b>: Documento do proprietario da conta corrente (CPF ou CNPJ)
30
+ attr_accessor :documento_cedente
31
+ # <b>OPCIONAL</b>: Número sequencial utilizado identificar o boleto
32
+ attr_accessor :numero_documento
33
+ # <b>REQUERIDO</b>: Símbolo da moeda utilizada (R$ no brasil)
34
+ attr_accessor :especie
35
+ # <b>REQUERIDO</b>: Tipo do documento (Geralmente DM que quer dizer Duplicata Mercantil)
36
+ attr_accessor :especie_documento
37
+ # <b>REQUERIDO</b>: Data em que foi emitido o boleto
38
+ attr_accessor :data_documento
39
+ # <b>OPCIONAL</b>: Código utilizado para identificar o tipo de serviço cobrado
40
+ attr_accessor :codigo_servico
41
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
42
+ attr_accessor :instrucao1
43
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
44
+ attr_accessor :instrucao2
45
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
46
+ attr_accessor :instrucao3
47
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
48
+ attr_accessor :instrucao4
49
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
50
+ attr_accessor :instrucao5
51
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
52
+ attr_accessor :instrucao6
53
+ # <b>OPCIONAL</b>: Utilizado para mostrar alguma informação ao sacado
54
+ attr_accessor :instrucao7
55
+ # <b>REQUERIDO</b>: Informação sobre onde o sacado podera efetuar o pagamento
56
+ attr_accessor :local_pagamento
57
+ # <b>REQUERIDO</b>: Informa se o banco deve aceitar o boleto após o vencimento ou não( S ou N, quase sempre S)
58
+ attr_accessor :aceite
59
+ # <b>REQUERIDO</b>: Nome da pessoa que receberá o boleto
60
+ attr_accessor :sacado
61
+ # <b>OPCIONAL</b>: Endereco da pessoa que receberá o boleto
62
+ attr_accessor :sacado_endereco
63
+ # <b>REQUERIDO</b>: Documento da pessoa que receberá o boleto
64
+ attr_accessor :sacado_documento
65
+
66
+ # Responsável por definir dados iniciais quando se cria uma nova intância da classe Base.
67
+ def initialize(campos={})
68
+ padrao = { :moeda => "9", :data_documento => Date.today, :dias_vencimento => 1, :quantidade => 1,
69
+ :especie_documento => "DM", :especie => "R$", :aceite => "S", :valor => 0.0,
70
+ :local_pagamento => "QUALQUER BANCO ATÉ O VENCIMENTO"}
71
+
72
+ campos = padrao.merge!(campos)
73
+ campos.each do |campo, valor|
74
+ instance_variable_set "@#{campo}", valor if self.respond_to?(campo)
75
+ end
76
+ end
77
+
78
+ # Retorna dígito verificador do banco, calculado com modulo11 de 9 para 2
79
+ def banco_dv
80
+ self.banco.modulo11_9to2
81
+ end
82
+
83
+ # Retorna dígito verificador da agência, calculado com modulo11 de 9 para 2
84
+ def agencia_dv
85
+ self.agencia.modulo11_9to2
86
+ end
87
+
88
+ # Retorna dígito verificador da conta corrente, calculado com modulo11 de 9 para 2
89
+ def conta_corrente_dv
90
+ self.conta_corrente.modulo11_9to2
91
+ end
92
+
93
+ # Retorna dígito verificador do nosso número, calculado com modulo11 de 9 para 2
94
+ def nosso_numero_dv
95
+ self.numero_documento.modulo11_9to2
96
+ end
97
+
98
+ # Número sequencial utilizado para distinguir os boletos na agência
99
+ def nosso_numero
100
+ self.numero_documento
101
+ end
102
+
103
+ # Campo usado apenas na exibição no boleto
104
+ # Deverá ser sobreescrito para cada banco
105
+ def nosso_numero_boleto
106
+ "Sobreescreva este método na classe referente ao banco que você esta criando"
107
+ end
108
+
109
+ # Campo usado apenas na exibição no boleto
110
+ # Deverá ser sobreescrito para cada banco
111
+ def agencia_conta_boleto
112
+ "Sobreescreva este método na classe referente ao banco que você esta criando"
113
+ end
114
+
115
+ # Retorna o valor total do documento: <b>quantidate * valor</b> ou <b>zero(0)</b> caso não consiga efetuar o cálculo.
116
+ def valor_documento
117
+ return 0 unless self.quantidade.kind_of?(Numeric) && self.valor.kind_of?(Numeric)
118
+ self.quantidade * self.valor.to_f
119
+ end
120
+
121
+ # Retorna data de vencimento baseado na <b>data_documento + dias_vencimento</b> ou <b>false</b> caso não consiga efetuar o cálculo.
122
+ def data_vencimento
123
+ return nil unless self.data_documento.kind_of?(Date) && self.dias_vencimento.kind_of?(Numeric)
124
+ (self.data_documento + self.dias_vencimento.to_i)
125
+ end
126
+
127
+ # Retorna uma String com 44 caracteres representando o codigo de barras do boleto
128
+ # O código de barra para cobrança contém 44 posições dispostas da seguinte forma:
129
+ # Posição Tamanho Conteúdo
130
+ # 01 a 03 3 Identificação do Banco
131
+ # 04 a 04 1 Código da Moeda (Real = 9, Outras=0)
132
+ # 05 a 05 1 Dígito verificador do Código de Barras
133
+ # 06 a 09 4 Fator de Vencimento (Vide Nota)
134
+ # 10 a 19 10 Valor
135
+ # 20 a 44 25 Campo Livre
136
+ # As posições do campo livre ficam a critério de cada Banco arrecadador.
137
+ def codigo_barras
138
+ codigo = monta_codigo_43_digitos
139
+ return unless codigo
140
+ return if codigo.size != 43
141
+ codigo_dv = codigo.modulo11_2to9
142
+
143
+ "#{codigo[0..3]}#{codigo_dv}#{codigo[4..42]}"
144
+ end
145
+
146
+ # Responsável por montar uma String com 43 caracteres que será usado na criação do código de barras
147
+ # Este metodo precisa ser reescrito para cada classe de boleto a ser criada.
148
+ def monta_codigo_43_digitos
149
+ "Sobreescreva este método na classe referente ao banco que você esta criando"
150
+ end
151
+
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,153 @@
1
+ begin
2
+ require 'rghost'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ gem 'rghost'
6
+ require 'rghost'
7
+ end
8
+
9
+ begin
10
+ require 'rghost_barcode'
11
+ rescue LoadError
12
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
13
+ gem 'rghost_barcode'
14
+ require 'rghost_barcode'
15
+ end
16
+
17
+ module Brcobranca
18
+ module Boleto
19
+ module Template
20
+ # Templates para usar com Rghost
21
+ module Rghost
22
+ include RGhost unless self.include?(RGhost)
23
+
24
+ # 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)
29
+ end
30
+
31
+ # Responsável por setar os valores necessários no template genérico
32
+ # Retorna um stream pronto para gravaçào
33
+ #
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'
36
+ #
37
+ # Ou pode ser passado como paramentro:
38
+ # :tipo => 'pdf'
39
+ def modelo_generico(options={})
40
+ doc=Document.new :paper => :A4 # 210x297
41
+
42
+ template_path = File.join(File.dirname(__FILE__),'..','..','arquivos','templates','modelo_generico.eps')
43
+
44
+ raise "Não foi possível encontrar o template. Verifique o caminho" unless File.exist?(template_path)
45
+
46
+ doc.define_template(:template, template_path, :x => '0.3 cm', :y => "0 cm")
47
+ doc.use_template :template
48
+
49
+ doc.define_tags do
50
+ tag :grande, :size => 13
51
+ end
52
+
53
+ # Busca logo automaticamente
54
+ logo = monta_logo
55
+
56
+ #INICIO Primeira parte do BOLETO
57
+ # LOGOTIPO do BANCO
58
+ doc.image(logo, :x => '0.5 cm', :y => '23.85 cm', :zoom => 80) if logo
59
+ # Dados
60
+ doc.moveto :x => '5.2 cm' , :y => '23.85 cm'
61
+ doc.show "#{self.banco}-#{self.banco_dv}", :tag => :grande
62
+ doc.moveto :x => '7.5 cm' , :y => '23.85 cm'
63
+ doc.show self.codigo_barras.linha_digitavel, :tag => :grande
64
+ doc.moveto :x => '0.7 cm' , :y => '23 cm'
65
+ doc.show self.cedente
66
+ doc.moveto :x => '11 cm' , :y => '23 cm'
67
+ doc.show self.agencia_conta_boleto
68
+ doc.moveto :x => '14.2 cm' , :y => '23 cm'
69
+ doc.show self.especie
70
+ doc.moveto :x => '15.7 cm' , :y => '23 cm'
71
+ doc.show self.quantidade
72
+ doc.moveto :x => '0.7 cm' , :y => '22.2 cm'
73
+ doc.show self.numero_documento
74
+ doc.moveto :x => '7 cm' , :y => '22.2 cm'
75
+ doc.show "#{self.documento_cedente.formata_documento}"
76
+ doc.moveto :x => '12 cm' , :y => '22.2 cm'
77
+ doc.show self.data_vencimento.to_s_br
78
+ doc.moveto :x => '16.5 cm' , :y => '23 cm'
79
+ doc.show self.nosso_numero_boleto
80
+ doc.moveto :x => '16.5 cm' , :y => '22.2 cm'
81
+ doc.show self.valor_documento.to_currency
82
+ doc.moveto :x => '1.4 cm' , :y => '20.9 cm'
83
+ doc.show "#{self.sacado} - #{self.sacado_documento.formata_documento}"
84
+ doc.moveto :x => '1.4 cm' , :y => '20.6 cm'
85
+ doc.show "#{self.sacado_endereco}"
86
+ #FIM Primeira parte do BOLETO
87
+
88
+ #INICIO Segunda parte do BOLETO BB
89
+ # LOGOTIPO do BANCO
90
+ doc.image(logo, :x => '0.5 cm', :y => '16.8 cm', :zoom => 80) if logo
91
+ 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
93
+ 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
95
+ doc.moveto :x => '0.7 cm' , :y => '16 cm'
96
+ doc.show self.local_pagamento if self.local_pagamento
97
+ doc.moveto :x => '16.5 cm' , :y => '16 cm'
98
+ doc.show self.data_vencimento.to_s_br if self.data_vencimento
99
+ doc.moveto :x => '0.7 cm' , :y => '15.2 cm'
100
+ doc.show self.cedente if self.cedente
101
+ doc.moveto :x => '16.5 cm' , :y => '15.2 cm'
102
+ doc.show self.agencia_conta_boleto
103
+ doc.moveto :x => '0.7 cm' , :y => '14.4 cm'
104
+ doc.show self.data_documento.to_s_br if self.data_documento
105
+ doc.moveto :x => '4.2 cm' , :y => '14.4 cm'
106
+ doc.show self.numero_documento if self.numero_documento
107
+ doc.moveto :x => '10 cm' , :y => '14.4 cm'
108
+ doc.show self.especie if self.especie
109
+ doc.moveto :x => '11.7 cm' , :y => '14.4 cm'
110
+ doc.show self.aceite if self.aceite
111
+ doc.moveto :x => '13 cm' , :y => '14.4 cm'
112
+ doc.show self.data_processamento.to_s_br if self.data_processamento
113
+ doc.moveto :x => '16.5 cm' , :y => '14.4 cm'
114
+ doc.show self.nosso_numero_boleto
115
+ doc.moveto :x => '4.4 cm' , :y => '13.5 cm'
116
+ doc.show self.carteira if self.carteira
117
+ doc.moveto :x => '6.4 cm' , :y => '13.5 cm'
118
+ doc.show self.moeda if self.moeda
119
+ doc.moveto :x => '8 cm' , :y => '13.5 cm'
120
+ doc.show self.quantidade if self.quantidade
121
+ doc.moveto :x => '11 cm' , :y => '13.5 cm'
122
+ doc.show self.valor.to_currency if self.valor
123
+ doc.moveto :x => '16.5 cm' , :y => '13.5 cm'
124
+ doc.show self.valor_documento.to_currency if self.valor_documento
125
+ doc.moveto :x => '0.7 cm' , :y => '12.7 cm'
126
+ doc.show self.instrucao1 if self.instrucao1
127
+ doc.moveto :x => '0.7 cm' , :y => '12.3 cm'
128
+ doc.show self.instrucao2 if self.instrucao2
129
+ doc.moveto :x => '0.7 cm' , :y => '11.9 cm'
130
+ doc.show self.instrucao3 if self.instrucao3
131
+ doc.moveto :x => '0.7 cm' , :y => '11.5 cm'
132
+ doc.show self.instrucao4 if self.instrucao4
133
+ doc.moveto :x => '0.7 cm' , :y => '11.1 cm'
134
+ doc.show self.instrucao5 if self.instrucao5
135
+ doc.moveto :x => '0.7 cm' , :y => '10.7 cm'
136
+ doc.show self.instrucao6 if self.instrucao6
137
+ 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
139
+ doc.moveto :x => '1.2 cm' , :y => '8.4 cm'
140
+ doc.show "#{self.sacado_endereco}" if self.sacado_endereco
141
+ #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
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,34 @@
1
+ module Brcobranca
2
+ module Boleto
3
+ module Template
4
+ # Métodos auxiliares de montagem de template
5
+ module Util
6
+ # Responsável por definir a logotipo usada no template genérico,
7
+ # retorna o caminho para o <b>logotipo</b> ou <b>false</b> caso nao consiga encontrar o logotipo.
8
+ def monta_logo
9
+ case self.class.to_s
10
+ when "BancoBrasil"
11
+ imagem = 'bb.jpg'
12
+ when "BancoItau"
13
+ imagem = 'itau.jpg'
14
+ when "BancoHsbc"
15
+ imagem = 'hsbc.jpg'
16
+ when "BancoReal"
17
+ imagem = 'real.jpg'
18
+ when "BancoBradesco"
19
+ imagem = 'bradesco.jpg'
20
+ when "BancoUnibanco"
21
+ imagem = 'unibanco.jpg'
22
+ when "BancoBanespa"
23
+ imagem = 'banespa.jpg'
24
+ when "BancoCaixa"
25
+ imagem = 'caixa.jpg'
26
+ else
27
+ return false
28
+ end
29
+ File.join(File.dirname(__FILE__),'..','..','arquivos','logos',imagem)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ module Brcobranca
2
+ # Módulo de configuração.
3
+ module Config
4
+ # Opções disponíveis:
5
+ # Brcobranca::Config::OPCOES[:tipo] - Pode ser pdf, jpg e ps.
6
+ # Brcobranca::Config::OPCOES[:gerador] - Somente rghost até o momento
7
+ OPCOES = {:tipo => 'pdf', :gerador => 'rghost'}
8
+ end
9
+ end
@@ -0,0 +1,287 @@
1
+ module Brcobranca
2
+ # Métodos auxiliares de formatação
3
+ module Formatacao
4
+ # Formata como CPF
5
+ def to_br_cpf
6
+ (self.kind_of?(String) ? self : self.to_s).gsub(/^(.{3})(.{3})(.{3})(.{2})$/,'\1.\2.\3-\4')
7
+ end
8
+
9
+ # Formata como CEP
10
+ def to_br_cep
11
+ (self.kind_of?(String) ? self : self.to_s).gsub(/^(.{5})(.{3})$/,'\1-\2')
12
+ end
13
+
14
+ # Formata como CNPJ
15
+ def to_br_cnpj
16
+ (self.kind_of?(String) ? self : self.to_s).gsub(/^(.{2})(.{3})(.{3})(.{4})(.{2})$/,'\1.\2.\3/\4-\5')
17
+ end
18
+
19
+ # Gera formatação automatica do documento baseado no tamanho do campo.
20
+ def formata_documento
21
+ case (self.kind_of?(String) ? self : self.to_s).size
22
+ when 8 then self.to_br_cep
23
+ when 11 then self.to_br_cpf
24
+ when 14 then self.to_br_cnpj
25
+ else
26
+ self
27
+ end
28
+ end
29
+
30
+ # Remove caracteres que não sejam numéricos do tipo MOEDA
31
+ def limpa_valor_moeda
32
+ return self unless self.kind_of?(String) && self.moeda?
33
+ self.somente_numeros
34
+ end
35
+
36
+ # Remove caracteres que não sejam numéricos
37
+ def somente_numeros
38
+ return self unless self.kind_of?(String)
39
+ self.gsub(/\D/,'')
40
+ end
41
+
42
+ # Completa zeros a esquerda.
43
+ # Ex. numero="123" :tamanho=>3 | numero="123"
44
+ # Ex. numero="123" :tamanho=>4 | numero="0123"
45
+ # Ex. numero="123" :tamanho=>5 | numero="00123"
46
+ def zeros_esquerda(options={})
47
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
48
+ return valor_inicial if (valor_inicial !~ /\S/)
49
+ digitos = options[:tamanho] || valor_inicial.size
50
+
51
+ diferenca = (digitos - valor_inicial.size)
52
+
53
+ return valor_inicial if (diferenca <= 0)
54
+ return (("0" * diferenca) + valor_inicial )
55
+ end
56
+
57
+ # Monta a linha digitável padrão para todos os bancos segundo a BACEN.
58
+ # Retorna + nil + para Codigo de Barras em branco,
59
+ # Codigo de Barras com tamanho diferente de 44 dígitos e
60
+ # Codigo de Barras que não tenham somente caracteres numéricos.
61
+ # A linha digitável será composta por cinco campos:
62
+ # 1º campo
63
+ # Composto pelo código de Banco, código da moeda, as cinco primeiras posições do campo livre
64
+ # e o dígito verificador deste campo;
65
+ # 2º campo
66
+ # Composto pelas posições 6ª a 15ª do campo livre e o dígito verificador deste campo;
67
+ # 3º campo
68
+ # Composto pelas posições 16ª a 25ª do campo livre e o dígito verificador deste campo;
69
+ # 4º campo
70
+ # Composto pelo dígito verificador do código de barras, ou seja, a 5ª posição do código de
71
+ # barras;
72
+ # 5º campo
73
+ # Composto pelo fator de vencimento com 4(quatro) caracteres e o valor do documento com
74
+ # 10(dez) caracteres, sem separadores e sem edição.
75
+ # Entre cada campo deverá haver espaço equivalente a 2 (duas) posições, sendo a 1ª
76
+ # interpretada por um ponto (.) e a 2ª por um espaço em branco.
77
+ def linha_digitavel
78
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
79
+ raise ArgumentError, "Número em branco" if valor_inicial.nil?
80
+ raise ArgumentError, "Somente números" unless valor_inicial.numeric?
81
+ raise ArgumentError, "Precisa conter 44 caracteres e você passou um valor com #{valor_inicial.size} caracteres" if valor_inicial.size != 44
82
+
83
+ dv_1 = ("#{valor_inicial[0..3]}#{valor_inicial[19..23]}").modulo10
84
+ campo_1_dv = "#{valor_inicial[0..3]}#{valor_inicial[19..23]}#{dv_1}"
85
+ campo_linha_1 = "#{campo_1_dv[0..4]}.#{campo_1_dv[5..9]}"
86
+
87
+ dv_2 = "#{valor_inicial[24..33]}".modulo10
88
+ campo_2_dv = "#{valor_inicial[24..33]}#{dv_2}"
89
+ campo_linha_2 = "#{campo_2_dv[0..4]}.#{campo_2_dv[5..10]}"
90
+
91
+ dv_3 = "#{valor_inicial[34..43]}".modulo10
92
+ campo_3_dv = "#{valor_inicial[34..43]}#{dv_3}"
93
+ campo_linha_3 = "#{campo_3_dv[0..4]}.#{campo_3_dv[5..10]}"
94
+
95
+ campo_linha_4 = "#{valor_inicial[4..4]}"
96
+
97
+ campo_linha_5 = "#{valor_inicial[5..18]}"
98
+
99
+ "#{campo_linha_1} #{campo_linha_2} #{campo_linha_3} #{campo_linha_4} #{campo_linha_5}"
100
+ end
101
+ end
102
+
103
+ # métodos auxiliares de cálculos
104
+ module Calculo
105
+
106
+ # Verifica se String só contem caracteres numéricos.
107
+ #
108
+ # @return [Boolean]
109
+ def is_number?
110
+ self.to_s.empty? ? false : (self.to_s =~ (/\D/)).nil?
111
+ end
112
+
113
+ # Método padrão para cálculo de módulo 10 segundo a BACEN.
114
+ def modulo10
115
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
116
+ raise ArgumentError, "Somente números" unless valor_inicial.numeric?
117
+
118
+ total = 0
119
+ multiplicador = 2
120
+
121
+ valor_inicial.split(//).reverse!.each do |caracter|
122
+ total += (caracter.to_i * multiplicador).soma_digitos
123
+ multiplicador = multiplicador == 2 ? 1 : 2
124
+ end
125
+
126
+ valor = (10 - (total % 10))
127
+ valor == 10 ? 0 : valor
128
+ end
129
+
130
+ # Método padrão para cálculo de módulo 11 com multiplicaroes de 9 a 2 segundo a BACEN.
131
+ # Usado no DV do Nosso Numero, Agência e Cedente.
132
+ # Retorna + nil + para todos os parametros que nao forem String
133
+ # Retorna + nil + para String em branco
134
+ def modulo11_9to2
135
+ total = self.multiplicador([9,8,7,6,5,4,3,2])
136
+
137
+ return (total % 11 )
138
+ end
139
+
140
+ # Método padrão para cálculo de módulo 11 com multiplicaroes de 2 a 9 segundo a BACEN.
141
+ # Usado no DV do Código de Barras.
142
+ # Retorna + nil + para todos os parametros que não forem String
143
+ # Retorna + nil + para String em branco
144
+ def modulo11_2to9
145
+ total = self.multiplicador([2,3,4,5,6,7,8,9])
146
+
147
+ valor = (11 - (total % 11))
148
+ return [0,10,11].include?(valor) ? 1 : valor
149
+ end
150
+
151
+ def modulo_10_banespa
152
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
153
+ raise ArgumentError, "Somente números" unless valor_inicial.numeric?
154
+
155
+ fatores = [7,3,1,9,7,3,1,9,7,3]
156
+ total = 0
157
+ posicao = 0
158
+ valor_inicial.split(//).each do |digito|
159
+ total += (digito.to_i * fatores[posicao]).to_s.split(//)[-1].to_i
160
+ posicao = (posicao < (fatores.size - 1)) ? (posicao + 1) : 0
161
+ end
162
+ dv = 10 - total.to_s.split(//)[-1].to_i
163
+ dv == 10 ? 0 : dv
164
+ end
165
+
166
+ # Retorna o dígito verificador de <b>modulo 11(9-2)</b> trocando retorno <b>10 por X</b>.
167
+ # Usado por alguns bancos.
168
+ def modulo11_9to2_10_como_x
169
+ valor = self.modulo11_9to2
170
+ valor == 10 ? "X" : valor
171
+ end
172
+
173
+ # Retorna o dígito verificador de <b>modulo 11(9-2)</b> trocando retorno <b>10 por 0</b>.
174
+ # Usado por alguns bancos.
175
+ def modulo11_9to2_10_como_zero
176
+ valor = self.modulo11_9to2
177
+ valor == 10 ? 0 : valor
178
+ end
179
+
180
+ # Soma números inteiros positivos com 2 dígitos ou mais
181
+ # Retorna <b>0(zero)</b> caso seja impossível.
182
+ # Ex. 1 = 1
183
+ # Ex. 11 = (1+1) = 2
184
+ # Ex. 13 = (1+3) = 4
185
+ def soma_digitos
186
+ valor_inicial = self.kind_of?(Fixnum) ? self : self.to_i
187
+ return 0 if valor_inicial == 0
188
+ return valor_inicial if valor_inicial <= 9
189
+
190
+ valor_inicial = valor_inicial.to_s
191
+ total = 0
192
+
193
+ 0.upto(valor_inicial.size-1) {|digito| total += valor_inicial[digito,1].to_i }
194
+
195
+ return total
196
+ end
197
+
198
+ def multiplicador(fatores)
199
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
200
+ raise ArgumentError, "Somente números" unless valor_inicial.numeric?
201
+
202
+ total = 0
203
+ multiplicador_posicao = 0
204
+
205
+ valor_inicial.split(//).reverse!.each do |caracter|
206
+ total += (caracter.to_i * fatores[multiplicador_posicao])
207
+ multiplicador_posicao = (multiplicador_posicao < (fatores.size - 1)) ? (multiplicador_posicao + 1) : 0
208
+ end
209
+ total.to_i
210
+ end
211
+ end
212
+
213
+ # Métodos auxiliares de verificação e validação.
214
+ module Validacao
215
+ # Verifica se o valor é moeda.
216
+ # Ex. +1.232.33
217
+ # Ex. -1.232.33
218
+ # Ex. 1.232.33
219
+ def moeda?
220
+ value = self.kind_of?(String) ? self : self.to_s
221
+ value =~ /^(\+|-)?\d+((\.|,)\d{3}*)*((\.|,)\d{2}*)$/ ? true : false
222
+ end
223
+ end
224
+
225
+ # Métodos auxiliares de limpeza.
226
+ module Limpeza
227
+ # Retorna uma String contendo exatamente o valor FLOAT
228
+ def limpa_valor_moeda
229
+ valor_inicial = self.to_s
230
+ (valor_inicial + ("0" * (2 - valor_inicial.split(/\./).last.size ))).somente_numeros
231
+ end
232
+ end
233
+
234
+ # Métodos auxiliares de cálculos envolvendo <b>Datas</b>.
235
+ module CalculoData
236
+ # 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> desejado:
237
+ # VENCIMENTO 04/07/2000
238
+ # DATA BASE - 07/10/1997
239
+ # FATOR DE VENCIMENTO 1001
240
+ def fator_vencimento
241
+ data_base = Date.parse "1997-10-07"
242
+ (self - data_base).to_i
243
+ end
244
+
245
+ # Mostra a data em formato <b>dia/mês/ano</b>
246
+ def to_s_br
247
+ self.strftime('%d/%m/%Y')
248
+ end
249
+ # Retorna string contendo número de dias julianos:
250
+ # O cálculo é feito subtraindo-se a data atual, pelo último dia válido do ano anterior,
251
+ # acrescentando-se o último algarismo do ano atual na quarta posição.
252
+ # Deve retornar string com 4 digitos.
253
+ # Ex. Data atual = 11/02/2009
254
+ # Data válida ano anterior = 31/12/2008
255
+ # (Data atual - Data válida ano anterior) = 42
256
+ # último algarismo do ano atual = 9
257
+ # String atual 42+9 = 429
258
+ # Completa zero esquerda para formar 4 digitos = "0429"
259
+ def to_juliano
260
+ ultima_data = Date.parse("#{self.year - 1}-12-31")
261
+ ultimo_digito_ano = self.to_s[3..3]
262
+ dias = (self - ultima_data)
263
+ (dias.to_s + ultimo_digito_ano).zeros_esquerda(:tamanho => 4)
264
+ end
265
+ end
266
+ end
267
+
268
+ # NEW AND COOL
269
+ [ String, Numeric ].each do |klass|
270
+ klass.class_eval { include Brcobranca::Formatacao }
271
+ end
272
+
273
+ [ String, Numeric ].each do |klass|
274
+ klass.class_eval { include Brcobranca::Validacao }
275
+ end
276
+
277
+ [ String, Numeric ].each do |klass|
278
+ klass.class_eval { include Brcobranca::Calculo }
279
+ end
280
+
281
+ [ Float ].each do |klass|
282
+ klass.class_eval { include Brcobranca::Limpeza }
283
+ end
284
+
285
+ [ Date ].each do |klass|
286
+ klass.class_eval { include Brcobranca::CalculoData }
287
+ end