kivanio-brcobranca 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +21 -0
  2. data/Manifest.txt +48 -0
  3. data/README.rdoc +72 -0
  4. data/Rakefile +32 -0
  5. data/brcobranca.gemspec +47 -0
  6. data/lib/brcobranca/arquivos/logos/bb.jpg +0 -0
  7. data/lib/brcobranca/arquivos/logos/bradesco.jpg +0 -0
  8. data/lib/brcobranca/arquivos/logos/hsbc.jpg +0 -0
  9. data/lib/brcobranca/arquivos/logos/itau.jpg +0 -0
  10. data/lib/brcobranca/arquivos/logos/real.jpg +0 -0
  11. data/lib/brcobranca/arquivos/logos/unibanco.jpg +0 -0
  12. data/lib/brcobranca/arquivos/templates/modelo_generico.eps +0 -0
  13. data/lib/brcobranca/boleto/banco_bradesco.rb +31 -0
  14. data/lib/brcobranca/boleto/banco_brasil.rb +79 -0
  15. data/lib/brcobranca/boleto/banco_hsbc.rb +63 -0
  16. data/lib/brcobranca/boleto/banco_itau.rb +105 -0
  17. data/lib/brcobranca/boleto/banco_real.rb +56 -0
  18. data/lib/brcobranca/boleto/banco_unibanco.rb +65 -0
  19. data/lib/brcobranca/boleto/base.rb +148 -0
  20. data/lib/brcobranca/boleto/template/rghost.rb +151 -0
  21. data/lib/brcobranca/boleto/template/util.rb +30 -0
  22. data/lib/brcobranca/config.rb +9 -0
  23. data/lib/brcobranca/core_ext.rb +269 -0
  24. data/lib/brcobranca/currency.rb +70 -0
  25. data/lib/brcobranca/retorno/base.rb +43 -0
  26. data/lib/brcobranca/retorno/retorno_cbr643.rb +44 -0
  27. data/lib/brcobranca.rb +27 -0
  28. data/script/console +10 -0
  29. data/script/destroy +14 -0
  30. data/script/generate +14 -0
  31. data/script/txt2html +71 -0
  32. data/test/arquivos/CBR64310.RET +28 -0
  33. data/test/test_banco_bradesco.rb +87 -0
  34. data/test/test_banco_brasil.rb +276 -0
  35. data/test/test_banco_hsbc.rb +81 -0
  36. data/test/test_banco_itau.rb +103 -0
  37. data/test/test_banco_real.rb +112 -0
  38. data/test/test_banco_unibanco.rb +92 -0
  39. data/test/test_base.rb +162 -0
  40. data/test/test_core_ext.rb +227 -0
  41. data/test/test_currency.rb +51 -0
  42. data/test/test_helper.rb +5 -0
  43. data/test/test_retorno_cbr643.rb +66 -0
  44. data/website/index.html +89 -0
  45. data/website/index.txt +46 -0
  46. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  47. data/website/stylesheets/screen.css +159 -0
  48. data/website/template.html.erb +57 -0
  49. metadata +164 -0
