br_documents 0.0.2

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