br_boleto 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +145 -0
- data/History.txt +4 -0
- data/LICENSE +20 -0
- data/README.markdown +156 -0
- data/Rakefile +8 -0
- data/br_boleto.gemspec +26 -0
- data/lib/br_boleto.rb +87 -0
- data/lib/br_boleto/calculos/digitos.rb +35 -0
- data/lib/br_boleto/calculos/fator_vencimento.rb +129 -0
- data/lib/br_boleto/calculos/fatores_de_multiplicacao.rb +67 -0
- data/lib/br_boleto/calculos/linha_digitavel.rb +158 -0
- data/lib/br_boleto/calculos/modulo10.rb +83 -0
- data/lib/br_boleto/calculos/modulo11.rb +54 -0
- data/lib/br_boleto/calculos/modulo11_fator3197.rb +88 -0
- data/lib/br_boleto/calculos/modulo11_fator_de2a7.rb +97 -0
- data/lib/br_boleto/calculos/modulo11_fator_de2a9.rb +83 -0
- data/lib/br_boleto/calculos/modulo11_fator_de2a9_resto_zero.rb +29 -0
- data/lib/br_boleto/calculos/modulo11_fator_de9a2.rb +65 -0
- data/lib/br_boleto/calculos/modulo11_fator_de9a2_resto_x.rb +55 -0
- data/lib/br_boleto/calculos/modulo_numero_de_controle.rb +117 -0
- data/lib/br_boleto/core/boleto.rb +558 -0
- data/lib/br_boleto/core/sicoob.rb +169 -0
- data/lib/br_boleto/version.rb +8 -0
- data/test/br_boleto/calculos/digitos_test.rb +15 -0
- data/test/br_boleto/calculos/fator_vencimento_test.rb +56 -0
- data/test/br_boleto/calculos/fatores_de_multiplicacao_test.rb +66 -0
- data/test/br_boleto/calculos/linha_digitavel_test.rb +58 -0
- data/test/br_boleto/calculos/modulo10_test.rb +54 -0
- data/test/br_boleto/calculos/modulo11_fator3197_test.rb +43 -0
- data/test/br_boleto/calculos/modulo11_fator_de2a7_test.rb +44 -0
- data/test/br_boleto/calculos/modulo11_fator_de2a9_resto_zero_test.rb +40 -0
- data/test/br_boleto/calculos/modulo11_fator_de2a9_test.rb +68 -0
- data/test/br_boleto/calculos/modulo11_fator_de9a2_resto_x_test.rb +38 -0
- data/test/br_boleto/calculos/modulo11_fator_de9a2_test.rb +32 -0
- data/test/br_boleto/calculos/modulo11_test.rb +28 -0
- data/test/br_boleto/calculos/modulo_numero_de_controle_test.rb +38 -0
- data/test/br_boleto/core/boleto_test.rb +221 -0
- data/test/br_boleto/core/sicoob_test.rb +138 -0
- data/test/factories/boleto.rb +22 -0
- data/test/factories/boleto_sicoob.rb +23 -0
- data/test/inheritance/boleto_test.rb +15 -0
- data/test/inheritance/sicoob_test.rb +25 -0
- data/test/test_helper.rb +37 -0
- metadata +151 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support/core_ext/enumerable'
|
3
|
+
|
4
|
+
module BrBoleto
|
5
|
+
module Calculos
|
6
|
+
# Classe responsável por lidar com os dígitos dos módulos.
|
7
|
+
#
|
8
|
+
class Digitos
|
9
|
+
# @param [Integer] number Número que servirá para os cálculo com os dígitos desse número.
|
10
|
+
#
|
11
|
+
def initialize(number)
|
12
|
+
@number = number
|
13
|
+
end
|
14
|
+
|
15
|
+
# Soma cada dígito do número passado no #initialize.
|
16
|
+
# Alguns bancos requerem esse tipo estranho de cálculo em alguns módulos.
|
17
|
+
# @return [Fixnum] Resultado da soma de cada dígito.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# Digitos.new(12).sum
|
22
|
+
# # => 3
|
23
|
+
#
|
24
|
+
# Digitos.new(2244).sum
|
25
|
+
# # => 12
|
26
|
+
#
|
27
|
+
# Digitos.new(90123451).sum
|
28
|
+
# # => 25
|
29
|
+
#
|
30
|
+
def sum
|
31
|
+
@number.to_s.split('').collect { |number| number.to_i }.sum
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module BrBoleto
|
3
|
+
module Calculos
|
4
|
+
# Classe responsável pelo cálculo de Fator de Vencimento do boleto bancário.
|
5
|
+
#
|
6
|
+
# === Descricão
|
7
|
+
#
|
8
|
+
# Conforme Carta-circular 002926 do Banco Central do Brasil, de 24/07/2000, recomenda-se a indicação do Fator de Vencimento no Código de Barras.
|
9
|
+
# A partir de 02/04/2001, o Banco acolhedor/recebedor não será mais responsável por eventuais diferenças de recebimento de BOLETOs fora do prazo,
|
10
|
+
# ou sem a indicação do fator de vencimento.
|
11
|
+
#
|
12
|
+
# === Forma para obtenção do Fator de Vencimento
|
13
|
+
#
|
14
|
+
# Calcula-se <b>o número de dias corridos</b> entre a data base (<b>“Fixada” em 07/10/1997</b>) e a do vencimento desejado:
|
15
|
+
# Alguns bancos dizem para Fazer o seguinte Cálculo: ((data de vencimento) - (03/07/2000) + 1000)
|
16
|
+
# Porém esse cálculo é a mesma coisa que fazer: ((data de vencimento) - (07/10/1997))
|
17
|
+
#
|
18
|
+
# Vencimento desejado: 04/07/2000
|
19
|
+
# Data base : - 07/10/1997
|
20
|
+
# # => 1001
|
21
|
+
#
|
22
|
+
# === Atenção
|
23
|
+
#
|
24
|
+
# Caso ocorra divergência entre a data impressa no campo “data de vencimento” e a constante no código de barras,
|
25
|
+
# o recebimento se dará da seguinte forma:
|
26
|
+
#
|
27
|
+
# * Quando pago por sistemas eletrônicos (Home-Banking, Auto-Atendimento, Internet, SISPAG, telefone, etc.), prevalecerá à representada no “código de barras”;
|
28
|
+
# * Quando quitado na rede de agências, diretamente no caixa, será considerada a data impressa no campo “vencimento” do BOLETO.
|
29
|
+
#
|
30
|
+
# @return [String] retorna o resultado do cálculo. <b>Deve conter 4 dígitos</b>.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
#
|
34
|
+
# FatorVencimento.new(Date.parse("2012-12-02"))
|
35
|
+
# #=> "5535"
|
36
|
+
#
|
37
|
+
# FatorVencimento.new(Date.parse("1997-10-08"))
|
38
|
+
# #=> "0001"
|
39
|
+
#
|
40
|
+
# FatorVencimento.new(Date.parse("2012-12-16"))
|
41
|
+
# #=> "5549"
|
42
|
+
#
|
43
|
+
# FatorVencimento.new(Date.parse("2014-12-15"))
|
44
|
+
# #=> "6278"
|
45
|
+
#
|
46
|
+
|
47
|
+
|
48
|
+
class FatorVencimento < String
|
49
|
+
|
50
|
+
# A base é des de quando será subtraido a data de validade
|
51
|
+
attr_accessor :base_date
|
52
|
+
def base_date
|
53
|
+
@base_date || Date.new(1997, 10, 7)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param [Date] expiration_date
|
57
|
+
# @param [Date] base_date
|
58
|
+
# @return [String] retorna o resultado do cálculo. <b>Deve conter 4 dígitos</b>.
|
59
|
+
# @example
|
60
|
+
# FatorVencimento.new(Date.parse("2012-09-02"))
|
61
|
+
# #=> "5444"
|
62
|
+
#
|
63
|
+
# FatorVencimento.new(Date.parse("1999-10-01"))
|
64
|
+
# #=> "0724"
|
65
|
+
#
|
66
|
+
# FatorVencimento.new(Date.parse("2022-12-16"))
|
67
|
+
# #=> "9201"
|
68
|
+
#
|
69
|
+
|
70
|
+
#########################################################
|
71
|
+
############ OPÇÃO PARA CUSTOMIZAÇÃO DO CÁLCULO #########
|
72
|
+
############# MODIFIQUE APENAS SE TIVER CERTEZA #########
|
73
|
+
#########################################################
|
74
|
+
# Caso algum dia mude a forma do cálculo da data base, os valores do cálculo
|
75
|
+
# poderão ser passados por parâmetro. Dia 22/02/2025 a diferença terá 5 números
|
76
|
+
# Mas até lá não se sabe o que irá mudar
|
77
|
+
attr_accessor :subtracao
|
78
|
+
# Caso necessite subtratir o resultado entre a diferença do (vencimento - data_base)
|
79
|
+
def subtracao
|
80
|
+
@subtracao || 0
|
81
|
+
end
|
82
|
+
|
83
|
+
# Caso necessite somar o resultado entre a diferença do (vencimento - data_base)
|
84
|
+
attr_accessor :soma
|
85
|
+
def soma
|
86
|
+
@soma || 0
|
87
|
+
end
|
88
|
+
|
89
|
+
# Caso necessite modificar o número de caracteres de retorno
|
90
|
+
attr_accessor :quantidade_de_caracteres
|
91
|
+
def quantidade_de_caracteres
|
92
|
+
@quantidade_de_caracteres || 4
|
93
|
+
end
|
94
|
+
#########################################################
|
95
|
+
|
96
|
+
def initialize(expiration_date, options={})
|
97
|
+
@expiration_date = expiration_date
|
98
|
+
self.base_date = options[:base_date]
|
99
|
+
self.subtracao = options[:subtracao]
|
100
|
+
self.soma = options[:soma]
|
101
|
+
self.quantidade_de_caracteres = options[:quantidade_de_caracteres]
|
102
|
+
|
103
|
+
if @expiration_date.present?
|
104
|
+
super(calculate)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
# Cálculo da data de vencimento com a data base.
|
111
|
+
#
|
112
|
+
# @return [String] exatamente 4 dígitos
|
113
|
+
#
|
114
|
+
def calculate
|
115
|
+
expiration_date_minus_base_date.to_s.rjust(quantidade_de_caracteres, '0')
|
116
|
+
end
|
117
|
+
|
118
|
+
# @api private
|
119
|
+
#
|
120
|
+
# Cálculo da data de vencimento com a data base.
|
121
|
+
# Chamando #to_i para não retornar um Float.
|
122
|
+
# @return [Integer] diff between this two dates.
|
123
|
+
#
|
124
|
+
def expiration_date_minus_base_date
|
125
|
+
((@expiration_date - base_date).to_i+soma)-subtracao
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module BrBoleto
|
3
|
+
module Calculos
|
4
|
+
# Classe responsável por multiplicar cada dígito pelos fatores de multiplicação passado como argumento.
|
5
|
+
#
|
6
|
+
# Imagine que temos o número <b>'2468'</b> e os fatores de multiplicação <b>[2, 1]</b>.
|
7
|
+
#
|
8
|
+
# Será calculado da seguinte maneira:
|
9
|
+
#
|
10
|
+
# 2 4 6 8
|
11
|
+
# * * * * ===> Multiplicação
|
12
|
+
# 1 2 1 2
|
13
|
+
#
|
14
|
+
# #=> [2, 8, 6, 16]
|
15
|
+
#
|
16
|
+
# Você pode passar outros fatores de multiplicação se você precisar.
|
17
|
+
# Por exemplo, dado o número '1234567890' e os fatores de multiplicação: <b>[2, 3, 4, 5, 6, 7, 8, 9]</b>.
|
18
|
+
# Será calculado da seguinte maneira:
|
19
|
+
#
|
20
|
+
# 1 2 3 4 5 6 7 8 9 0
|
21
|
+
# * * * * * * * * * *
|
22
|
+
# 3 2 9 8 7 6 5 4 3 2
|
23
|
+
#
|
24
|
+
# #=> [3, 4, 27, 32, 35, 36, 35, 32, 27, 0]
|
25
|
+
#
|
26
|
+
# @param [String] O número que será usado para multiplicar cada dígito.
|
27
|
+
# @param [Hash] Os fatores de multiplicação que irão ser calculados na ordem reversa.
|
28
|
+
#
|
29
|
+
# @example Calculo
|
30
|
+
#
|
31
|
+
# BrBoleto::Calculos::FatoresDeMultiplicacao.new(123, fatores: [2, 1])
|
32
|
+
# # => [1, 2, 6]
|
33
|
+
#
|
34
|
+
# BrBoleto::Calculos::FatoresDeMultiplicacao.new(123, fatores: [2, 3, 4, 5, 6, 7, 8, 9])
|
35
|
+
# # => [4, 6, 6]
|
36
|
+
#
|
37
|
+
# BrBoleto::Calculos::FatoresDeMultiplicacao.new(809070608090, fatores: [9, 8, 7, 6, 5, 4, 3, 2])
|
38
|
+
# # => [48, 0, 72, 0, 14, 0, 24, 0, 48, 0, 72, 0]
|
39
|
+
#
|
40
|
+
class FatoresDeMultiplicacao < Array
|
41
|
+
# @param [String || Integer] number
|
42
|
+
# @param [Hash] options
|
43
|
+
# @option options [Array] :fatores
|
44
|
+
# @return [Array]
|
45
|
+
# @example
|
46
|
+
#
|
47
|
+
# FatoresDeMultiplicacao.new(12, fatores: [2, 1])
|
48
|
+
# # => [1, 4]
|
49
|
+
#
|
50
|
+
# FatoresDeMultiplicacao.new(1864, fatores: [2, 3, 4, 5, 6, 7, 8, 9])
|
51
|
+
# # => [5, 32, 18, 8]
|
52
|
+
#
|
53
|
+
def initialize(number, options)
|
54
|
+
@number = number.to_s.reverse.split('')
|
55
|
+
@factors = options.fetch(:fatores).cycle.take(@number.size)
|
56
|
+
super(calculate)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Para cada número realiza a multiplicação para cada dígito.
|
60
|
+
# @return [Array]
|
61
|
+
#
|
62
|
+
def calculate
|
63
|
+
@number.collect.each_with_index { |n, index| n.to_i * @factors[index] }.reverse
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support/core_ext/object'
|
3
|
+
|
4
|
+
module BrBoleto
|
5
|
+
module Calculos
|
6
|
+
# Representação numérica do código de barras, mais conhecida como linha digitável! :p
|
7
|
+
#
|
8
|
+
# A representação numérica do código de barras é composta, por cinco campos.
|
9
|
+
# Sendo os três primeiros campos, amarrados por DAC's (dígitos verificadores),
|
10
|
+
# todos calculados pelo módulo 10.
|
11
|
+
#
|
12
|
+
# <b>OBS.:</b> Para mais detalhes deste cálculo, veja a descrição em Modulo10.
|
13
|
+
#
|
14
|
+
# === Linha Digitável
|
15
|
+
#
|
16
|
+
# A linha digitável contêm exatamente 47 posições nessa sequência:
|
17
|
+
#
|
18
|
+
# _____________________________________________________________________________________________________________
|
19
|
+
# |Campo | Posição | Tamanho | Descrição |
|
20
|
+
# |------|----------|---------|--------------------------------------------------------------------------------|
|
21
|
+
# | 1º | 01-03 | 03 | Código do banco (posições 1 a 3 do código de barras) |
|
22
|
+
# | | 04 | 01 | Código da moeda (posição 4 do código de barras) |
|
23
|
+
# | | 05-09 | 5 | Cinco primeiras posições do campo livre (posições 20 a 24 do código de barras) |
|
24
|
+
# | | 10 | 1 | Dígito verificador do primeiro campo (Módulo10) |
|
25
|
+
# |------------------------------------------------------------------------------------------------------------|
|
26
|
+
# | 2º | 11-20 | 10 | 6º a 15º posições do campo livre (posições 25 a 34 do código de barras) |
|
27
|
+
# | | 21 | 01 | Dígito verificador do segundo campo (Módulo10) |
|
28
|
+
# |------------------------------------------------------------------------------------------------------------|
|
29
|
+
# | 3º | 22-31 | 10 | 16º a 25º posições do campo livre (posições 35 a 44 do código de barras) |
|
30
|
+
# | | 32 | 01 | Dígito verificador do terceiro campo (Módulo10) |
|
31
|
+
# |------------------------------------------------------------------------------------------------------------|
|
32
|
+
# | 4º | 33 | 01 | Dígito verificador do código de barras (posição 5 do código de barras) |
|
33
|
+
# |------------------------------------------------------------------------------------------------------------|
|
34
|
+
# | 5ª | 34-37 | 04 | Fator de vencimento (posições 6 a 9 do código de barras) |
|
35
|
+
# | | 38-47 | 10 | Valor nominal do documento (posições 10 a 19 do código de barras) |
|
36
|
+
# -------------------------------------------------------------------------------------------------------------|
|
37
|
+
#
|
38
|
+
# @return [String] Contêm a representação numérica do código de barras formatado com pontos e espaços.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
#
|
42
|
+
# LinhaDigitavel.new('34196166700000123451091234567880057123457000')
|
43
|
+
# # => '34191.09123 34567.880058 71234.570001 6 16670000012345'
|
44
|
+
#
|
45
|
+
# LinhaDigitavel.new('99991101200000350007772130530150081897500000')
|
46
|
+
# # => '99997.77213 30530.150082 18975.000003 1 10120000035000'
|
47
|
+
#
|
48
|
+
# LinhaDigitavel.new('39998100100000311551111122222500546666666001')
|
49
|
+
# # => '39991.11119 22222.500542 66666.660015 8 10010000031155'
|
50
|
+
#
|
51
|
+
class LinhaDigitavel < String
|
52
|
+
attr_reader :codigo_de_barras
|
53
|
+
# @param [String] codigo_de_barras Código de Barras de 44 posições
|
54
|
+
# @return [String]
|
55
|
+
#
|
56
|
+
# Representação numérica do código de barras
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
#
|
60
|
+
# LinhaDigitavel.new('34196166700000123451091234567880057123457000')
|
61
|
+
# # => '34191.09123 34567.880058 71234.570001 6 16670000012345'
|
62
|
+
#
|
63
|
+
# LinhaDigitavel.new('99991101200000350007772130530150081897500000')
|
64
|
+
# # => '99997.77213 30530.150082 18975.000003 1 10120000035000'
|
65
|
+
#
|
66
|
+
# LinhaDigitavel.new('39998100100000311551111122222500546666666001')
|
67
|
+
# # => '39991.11119 22222.500542 66666.660015 8 10010000031155'
|
68
|
+
#
|
69
|
+
# # Retorna uma String vazia caso o código de barras esteja vazio.
|
70
|
+
# LinhaDigitavel.new('')
|
71
|
+
# # => ''
|
72
|
+
#
|
73
|
+
# # Retorna uma String vazia caso o código de barras esteja vazio.
|
74
|
+
# LinhaDigitavel.new(nil)
|
75
|
+
# # => ''
|
76
|
+
#
|
77
|
+
# # Retorna uma String vazia caso o código de barras seja menor que 44 posições.
|
78
|
+
# LinhaDigitavel.new('123456789')
|
79
|
+
# # => ''
|
80
|
+
#
|
81
|
+
# # Retorna uma String vazia caso o código de barras seja maior que 44 posições.
|
82
|
+
# LinhaDigitavel.new('12345678901234567890123456789012345678901234567890')
|
83
|
+
# # => ''
|
84
|
+
#
|
85
|
+
def initialize(codigo_de_barras)
|
86
|
+
@codigo_de_barras = codigo_de_barras.to_s
|
87
|
+
|
88
|
+
if @codigo_de_barras.present? and @codigo_de_barras.size == 44
|
89
|
+
super(representacao_numerica_do_codigo_de_barras)
|
90
|
+
else
|
91
|
+
super('')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [String] Retorna todos os campos da linha digitável pegando as posições exatas do código de barras.
|
96
|
+
#
|
97
|
+
def representacao_numerica_do_codigo_de_barras
|
98
|
+
"#{primeiro_campo} #{segundo_campo} #{terceiro_campo} #{quarto_campo} #{quinto_campo}"
|
99
|
+
end
|
100
|
+
|
101
|
+
# @api private
|
102
|
+
#
|
103
|
+
# Retorna o primeiro campo da linha digitável com seu respectivo dígito verificador.
|
104
|
+
#
|
105
|
+
# @return [String]
|
106
|
+
#
|
107
|
+
def primeiro_campo
|
108
|
+
primeiro_campo_sem_digito = "#{codigo_de_barras[0..3]}#{codigo_de_barras[19..23]}"
|
109
|
+
digito_verificador = Modulo10.new(primeiro_campo_sem_digito)
|
110
|
+
"#{primeiro_campo_sem_digito}#{digito_verificador}".gsub(/^(.{5})(.{5})/, '\1.\2')
|
111
|
+
end
|
112
|
+
|
113
|
+
# @api private
|
114
|
+
#
|
115
|
+
# Retorna o segundo campo da linha digitável com seu respectivo dígito verificador.
|
116
|
+
#
|
117
|
+
# @return [String]
|
118
|
+
#
|
119
|
+
def segundo_campo
|
120
|
+
segundo_campo_sem_digito = "#{codigo_de_barras[24..33]}"
|
121
|
+
digito_verificador = Modulo10.new(segundo_campo_sem_digito)
|
122
|
+
"#{segundo_campo_sem_digito}#{digito_verificador}".gsub(/(.{5})(.{6})/, '\1.\2')
|
123
|
+
end
|
124
|
+
|
125
|
+
# @api private
|
126
|
+
#
|
127
|
+
# Retorna o terceiro campo da linha digitável com seu respectivo dígito verificador.
|
128
|
+
#
|
129
|
+
# @return [String]
|
130
|
+
#
|
131
|
+
def terceiro_campo
|
132
|
+
terceiro_campo_sem_digito = "#{codigo_de_barras[34..46]}"
|
133
|
+
digito_verificador = Modulo10.new(terceiro_campo_sem_digito)
|
134
|
+
"#{terceiro_campo_sem_digito}#{digito_verificador}".gsub(/(.{5})(.{6})/, '\1.\2')
|
135
|
+
end
|
136
|
+
|
137
|
+
# @api private
|
138
|
+
#
|
139
|
+
# Retorna o dígito verificador do código de barras (posição 5 do código de barras)
|
140
|
+
#
|
141
|
+
# @return [String]
|
142
|
+
#
|
143
|
+
def quarto_campo
|
144
|
+
"#{codigo_de_barras[4]}"
|
145
|
+
end
|
146
|
+
|
147
|
+
# @api private
|
148
|
+
#
|
149
|
+
# Retorna o quinto e último campo da linha digitável.
|
150
|
+
#
|
151
|
+
# @return [String]
|
152
|
+
#
|
153
|
+
def quinto_campo
|
154
|
+
"#{codigo_de_barras[5..8]}#{codigo_de_barras[9..18]}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module BrBoleto
|
3
|
+
module Calculos
|
4
|
+
# === Cálculo do Modulo 10
|
5
|
+
#
|
6
|
+
# === Passos
|
7
|
+
#
|
8
|
+
# 1) Multiplica-se cada algarismo do campo pela seqüência de multiplicadores <b>2, 1, 2, 1, 2, 1 ...</b>, posicionados da direita para a esquerda.
|
9
|
+
#
|
10
|
+
# 2) Some individualmente, os algarismos dos resultados dos produtos, obtendo-se o total (N).
|
11
|
+
#
|
12
|
+
# 3) Divida o total encontrado (N) por 10, e determine o resto da divisão como MOD 10 (N).
|
13
|
+
#
|
14
|
+
# 4) Encontre o DAC através da seguinte expressão:
|
15
|
+
#
|
16
|
+
# DAC = 10 - Mod 10 (n)
|
17
|
+
#
|
18
|
+
# <b>OBS.:</b> Se o resultado do passo 4 for 10, considere o DAC = 0.
|
19
|
+
#
|
20
|
+
# ==== Exemplos
|
21
|
+
#
|
22
|
+
# Considerando-se a seguinte representação numérica <b>'12345'</b>.
|
23
|
+
#
|
24
|
+
# 1) Multiplicando a seqüência de multiplicadores:
|
25
|
+
#
|
26
|
+
# 1 2 3 4 5
|
27
|
+
# * * * * * ===> Multiplicação.
|
28
|
+
# 2 1 2 1 2
|
29
|
+
#
|
30
|
+
# 2) Some, individualmente:
|
31
|
+
#
|
32
|
+
# 2 + 2 + 6 + 4 + 1 + 0 (Veja a observação abaixo explicando o '1' + '0').
|
33
|
+
# # => 15
|
34
|
+
#
|
35
|
+
# <b>OBS.:</b>: Resultado da soma que possua 2 digitos deve somar cada dígito.
|
36
|
+
# Exemplos: 10 -> 1 + 0. 11 -> 1 + 1, 28 -> 2 + 8, etc.
|
37
|
+
#
|
38
|
+
# 3) Divida o total encontrado por 10, a fim de determinar o resto da divisão:
|
39
|
+
#
|
40
|
+
# 15 % 10
|
41
|
+
# # => 5
|
42
|
+
#
|
43
|
+
# 4) Calculando o DAC:
|
44
|
+
#
|
45
|
+
# 10 - 5
|
46
|
+
# # => 5 =======> Resultado final retornado.
|
47
|
+
#
|
48
|
+
class Modulo10 < String
|
49
|
+
# @param [String ou Integer] number (Corresponde ao número a ser calculado pelo Módulo 10)
|
50
|
+
# @return [String]
|
51
|
+
# @example
|
52
|
+
#
|
53
|
+
# BrBoleto::Calculos::Modulo10.new(1233)
|
54
|
+
# # => "6"
|
55
|
+
#
|
56
|
+
# BrBoleto::Calculos::Modulo10.new(4411)
|
57
|
+
# # => "5"
|
58
|
+
#
|
59
|
+
# BrBoleto::Calculos::Modulo10.new('9000')
|
60
|
+
# # => "1"
|
61
|
+
#
|
62
|
+
# BrBoleto::Calculos::Modulo10.new('6789')
|
63
|
+
# # => "2"
|
64
|
+
#
|
65
|
+
def initialize(number)
|
66
|
+
@number = number
|
67
|
+
super(calculate.to_s)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [String] Resultado final do cálculo do módulo 10.
|
71
|
+
#
|
72
|
+
def calculate
|
73
|
+
sum_total = FatoresDeMultiplicacao.new(@number, fatores: [2, 1]).collect do |result_of_each_sum|
|
74
|
+
Digitos.new(result_of_each_sum).sum
|
75
|
+
end.sum
|
76
|
+
total = 10 - (sum_total % 10)
|
77
|
+
|
78
|
+
return 0 if total.equal?(10)
|
79
|
+
total
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|