br_boleto 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|