br_documents 0.0.2
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/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/README.md +146 -0
- data/Rakefile +1 -0
- data/br_documents.gemspec +30 -0
- data/config/locales/pt-BR.yml +8 -0
- data/lib/br_documents.rb +4 -0
- data/lib/br_documents/cnpj_cpf/cnpj.rb +21 -0
- data/lib/br_documents/cnpj_cpf/cpf.rb +21 -0
- data/lib/br_documents/cnpj_cpf/document.rb +35 -0
- data/lib/br_documents/cnpj_validator.rb +8 -0
- data/lib/br_documents/commons/mod11.rb +20 -0
- data/lib/br_documents/cpf_validator.rb +8 -0
- data/lib/br_documents/ie/ac.rb +17 -0
- data/lib/br_documents/ie/al.rb +17 -0
- data/lib/br_documents/ie/am.rb +17 -0
- data/lib/br_documents/ie/ap.rb +52 -0
- data/lib/br_documents/ie/ba.rb +75 -0
- data/lib/br_documents/ie/base.rb +17 -0
- data/lib/br_documents/ie/ce.rb +12 -0
- data/lib/br_documents/ie/df.rb +17 -0
- data/lib/br_documents/ie/es.rb +12 -0
- data/lib/br_documents/ie/factory.rb +12 -0
- data/lib/br_documents/ie/go.rb +17 -0
- data/lib/br_documents/ie/ma.rb +12 -0
- data/lib/br_documents/ie/mg.rb +53 -0
- data/lib/br_documents/ie/ms.rb +12 -0
- data/lib/br_documents/ie/mt.rb +18 -0
- data/lib/br_documents/ie/pa.rb +17 -0
- data/lib/br_documents/ie/pattern1.rb +26 -0
- data/lib/br_documents/ie/pattern2.rb +30 -0
- data/lib/br_documents/ie/pb.rb +12 -0
- data/lib/br_documents/ie/pe.rb +51 -0
- data/lib/br_documents/ie/pi.rb +12 -0
- data/lib/br_documents/ie/pr.rb +19 -0
- data/lib/br_documents/ie/rj.rb +18 -0
- data/lib/br_documents/ie/rn.rb +47 -0
- data/lib/br_documents/ie/ro.rb +49 -0
- data/lib/br_documents/ie/rr.rb +23 -0
- data/lib/br_documents/ie/rs.rb +18 -0
- data/lib/br_documents/ie/sc.rb +17 -0
- data/lib/br_documents/ie/se.rb +12 -0
- data/lib/br_documents/ie/sp.rb +55 -0
- data/lib/br_documents/ie/to.rb +18 -0
- data/lib/br_documents/ie_validator.rb +50 -0
- data/lib/br_documents/version.rb +3 -0
- data/spec/cnpj_cpf/cnpj_spec.rb +45 -0
- data/spec/cnpj_cpf/cpf_spec.rb +45 -0
- data/spec/cnpj_validator_spec.rb +36 -0
- data/spec/cpf_validator_spec.rb +36 -0
- data/spec/ie/ac_spec.rb +40 -0
- data/spec/ie/al_spec.rb +33 -0
- data/spec/ie/am_spec.rb +40 -0
- data/spec/ie/ap_spec.rb +33 -0
- data/spec/ie/ba_spec.rb +63 -0
- data/spec/ie/ce_spec.rb +13 -0
- data/spec/ie/df_spec.rb +40 -0
- data/spec/ie/es_spec.rb +13 -0
- data/spec/ie/factory_spec.rb +203 -0
- data/spec/ie/go_spec.rb +40 -0
- data/spec/ie/ma_spec.rb +13 -0
- data/spec/ie/mg_spec.rb +40 -0
- data/spec/ie/ms_spec.rb +13 -0
- data/spec/ie/mt_spec.rb +40 -0
- data/spec/ie/pa_spec.rb +40 -0
- data/spec/ie/pb_spec.rb +13 -0
- data/spec/ie/pe_spec.rb +59 -0
- data/spec/ie/pi_spec.rb +13 -0
- data/spec/ie/pr_spec.rb +33 -0
- data/spec/ie/rj_spec.rb +40 -0
- data/spec/ie/rn_spec.rb +59 -0
- data/spec/ie/ro_spec.rb +59 -0
- data/spec/ie/rr_spec.rb +40 -0
- data/spec/ie/rs_spec.rb +38 -0
- data/spec/ie/sc_spec.rb +40 -0
- data/spec/ie/se_spec.rb +13 -0
- data/spec/ie/shared_examples_for_pattern1.rb +33 -0
- data/spec/ie/sp_spec.rb +42 -0
- data/spec/ie/to_spec.rb +40 -0
- data/spec/ie_validator_spec.rb +65 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/utilities.rb +3 -0
- metadata +248 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "pattern1"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class RJ < Pattern1
|
6
|
+
def initialize(number)
|
7
|
+
super
|
8
|
+
@mask = /^(\d{2}\.\d{3}\.\d{2}\-\d{1})$|^(\d{8})$/
|
9
|
+
@weight = [2, 7, 6, 5, 4, 3, 2]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def format_ie(number)
|
14
|
+
number.sub(/(\d{2})(\d{3})(\d{2})(\d{1})/, "\\1.\\2.\\3-\\4")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class RN < Base
|
6
|
+
include Commons::Mod11
|
7
|
+
|
8
|
+
private
|
9
|
+
def format_ie(number)
|
10
|
+
if number.gsub(/(\.)|(\-)/, "").length == 9
|
11
|
+
number.sub(/(\d{2})(\d{3})(\d{3})(\d{1})/, "\\1.\\2.\\3-\\4")
|
12
|
+
else
|
13
|
+
number.sub(/(\d{2})(\d{1})(\d{3})(\d{3})(\d{1})/, "\\1.\\2.\\3.\\4-\\5")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid_format?
|
18
|
+
valid_old_format or valid_new_format
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid_old_format
|
22
|
+
regex = /^(\d{2}\.\d{3}\.\d{3}\-\d{1}})$|^(\d{9})$/
|
23
|
+
regex.match(@number).present?
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_new_format
|
27
|
+
regex = /^(\d{2}\.\d{1}\.\d{3}\.\d{3}\-\d{1}})$|^(\d{10})$/
|
28
|
+
regex.match(@number).present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid_digital_check?
|
32
|
+
@number.gsub!(/\./, "")
|
33
|
+
|
34
|
+
weight = []
|
35
|
+
@number.length.downto(2).each {|w| weight << w }
|
36
|
+
|
37
|
+
@number[-1].eql? generate_digital_check(@number, weight).to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_digital_check(values, weights)
|
41
|
+
sum = reduce_weights(values, weights)
|
42
|
+
mod = sum * 10 % 11
|
43
|
+
mod == 10 ? 0 : mod
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class RO < Base
|
6
|
+
include Commons::Mod11
|
7
|
+
|
8
|
+
private
|
9
|
+
def format_ie(number)
|
10
|
+
if number.gsub(/(\.)|(\-)/, "").length == 9
|
11
|
+
number.sub(/(\d{3})(\d{5})(\d{1})/, "\\1.\\2-\\3")
|
12
|
+
else
|
13
|
+
number.sub(/(\d{13})(\d{1})/, "\\1-\\2")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid_format?
|
18
|
+
valid_old_format or valid_new_format
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid_old_format
|
22
|
+
regex = /^(\d{3}\.\d{5}\-\d{1})$|^(\d{9})$/
|
23
|
+
regex.match(@number).present?
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_new_format
|
27
|
+
regex = /^(\d{13}\-\d{1})$|^(\d{14})$/
|
28
|
+
regex.match(@number).present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid_digital_check?
|
32
|
+
valid_old_digital_check or valid_new_digital_check
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid_old_digital_check
|
36
|
+
weight = [3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
37
|
+
@number.gsub!(/\./, "")
|
38
|
+
@number[-1].eql? generate_digital_check(@number[-6, 6], weight).to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid_new_digital_check
|
42
|
+
weight = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
43
|
+
@number.gsub!(/\./, "")
|
44
|
+
@number[-1].eql? generate_digital_check(@number, weight).to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "pattern1"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class RR < Pattern1
|
6
|
+
def initialize(number)
|
7
|
+
super
|
8
|
+
@mask = /^(\d{8}\-\d{1})$|^(\d{9})$/
|
9
|
+
@weight = [1, 2, 3, 4, 5, 6, 7, 8]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def format_ie(number)
|
14
|
+
number.sub(/(\d{8})(\d{1})/, "\\1-\\2")
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_digital_check(values, weights)
|
18
|
+
sum = reduce_weights(values, weights)
|
19
|
+
sum % 9
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "pattern1"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class RS < Pattern1
|
6
|
+
def initialize(number)
|
7
|
+
super
|
8
|
+
@mask = /^(\d{3}\/\d{7})$|^(\d{10})$/
|
9
|
+
@weight = [2, 9, 8, 7, 6, 5, 4, 3, 2]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def format_ie(number)
|
14
|
+
number.sub(/(\d{3})(\d{7})/, "\\1/\\2")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "pattern1"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class SC < Pattern1
|
6
|
+
def initialize(number)
|
7
|
+
super
|
8
|
+
@mask = /^(\d{3}\.\d{3}\.\d{3})$|^(\d{9})$/
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def format_ie(number)
|
13
|
+
number.sub(/(\d{3})(\d{3})(\d{3})/, "\\1.\\2.\\3")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class SP < Base
|
6
|
+
include Commons::Mod11
|
7
|
+
|
8
|
+
private
|
9
|
+
def format_ie(number)
|
10
|
+
if number.gsub(/(\-)|(\.)|(\/)/, "").length == 13
|
11
|
+
number.sub(/(\w{1})(\d{8})(\d{1})(\d{3})/, "\\1-\\2.\\3/\\4")
|
12
|
+
else
|
13
|
+
number.sub(/(\d{3})(\d{3})(\d{3})(\d{3})/, "\\1.\\2.\\3.\\4")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid_format?
|
18
|
+
regex = /^(\d{3}\.\d{3}\.\d{3}\.\d{3})$|^(\d{12})$|^(P-\d{8}\.\d{1}\/\d{3})$/
|
19
|
+
regex.match(@number).present?
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_digital_check?
|
23
|
+
if @number[0].eql? "P"
|
24
|
+
valid_rural_producer_digital_check?
|
25
|
+
else
|
26
|
+
valid_standard_digital_check?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid_standard_digital_check?
|
31
|
+
@number.gsub!(/[\.\/P-]/, "")
|
32
|
+
|
33
|
+
weight1 = [1, 3, 4, 5, 6, 7, 8, 10]
|
34
|
+
weight2 = [3, 2, 10, 9, 8, 7, 6, 5, 4, 3, 2]
|
35
|
+
|
36
|
+
dc1 = generate_digital_check(weight1)
|
37
|
+
dc2 = generate_digital_check(weight2)
|
38
|
+
|
39
|
+
(@number[8] == dc1) and (@number[11] == dc2)
|
40
|
+
end
|
41
|
+
|
42
|
+
def valid_rural_producer_digital_check?
|
43
|
+
@number.gsub!(/[\.\/P-]/, "")
|
44
|
+
weight9 = [1, 3, 4, 5, 6, 7, 8, 10]
|
45
|
+
@number[8] == generate_digital_check(weight9)
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_digital_check(weights)
|
49
|
+
sum = reduce_weights(@number, weights)
|
50
|
+
mod = sum % 11
|
51
|
+
mod.to_s[-1]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "pattern1"
|
2
|
+
|
3
|
+
module BrDocuments
|
4
|
+
module IE
|
5
|
+
class TO < Pattern1
|
6
|
+
def initialize(number)
|
7
|
+
super
|
8
|
+
@mask = /^(\d{2}\.\d{2}\.\d{6}\-\d{1})$|^(\d{11})$/
|
9
|
+
@weight = [9, 8, 0, 0, 7, 6, 5, 4, 3, 2]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def format_ie(number)
|
14
|
+
number
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class IeValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each(record, attribute, value)
|
3
|
+
if ie_present?(value)
|
4
|
+
attribute_uf_was_configured_at_validator?(record, attribute) and
|
5
|
+
can_read_uf_at_record?(options, record, attribute) and
|
6
|
+
ie_valid?(record, attribute, value)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def ie_present?(value)
|
12
|
+
value.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
def attribute_uf_was_configured_at_validator?(record, attribute)
|
16
|
+
record.errors.add(:base,
|
17
|
+
I18n.t("validator.ie.uf.no_configured")) unless options[:uf].present?
|
18
|
+
record.errors.messages.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def can_read_uf_at_record?(options, record, attribute)
|
22
|
+
begin
|
23
|
+
read_uf(record)
|
24
|
+
rescue NoMethodError
|
25
|
+
record.errors.add(:base, I18n.t("validator.ie.uf.no_present",
|
26
|
+
uf: options[:uf])
|
27
|
+
)
|
28
|
+
end
|
29
|
+
record.errors.messages.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def ie_valid?(record, attribute, value)
|
33
|
+
begin
|
34
|
+
uf = read_uf(record)
|
35
|
+
ie = BrDocuments::IE::Factory.create(uf, value)
|
36
|
+
record.errors.add(attribute, :invalid) if not ie.valid?
|
37
|
+
rescue ArgumentError => ex
|
38
|
+
record.errors.add(attribute, ex.message)
|
39
|
+
end
|
40
|
+
record.errors.messages.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_uf(record)
|
44
|
+
attribute = record
|
45
|
+
options[:uf].split("#").each do | field |
|
46
|
+
attribute = attribute.send(field)
|
47
|
+
end
|
48
|
+
attribute
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe BrDocuments::CnpjCpf::Cnpj do
|
4
|
+
it "is invalid with malformed number" do
|
5
|
+
["242.2818/50001-54", "35.611.011/000192"].each do |number|
|
6
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new(number)
|
7
|
+
expect(cnpj).to_not be_valid
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is invalid with a number longer than 14" do
|
12
|
+
["24.228.185/0001-544", "936710360001881"].each do |number|
|
13
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new(number)
|
14
|
+
expect(cnpj).to_not be_valid
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is invalid with a number shorter than 14" do
|
19
|
+
["24.228.185/0001-5", "9367103600018"].each do |number|
|
20
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new(number)
|
21
|
+
expect(cnpj).to_not be_valid
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is invalid with a sequence of the same number" do
|
26
|
+
["11.111.111/1111-11", "22222222222222"].each do |number|
|
27
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new(number)
|
28
|
+
expect(cnpj).to_not be_valid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "is invalid with invalid check number" do
|
33
|
+
["04.001.155/0001-03", "85961757000101"].each do |number|
|
34
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new(number)
|
35
|
+
expect(cnpj).to_not be_valid
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "is valid with correct number" do
|
40
|
+
["04.001.155/0001-01", "85961757000102"].each do |number|
|
41
|
+
cnpj = BrDocuments::CnpjCpf::Cnpj.new(number)
|
42
|
+
expect(cnpj).to be_valid
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe BrDocuments::CnpjCpf::Cpf do
|
4
|
+
it "is invalid with malformed number" do
|
5
|
+
["111.126.491.07", "482.261.15-663", "111444.777-35"].each do |number|
|
6
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(number)
|
7
|
+
expect(cpf).to_not be_valid
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is invalid with a number longer than 11" do
|
12
|
+
["045.769.421-150", "308514217766"].each do |number|
|
13
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(number)
|
14
|
+
expect(cpf).to_not be_valid
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is invalid with a number shorter than 11" do
|
19
|
+
["111.444.777-3", "1234567890"].each do |number|
|
20
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(number)
|
21
|
+
expect(cpf).to_not be_valid
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is invalid with a sequence of the same number" do
|
26
|
+
["111.111.111-11", "22222222222"].each do |number|
|
27
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(number)
|
28
|
+
expect(cpf).to_not be_valid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "is invalid with invalid check number" do
|
33
|
+
["111.111.111-22", "2222222233"].each do |number|
|
34
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(number)
|
35
|
+
expect(cpf).to_not be_valid
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "is valid with correct number" do
|
40
|
+
["111.444.777-35", "01233254120"].each do |number|
|
41
|
+
cpf = BrDocuments::CnpjCpf::Cpf.new(number)
|
42
|
+
expect(cpf).to be_valid
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe CnpjValidator do
|
4
|
+
before(:each) do
|
5
|
+
@validator = CnpjValidator.new(attributes: "cnpj")
|
6
|
+
@mock = double("model")
|
7
|
+
@mock.stub(:errors).and_return([])
|
8
|
+
@mock.errors.stub(:messages).and_return({})
|
9
|
+
@mock.errors.stub(:add) do | attribute, error |
|
10
|
+
@mock.errors.messages[attribute] = [error]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
subject { @validator }
|
15
|
+
|
16
|
+
context "when Cnpj is valid" do
|
17
|
+
it "doesn't add errors in model" do
|
18
|
+
subject.validate_each(@mock, "cnpj", "85961757000102")
|
19
|
+
expect(@mock.errors.messages).to be_empty
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when Cnpj is blank" do
|
24
|
+
it "doesn't add errors in model" do
|
25
|
+
subject.validate_each(@mock, "cnpj", "")
|
26
|
+
expect(@mock.errors.messages).to be_empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when Cnpj is invalid" do
|
31
|
+
it "adds errors in model" do
|
32
|
+
subject.validate_each(@mock, "cnpj", "85961757000103")
|
33
|
+
expect(@mock.errors.messages).to_not be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|