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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +4 -0
  5. data/README.md +146 -0
  6. data/Rakefile +1 -0
  7. data/br_documents.gemspec +30 -0
  8. data/config/locales/pt-BR.yml +8 -0
  9. data/lib/br_documents.rb +4 -0
  10. data/lib/br_documents/cnpj_cpf/cnpj.rb +21 -0
  11. data/lib/br_documents/cnpj_cpf/cpf.rb +21 -0
  12. data/lib/br_documents/cnpj_cpf/document.rb +35 -0
  13. data/lib/br_documents/cnpj_validator.rb +8 -0
  14. data/lib/br_documents/commons/mod11.rb +20 -0
  15. data/lib/br_documents/cpf_validator.rb +8 -0
  16. data/lib/br_documents/ie/ac.rb +17 -0
  17. data/lib/br_documents/ie/al.rb +17 -0
  18. data/lib/br_documents/ie/am.rb +17 -0
  19. data/lib/br_documents/ie/ap.rb +52 -0
  20. data/lib/br_documents/ie/ba.rb +75 -0
  21. data/lib/br_documents/ie/base.rb +17 -0
  22. data/lib/br_documents/ie/ce.rb +12 -0
  23. data/lib/br_documents/ie/df.rb +17 -0
  24. data/lib/br_documents/ie/es.rb +12 -0
  25. data/lib/br_documents/ie/factory.rb +12 -0
  26. data/lib/br_documents/ie/go.rb +17 -0
  27. data/lib/br_documents/ie/ma.rb +12 -0
  28. data/lib/br_documents/ie/mg.rb +53 -0
  29. data/lib/br_documents/ie/ms.rb +12 -0
  30. data/lib/br_documents/ie/mt.rb +18 -0
  31. data/lib/br_documents/ie/pa.rb +17 -0
  32. data/lib/br_documents/ie/pattern1.rb +26 -0
  33. data/lib/br_documents/ie/pattern2.rb +30 -0
  34. data/lib/br_documents/ie/pb.rb +12 -0
  35. data/lib/br_documents/ie/pe.rb +51 -0
  36. data/lib/br_documents/ie/pi.rb +12 -0
  37. data/lib/br_documents/ie/pr.rb +19 -0
  38. data/lib/br_documents/ie/rj.rb +18 -0
  39. data/lib/br_documents/ie/rn.rb +47 -0
  40. data/lib/br_documents/ie/ro.rb +49 -0
  41. data/lib/br_documents/ie/rr.rb +23 -0
  42. data/lib/br_documents/ie/rs.rb +18 -0
  43. data/lib/br_documents/ie/sc.rb +17 -0
  44. data/lib/br_documents/ie/se.rb +12 -0
  45. data/lib/br_documents/ie/sp.rb +55 -0
  46. data/lib/br_documents/ie/to.rb +18 -0
  47. data/lib/br_documents/ie_validator.rb +50 -0
  48. data/lib/br_documents/version.rb +3 -0
  49. data/spec/cnpj_cpf/cnpj_spec.rb +45 -0
  50. data/spec/cnpj_cpf/cpf_spec.rb +45 -0
  51. data/spec/cnpj_validator_spec.rb +36 -0
  52. data/spec/cpf_validator_spec.rb +36 -0
  53. data/spec/ie/ac_spec.rb +40 -0
  54. data/spec/ie/al_spec.rb +33 -0
  55. data/spec/ie/am_spec.rb +40 -0
  56. data/spec/ie/ap_spec.rb +33 -0
  57. data/spec/ie/ba_spec.rb +63 -0
  58. data/spec/ie/ce_spec.rb +13 -0
  59. data/spec/ie/df_spec.rb +40 -0
  60. data/spec/ie/es_spec.rb +13 -0
  61. data/spec/ie/factory_spec.rb +203 -0
  62. data/spec/ie/go_spec.rb +40 -0
  63. data/spec/ie/ma_spec.rb +13 -0
  64. data/spec/ie/mg_spec.rb +40 -0
  65. data/spec/ie/ms_spec.rb +13 -0
  66. data/spec/ie/mt_spec.rb +40 -0
  67. data/spec/ie/pa_spec.rb +40 -0
  68. data/spec/ie/pb_spec.rb +13 -0
  69. data/spec/ie/pe_spec.rb +59 -0
  70. data/spec/ie/pi_spec.rb +13 -0
  71. data/spec/ie/pr_spec.rb +33 -0
  72. data/spec/ie/rj_spec.rb +40 -0
  73. data/spec/ie/rn_spec.rb +59 -0
  74. data/spec/ie/ro_spec.rb +59 -0
  75. data/spec/ie/rr_spec.rb +40 -0
  76. data/spec/ie/rs_spec.rb +38 -0
  77. data/spec/ie/sc_spec.rb +40 -0
  78. data/spec/ie/se_spec.rb +13 -0
  79. data/spec/ie/shared_examples_for_pattern1.rb +33 -0
  80. data/spec/ie/sp_spec.rb +42 -0
  81. data/spec/ie/to_spec.rb +40 -0
  82. data/spec/ie_validator_spec.rb +65 -0
  83. data/spec/spec_helper.rb +21 -0
  84. data/spec/support/utilities.rb +3 -0
  85. 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,12 @@
1
+ require_relative "pattern1"
2
+
3
+ module BrDocuments
4
+ module IE
5
+ class SE < Pattern1
6
+ private
7
+ def format_ie(number)
8
+ number.sub(/(\d{8})(\d{1})/, "\\1-\\2")
9
+ end
10
+ end
11
+ end
12
+ 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,3 @@
1
+ module BrDocuments
2
+ VERSION = "0.0.2"
3
+ 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