br_documents 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|