@@ -0,0 +1,148 @@
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
+ # Retorna o valor total do documento: <b>quantidate * valor</b> ou <b>zero(0)</b> caso não consiga efetuar o cálculo.
104
+ def valor_documento
105
+ begin
106
+ self.quantidade * self.valor.to_f
107
+ rescue
108
+ 0
109
+ end
110
+ end
111
+
112
+ # Retorna data de vencimento baseado na <b>data_documento + dias_vencimento</b> ou <b>false</b> caso não consiga efetuar o cálculo.
113
+ def data_vencimento
114
+ begin
115
+ return false unless self.data_documento.kind_of?(Date)
116
+ (self.data_documento + self.dias_vencimento.to_i)
117
+ rescue
118
+ false
119
+ end
120
+ end
121
+
122
+ # Retorna uma String com 44 caracteres representando o codigo de barras do boleto
123
+ # O código de barra para cobrança contém 44 posições dispostas da seguinte forma:
124
+ # Posição Tamanho Conteúdo
125
+ # 01 a 03 3 Identificação do Banco
126
+ # 04 a 04 1 Código da Moeda (Real = 9, Outras=0)
127
+ # 05 a 05 1 Dígito verificador do Código de Barras
128
+ # 06 a 09 4 Fator de Vencimento (Vide Nota)
129
+ # 10 a 19 10 Valor
130
+ # 20 a 44 25 Campo Livre
131
+ # As posições do campo livre ficam a critério de cada Banco arrecadador.
132
+ def codigo_barras
133
+ codigo = monta_codigo_43_digitos
134
+ return nil unless codigo
135
+ return nil if codigo.size != 43
136
+ codigo_dv = codigo.modulo11_2to9
137
+
138
+ "#{codigo[0..3]}#{codigo_dv}#{codigo[4..42]}"
139
+ end
140
+
141
+ # Responsável por montar uma String com 43 caracteres que será usado na criação do código de barras
142
+ # Este metodo precisa ser reescrito para cada classe de boleto a ser criada.
143
+ def monta_codigo_43_digitos
144
+ "Sobreescreva este método na classe referente ao banco que você esta criando"
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,151 @@
1
+ begin
2
+ require 'rghost'
3
+ rescue LoadError
4
+ puts 'Por favor execute `sudo gem install rghost` para usar o brcobranca'
5
+ end
6
+ begin
7
+ require 'rghost_barcode'
8
+ rescue LoadError
9
+ puts 'Por favor execute `sudo gem install rghost_barcode` para usar o brcobranca'
10
+ end
11
+
12
+ module Brcobranca
13
+ module Boleto
14
+ module Template
15
+ # Templates para usar com Rghost
16
+ module Rghost
17
+ include RGhost unless self.include?(RGhost)
18
+
19
+ # Gera o boleto em usando o formato desejado [:pdf, :jpg, :tif, :png, :ps, :laserjet, ... etc]
20
+ # Veja mais formatos na documentação do rghost: http://wiki.github.com/shairontoledo/rghost/supported-devices-drivers-and-formats
21
+ def to(formato)
22
+ modelo_generico(:tipo => formato)
23
+ end
24
+
25
+ # Responsável por setar os valores necessários no template genérico
26
+ # Retorna um stream pronto para gravaçào
27
+ #
28
+ # O tipo do arquivo gerado pode ser modificado incluindo a configuração a baixo dentro da sua aplicação:
29
+ # Brcobranca::Config::OPCOES[:tipo] = 'pdf'
30
+ #
31
+ # Ou pode ser passado como paramentro:
32
+ # :tipo => 'pdf'
33
+ def modelo_generico(options={})
34
+ doc=Document.new :paper => :A4 # 210x297
35
+
36
+ template_path = File.join(File.dirname(__FILE__),'..','..','arquivos','templates','modelo_generico.eps')
37
+
38
+ raise "Não foi possível encontrar o template. Verifique o caminho" unless File.exist?(template_path)
39
+
40
+ doc.define_template(:template, template_path, :x => '0.3 cm', :y => "0 cm")
41
+ doc.use_template :template
42
+
43
+ doc.define_tags do
44
+ tag :grande, :size => 13
45
+ end
46
+
47
+ # Busca logo automaticamente
48
+ logo = monta_logo
49
+
50
+ #INICIO Primeira parte do BOLETO
51
+ # LOGOTIPO do BANCO
52
+ doc.image(logo, :x => '0.5 cm', :y => '23.85 cm', :zoom => 80) if logo
53
+ # Dados
54
+ doc.moveto :x => '5.2 cm' , :y => '23.85 cm'
55
+ doc.show "#{self.banco}-#{self.banco_dv}", :tag => :grande
56
+ doc.moveto :x => '7.5 cm' , :y => '23.85 cm'
57
+ doc.show self.codigo_barras.linha_digitavel, :tag => :grande
58
+ doc.moveto :x => '0.7 cm' , :y => '23 cm'
59
+ doc.show self.cedente
60
+ doc.moveto :x => '11 cm' , :y => '23 cm'
61
+ doc.show "#{self.agencia}-#{self.agencia_dv}/#{self.conta_corrente}-#{self.conta_corrente_dv}"
62
+ doc.moveto :x => '14.2 cm' , :y => '23 cm'
63
+ doc.show self.especie
64
+ doc.moveto :x => '15.7 cm' , :y => '23 cm'
65
+ doc.show self.quantidade
66
+ doc.moveto :x => '0.7 cm' , :y => '22.2 cm'
67
+ doc.show self.numero_documento
68
+ doc.moveto :x => '7 cm' , :y => '22.2 cm'
69
+ doc.show "#{self.sacado_documento.formata_documento}"
70
+ doc.moveto :x => '12 cm' , :y => '22.2 cm'
71
+ doc.show self.data_vencimento.to_s_br
72
+ doc.moveto :x => '16.5 cm' , :y => '23 cm'
73
+ doc.show self.nosso_numero
74
+ doc.moveto :x => '16.5 cm' , :y => '22.2 cm'
75
+ doc.show self.valor_documento.to_currency
76
+ doc.moveto :x => '1.4 cm' , :y => '20.9 cm'
77
+ doc.show "#{self.sacado} - #{self.sacado_documento.formata_documento}"
78
+ doc.moveto :x => '1.4 cm' , :y => '20.6 cm'
79
+ doc.show "#{self.sacado_endereco}"
80
+ #FIM Primeira parte do BOLETO
81
+
82
+ #INICIO Segunda parte do BOLETO BB
83
+ # LOGOTIPO do BANCO
84
+ doc.image(logo, :x => '0.5 cm', :y => '16.8 cm', :zoom => 80) if logo
85
+ doc.moveto :x => '5.2 cm' , :y => '16.8 cm'
86
+ doc.show "#{self.banco}-#{self.banco_dv}", :tag => :grande if self.banco && self.banco_dv
87
+ doc.moveto :x => '7.5 cm' , :y => '16.8 cm'
88
+ doc.show self.codigo_barras.linha_digitavel, :tag => :grande if self.codigo_barras && self.codigo_barras.linha_digitavel
89
+ doc.moveto :x => '0.7 cm' , :y => '16 cm'
90
+ doc.show self.local_pagamento if self.local_pagamento
91
+ doc.moveto :x => '16.5 cm' , :y => '16 cm'
92
+ doc.show self.data_vencimento.to_s_br if self.data_vencimento
93
+ doc.moveto :x => '0.7 cm' , :y => '15.2 cm'
94
+ doc.show self.cedente if self.cedente
95
+ doc.moveto :x => '16.5 cm' , :y => '15.2 cm'
96
+ doc.show "#{self.agencia}-#{self.agencia_dv}/#{self.conta_corrente}-#{self.conta_corrente_dv}"
97
+ doc.moveto :x => '0.7 cm' , :y => '14.4 cm'
98
+ doc.show self.data_documento.to_s_br if self.data_documento
99
+ doc.moveto :x => '4.2 cm' , :y => '14.4 cm'
100
+ doc.show self.numero_documento if self.numero_documento
101
+ doc.moveto :x => '10 cm' , :y => '14.4 cm'
102
+ doc.show self.especie if self.especie
103
+ doc.moveto :x => '11.7 cm' , :y => '14.4 cm'
104
+ doc.show self.aceite if self.aceite
105
+ doc.moveto :x => '13 cm' , :y => '14.4 cm'
106
+ doc.show self.data_processamento.to_s_br if self.data_processamento
107
+ doc.moveto :x => '16.5 cm' , :y => '14.4 cm'
108
+ doc.show self.nosso_numero
109
+ doc.moveto :x => '4.4 cm' , :y => '13.5 cm'
110
+ doc.show self.carteira if self.carteira
111
+ doc.moveto :x => '6.4 cm' , :y => '13.5 cm'
112
+ doc.show self.moeda if self.moeda
113
+ doc.moveto :x => '8 cm' , :y => '13.5 cm'
114
+ doc.show self.quantidade if self.quantidade
115
+ doc.moveto :x => '11 cm' , :y => '13.5 cm'
116
+ doc.show self.valor.to_currency if self.valor
117
+ doc.moveto :x => '16.5 cm' , :y => '13.5 cm'
118
+ doc.show self.valor_documento.to_currency if self.valor_documento
119
+ doc.moveto :x => '0.7 cm' , :y => '12.7 cm'
120
+ doc.show self.instrucao1 if self.instrucao1
121
+ doc.moveto :x => '0.7 cm' , :y => '12.3 cm'
122
+ doc.show self.instrucao2 if self.instrucao2
123
+ doc.moveto :x => '0.7 cm' , :y => '11.9 cm'
124
+ doc.show self.instrucao3 if self.instrucao3
125
+ doc.moveto :x => '0.7 cm' , :y => '11.5 cm'
126
+ doc.show self.instrucao4 if self.instrucao4
127
+ doc.moveto :x => '0.7 cm' , :y => '11.1 cm'
128
+ doc.show self.instrucao5 if self.instrucao5
129
+ doc.moveto :x => '0.7 cm' , :y => '10.7 cm'
130
+ doc.show self.instrucao6 if self.instrucao6
131
+ doc.moveto :x => '1.2 cm' , :y => '8.8 cm'
132
+ doc.show "#{self.sacado} - #{self.sacado_documento.formata_documento}" if self.sacado && self.sacado_documento
133
+ doc.moveto :x => '1.2 cm' , :y => '8.4 cm'
134
+ doc.show "#{self.sacado_endereco}" if self.sacado_endereco
135
+ #FIM Segunda parte do BOLETO
136
+
137
+ #Gerando codigo de barra com rghost_barcode
138
+ 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
139
+
140
+ # Gerando stream
141
+ unless options[:tipo]
142
+ options[:tipo] = Brcobranca::Config::OPCOES[:tipo]
143
+ end
144
+
145
+ options[:tipo] = options[:tipo].to_sym unless options[:tipo].kind_of?(Symbol)
146
+ doc.render_stream(options[:tipo])
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,30 @@
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
+ else
23
+ return false
24
+ end
25
+ File.join(File.dirname(__FILE__),'..','..','arquivos','logos',imagem)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ 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,269 @@
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
+ return nil if (valor_inicial !~ /\S/) || valor_inicial.size != 44 || (!valor_inicial.scan(/\D/).empty?)
80
+
81
+ dv_1 = ("#{valor_inicial[0..3]}#{valor_inicial[19..23]}").modulo10
82
+ campo_1_dv = "#{valor_inicial[0..3]}#{valor_inicial[19..23]}#{dv_1}"
83
+ campo_linha_1 = "#{campo_1_dv[0..4]}.#{campo_1_dv[5..9]}"
84
+
85
+ dv_2 = "#{valor_inicial[24..33]}".modulo10
86
+ campo_2_dv = "#{valor_inicial[24..33]}#{dv_2}"
87
+ campo_linha_2 = "#{campo_2_dv[0..4]}.#{campo_2_dv[5..10]}"
88
+
89
+ dv_3 = "#{valor_inicial[34..43]}".modulo10
90
+ campo_3_dv = "#{valor_inicial[34..43]}#{dv_3}"
91
+ campo_linha_3 = "#{campo_3_dv[0..4]}.#{campo_3_dv[5..10]}"
92
+
93
+ campo_linha_4 = "#{valor_inicial[4..4]}"
94
+
95
+ campo_linha_5 = "#{valor_inicial[5..18]}"
96
+
97
+ "#{campo_linha_1} #{campo_linha_2} #{campo_linha_3} #{campo_linha_4} #{campo_linha_5}"
98
+ end
99
+ end
100
+
101
+ # métodos auxiliares de cálculos
102
+ module Calculo
103
+ # Método padrão para cálculo de módulo 10 segundo a BACEN.
104
+ def modulo10
105
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
106
+ return nil if (valor_inicial !~ /\S/)
107
+
108
+ total = 0
109
+ multiplicador = 2
110
+
111
+ valor_inicial.split(//).reverse!.each do |caracter|
112
+ total += (caracter.to_i * multiplicador).soma_digitos
113
+ multiplicador = multiplicador == 2 ? 1 : 2
114
+ end
115
+
116
+ valor = (10 - (total % 10))
117
+ valor == 10 ? 0 : valor
118
+ end
119
+
120
+ # Método padrão para cálculo de módulo 11 com multiplicaroes de 9 a 2 segundo a BACEN.
121
+ # Usado no DV do Nosso Numero, Agência e Cedente.
122
+ # Retorna + nil + para todos os parametros que nao forem String
123
+ # Retorna + nil + para String em branco
124
+ def modulo11_9to2
125
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
126
+ return nil if (valor_inicial !~ /\S/)
127
+
128
+ multiplicadores = [9,8,7,6,5,4,3,2]
129
+ total = 0
130
+ multiplicador_posicao = 0
131
+
132
+ valor_inicial.split(//).reverse!.each do |caracter|
133
+ multiplicador_posicao = 0 if (multiplicador_posicao == 8)
134
+ total += (caracter.to_i * multiplicadores[multiplicador_posicao])
135
+ multiplicador_posicao += 1
136
+ end
137
+
138
+ return (total % 11 )
139
+ end
140
+
141
+ # Método padrão para cálculo de módulo 11 com multiplicaroes de 2 a 9 segundo a BACEN.
142
+ # Usado no DV do Código de Barras.
143
+ # Retorna + nil + para todos os parametros que não forem String
144
+ # Retorna + nil + para String em branco
145
+ def modulo11_2to9
146
+ valor_inicial = self.kind_of?(String) ? self : self.to_s
147
+ return nil if (valor_inicial !~ /\S/)
148
+
149
+ multiplicadores = [2,3,4,5,6,7,8,9]
150
+ total = 0
151
+ multiplicador_posicao = 0
152
+
153
+ valor_inicial.split(//).reverse!.each do |caracter|
154
+ multiplicador_posicao = 0 if (multiplicador_posicao == 8)
155
+ total += (caracter.to_i * multiplicadores[multiplicador_posicao])
156
+ multiplicador_posicao += 1
157
+ end
158
+
159
+ valor = (11 - (total % 11))
160
+ return [0,10,11].include?(valor) ? 1 : valor
161
+ end
162
+
163
+ # Retorna o dígito verificador de <b>modulo 11(9-2)</b> trocando retorno <b>10 por X</b>.
164
+ # Usado por alguns bancos.
165
+ def modulo11_9to2_10_como_x
166
+ valor = self.modulo11_9to2
167
+ valor == 10 ? "X" : valor
168
+ end
169
+
170
+ # Retorna o dígito verificador de <b>modulo 11(9-2)</b> trocando retorno <b>10 por 0</b>.
171
+ # Usado por alguns bancos.
172
+ def modulo11_9to2_10_como_zero
173
+ valor = self.modulo11_9to2
174
+ valor == 10 ? 0 : valor
175
+ end
176
+
177
+ # Soma números inteiros positivos com 2 dígitos ou mais
178
+ # Retorna <b>0(zero)</b> caso seja impossível.
179
+ # Ex. 1 = 1
180
+ # Ex. 11 = (1+1) = 2
181
+ # Ex. 13 = (1+3) = 4
182
+ def soma_digitos
183
+ valor_inicial = self.kind_of?(Fixnum) ? self : self.to_i
184
+ return 0 if valor_inicial == 0
185
+ return valor_inicial if valor_inicial <= 9
186
+
187
+ valor_inicial = valor_inicial.to_s
188
+ total = 0
189
+
190
+ 0.upto(valor_inicial.size-1) {|digito| total += valor_inicial[digito,1].to_i }
191
+
192
+ return total
193
+ end
194
+ end
195
+
196
+ # Métodos auxiliares de verificação e validação.
197
+ module Validacao
198
+ # Verifica se o valor é moeda.
199
+ # Ex. +1.232.33
200
+ # Ex. -1.232.33
201
+ # Ex. 1.232.33
202
+ def moeda?
203
+ return false unless self.kind_of?(String)
204
+ self =~ /^(\+|-)?\d+((\.|,)\d{3}*)*((\.|,)\d{2}*)$/ ? true : false
205
+ end
206
+ end
207
+
208
+ # Métodos auxiliares de limpeza.
209
+ module Limpeza
210
+ # Retorna uma String contendo exatamente o valor FLOAT
211
+ def limpa_valor_moeda
212
+ return self unless self.kind_of?(Float)
213
+ valor_inicial = self.to_s
214
+ (valor_inicial + ("0" * (2 - valor_inicial.split(/\./).last.size ))).somente_numeros
215
+ end
216
+ end
217
+
218
+ # Métodos auxiliares de cálculos envolvendo <b>Datas</b>.
219
+ module CalculoData
220
+ # 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:
221
+ # VENCIMENTO 04/07/2000
222
+ # DATA BASE - 07/10/1997
223
+ # FATOR DE VENCIMENTO 1001
224
+ def fator_vencimento
225
+ data_base = Date.parse "1997-10-07"
226
+ (self - data_base).to_i
227
+ end
228
+
229
+ # Mostra a data em formato <b>dia/mês/ano</b>
230
+ def to_s_br
231
+ self.strftime('%d/%m/%Y')
232
+ end
233
+ # Retorna string contendo número de dias julianos:
234
+ # O cálculo é feito subtraindo-se a data atual, pelo último dia válido do ano anterior,
235
+ # acrescentando-se o último algarismo do ano atual na quarta posição.
236
+ # Deve retornar string com 4 digitos.
237
+ # Ex. Data atual = 11/02/2009
238
+ # Data válida ano anterior = 31/12/2008
239
+ # (Data atual - Data válida ano anterior) = 42
240
+ # último algarismo do ano atual = 9
241
+ # String atual 42+9 = 429
242
+ # Completa zero esquerda para formar 4 digitos = "0429"
243
+ def to_juliano
244
+ ultima_data = Date.parse("#{self.year - 1}-12-31")
245
+ ultimo_digito_ano = self.to_s[3..3]
246
+ dias = (self - ultima_data)
247
+ (dias.to_s + ultimo_digito_ano).zeros_esquerda(:tamanho => 4)
248
+ end
249
+ end
250
+ end
251
+
252
+ class String #:nodoc:[all]
253
+ include Brcobranca::Formatacao
254
+ include Brcobranca::Validacao
255
+ include Brcobranca::Calculo
256
+ end
257
+
258
+ class Integer #:nodoc:[all]
259
+ include Brcobranca::Formatacao
260
+ include Brcobranca::Calculo
261
+ end
262
+
263
+ class Float #:nodoc:[all]
264
+ include Brcobranca::Limpeza
265
+ end
266
+
267
+ class Date #:nodoc:[all]
268
+ include Brcobranca::CalculoData
269
+ end
@@ -0,0 +1,70 @@
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
3
+ module Brcobranca #:nodoc:[all]
4
+ module Currency #:nodoc:[all]
5
+ BRL = {:delimiter => ".", :separator => ",", :unit => "R$", :precision => 2, :position => "before"}
6
+ USD = {:delimiter => ',', :separator => ".", :unit => "US$", :precision => 2, :position => "before"}
7
+ DEFAULT = BRL.merge(:unit => "")
8
+
9
+ module String #:nodoc:[all]
10
+ def to_number(options={})
11
+ return self.gsub(/,/, '.').to_f if self.numeric?
12
+ nil
13
+ end
14
+
15
+ def numeric?
16
+ self =~ /^(\+|-)?[0-9]+((\.|,)[0-9]+)?$/ ? true : false
17
+ end
18
+ end
19
+
20
+ module Number #:nodoc:[all]
21
+ def to_currency(options = {})
22
+ number = self
23
+ default = Brcobranca::Currency::DEFAULT.stringify_keys
24
+ options = default.merge(options.stringify_keys)
25
+ precision = options["precision"] || default["precision"]
26
+ unit = options["unit"] || default["unit"]
27
+ position = options["position"] || default["position"]
28
+ separator = precision > 0 ? options["separator"] || default["separator"] : ""
29
+ delimiter = options["delimiter"] || default["delimiter"]
30
+
31
+ begin
32
+ parts = number.with_precision(precision).split('.')
33
+ number = parts[0].to_i.with_delimiter(delimiter) + separator + parts[1].to_s
34
+ position == "before" ? unit + number : number + unit
35
+ rescue
36
+ number
37
+ end
38
+ end
39
+
40
+ def with_delimiter(delimiter=",", separator=".")
41
+ number = self
42
+ begin
43
+ parts = number.to_s.split(separator)
44
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
45
+ parts.join separator
46
+ rescue
47
+ self
48
+ end
49
+ end
50
+
51
+ def with_precision(precision=3)
52
+ number = self
53
+ "%01.#{precision}f" % number
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ class Fixnum #:nodoc:[all]
60
+ include Brcobranca::Currency::Number
61
+ end
62
+ class Bignum #:nodoc:[all]
63
+ include Brcobranca::Currency::Number
64
+ end
65
+ class Float #:nodoc:[all]
66
+ include Brcobranca::Currency::Number
67
+ end
68
+ class String #:nodoc:[all]
69
+ include Brcobranca::Currency::String
70
+ end