cpf_cnpj 0.6.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7b0bd493ddd22ed0ebe7128fd0e8dc17c8ff15bfb1209300e1ce60ae03b2c6b
4
- data.tar.gz: c2f7a21d000907e8779790d8b72ce6177b58ddaa2fb0f369941d3e3d1989eae1
3
+ metadata.gz: af6460ddd8fccffc42d4f642c5a511c01f484a7ca7103d2d5cc4edcc23fbeae6
4
+ data.tar.gz: e314c5cf1b043811a0ed804a7634a64f5079e833160385768dd3cd113a02b2d6
5
5
  SHA512:
6
- metadata.gz: b58f3e8547dda2131b290a4db50c0c84da0ccaf266ebd241cef0d34e43eb935d0e31d1310185749f9a929d19db01136484d1b54bbb1abb9c41d351409c6b685b
7
- data.tar.gz: 3d62c15ab2f3b0be301a55a5328368bcca1ccf1d2b453c3e28c01fa868dc10c403690b2ee2d33cd0bba375271a8a20b2415a77f477d3c3d2b941fad4049f8417
6
+ metadata.gz: 9389e3356414b201c0bd9eeb1eef63e07c1bf869a1fd1fa30c3ef90d105711f466343f3cef8a7ea8899bbdfdfa4586725f10c67022bd7325ee39a8519668f8f2
7
+ data.tar.gz: 41c4f3ee6632bc631070ae5879506d4ed78711aa6bb645302aa9b5bf8c9d235e7bdde042268ffe4b3fa412c43434cac00fae03a9dde9fd212609750cfe735495
data/README.md CHANGED
@@ -36,6 +36,12 @@ Or install it yourself as:
36
36
  This library has the same API for both CNPJ/CPF, so only one of them is
37
37
  documented below.
38
38
 
39
+ > [!NOTE]
40
+ >
41
+ > This library already supports the new alphanumeric CNPJ algorithm that will be
42
+ > available starting July 2026. For more information, see
43
+ > <https://www.gov.br/receitafederal/pt-br/acesso-a-informacao/acoes-e-programas/programas-e-atividades/cnpj-alfanumerico>.
44
+
39
45
  ```ruby
40
46
  require "cpf_cnpj"
41
47
 
@@ -3,11 +3,13 @@
3
3
  class CNPJ
4
4
  class Formatter
5
5
  STRICT_REGEX = %r{[/.-]}.freeze
6
- LOOSE_REGEX = /[^\d]/.freeze
6
+ LOOSE_REGEX = /[^A-Z\d]/.freeze
7
+ REPLACE_REGEX = /
8
+ \A([A-Z\d]{2})([A-Z\d]{3})([A-Z\d]{3})([A-Z\d]{4})([A-Z\d]{2})\Z
9
+ /x.freeze
7
10
 
8
11
  def self.format(number)
9
- strip(number)
10
- .gsub(/\A(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})\Z/, "\\1.\\2.\\3/\\4-\\5")
12
+ strip(number).gsub(REPLACE_REGEX, "\\1.\\2.\\3/\\4-\\5")
11
13
  end
12
14
 
13
15
  def self.strip(number, strict = false)
data/lib/cnpj.rb CHANGED
@@ -7,8 +7,8 @@ class CNPJ
7
7
 
8
8
  attr_reader :number, :strict
9
9
 
10
- REGEX = %r[\A\d{2}\.\d{3}.\d{3}/\d{4}-\d{2}\Z].freeze
11
- VALIDATION_SIZE_REGEX = /^\d{14}$/.freeze
10
+ REGEX = %r[\A[\dA-Z]{2}\.[\dA-Z]{3}.[\dA-Z]{3}/[\dA-Z]{4}-[\dA-Z]{2}\Z].freeze
11
+ VALIDATION_SIZE_REGEX = /^[A-Z\d]{14}$/.freeze
12
12
  NUMBER_SIZE = 12
13
13
 
14
14
  DENYLIST = %w[
@@ -33,13 +33,18 @@ class CNPJ
33
33
  end
34
34
 
35
35
  def self.generate(formatted = false)
36
- number = CpfCnpj::Generator.generate(NUMBER_SIZE, VerifierDigit)
37
- cnpj = new(number)
36
+ numbers = Array("0".."9") + ("A".."Z").to_a
37
+ digits = Array.new(NUMBER_SIZE) { numbers.sample }
38
+ numeric_digits = digits.map {|d| d.ord - 48 }
39
+ numeric_digits << VerifierDigit.generate(numeric_digits)
40
+ numeric_digits << VerifierDigit.generate(numeric_digits)
41
+
42
+ cnpj = new((digits + numeric_digits[-2, 2]).join)
38
43
  formatted ? cnpj.formatted : cnpj.stripped
39
44
  end
40
45
 
41
46
  def initialize(number, strict = false)
42
- @number = number.to_s
47
+ @number = number.to_s.upcase
43
48
  @strict = strict
44
49
  end
45
50
 
@@ -64,6 +69,7 @@ class CNPJ
64
69
  end
65
70
 
66
71
  return false unless stripped.match?(VALIDATION_SIZE_REGEX)
72
+
67
73
  return false if DENYLIST.include?(stripped)
68
74
 
69
75
  digits = numbers[0...NUMBER_SIZE]
@@ -79,10 +85,16 @@ class CNPJ
79
85
  alias eql? ==
80
86
 
81
87
  def number_without_verifier
82
- numbers[0...NUMBER_SIZE].join
88
+ stripped_chars[0...NUMBER_SIZE].join
89
+ end
90
+
91
+ private def stripped_chars
92
+ @stripped_chars ||= stripped.chars
83
93
  end
84
94
 
85
95
  private def numbers
86
- @numbers ||= stripped.each_char.to_a.map(&:to_i)
96
+ @numbers ||= stripped_chars.map do |number|
97
+ number.ord - 48
98
+ end
87
99
  end
88
100
  end
data/lib/cpf.rb CHANGED
@@ -34,8 +34,12 @@ class CPF
34
34
  end
35
35
 
36
36
  def self.generate(formatted = false)
37
- number = CpfCnpj::Generator.generate(NUMBER_SIZE, VerifierDigit)
38
- cpf = new(number)
37
+ numbers = Array(0..9)
38
+ digits = Array.new(NUMBER_SIZE) { numbers.sample }
39
+ digits << VerifierDigit.generate(digits)
40
+ digits << VerifierDigit.generate(digits)
41
+
42
+ cpf = new(digits.join)
39
43
  formatted ? cpf.formatted : cpf.stripped
40
44
  end
41
45
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CpfCnpj
4
- VERSION = "0.6.0"
4
+ VERSION = "1.0.0"
5
5
  end
6
6
 
7
7
  class CPF
data/lib/cpf_cnpj.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "English"
4
4
  require "optparse"
5
- require "cpf_cnpj/generator"
6
5
  require "cpf_cnpj/cli"
7
6
  require "cpf_cnpj/version"
8
7
  require "cpf"
@@ -72,7 +72,7 @@ module CNPJCli
72
72
  exit_status, stdout = run_command(["-gs"])
73
73
 
74
74
  assert_equal 0, exit_status
75
- assert_match(/\A\d{14}\Z/, stdout)
75
+ assert_match(/\A[A-Z\d]{14}\Z/, stdout)
76
76
  end
77
77
  end
78
78
 
data/test/cnpj_test.rb CHANGED
@@ -30,6 +30,18 @@ class CnpjTest < Minitest::Test
30
30
  assert CNPJ.valid?(number)
31
31
  end
32
32
 
33
+ test "validates formatted strings with letters" do
34
+ number = "12.ABC.345/01DE-35"
35
+
36
+ assert CNPJ.valid?(number)
37
+ end
38
+
39
+ test "validates formatted strings with letters (lowercase)" do
40
+ number = "12.abc.345/01de-35"
41
+
42
+ assert CNPJ.valid?(number)
43
+ end
44
+
33
45
  test "formats number" do
34
46
  cnpj = CNPJ.new("54550752000155")
35
47
 
@@ -50,14 +62,17 @@ class CnpjTest < Minitest::Test
50
62
  end
51
63
 
52
64
  test "generates formatted number" do
53
- assert_match %r[\A\d{2}\.\d{3}\.\d{3}/\d{4}-\d{2}\z], CNPJ.generate(true)
65
+ assert_match(
66
+ %r[\A[A-Z\d]{2}\.[A-Z\d]{3}\.[A-Z\d]{3}/[A-Z\d]{4}-[A-Z\d]{2}\z],
67
+ CNPJ.generate(true)
68
+ )
54
69
  end
55
70
 
56
71
  test "generates stripped number" do
57
- assert_match(/\A\d{14}\z/, CNPJ.generate)
72
+ assert_match(/\A[A-Z\d]{14}\z/, CNPJ.generate)
58
73
  end
59
74
 
60
- test "rejects strings" do
75
+ test "rejects invalid strings" do
61
76
  refute CNPJ.valid?("aa.bb.ccc/dddd-ee")
62
77
  end
63
78
 
@@ -66,6 +81,8 @@ class CnpjTest < Minitest::Test
66
81
  refute CNPJ.valid?("54....550....752///0001---55", strict: true)
67
82
  assert CNPJ.valid?("54.550.752/0001-55", strict: true)
68
83
  assert CNPJ.valid?("54550752000155", strict: true)
84
+ assert CNPJ.valid?("12.ABC.345/01DE-35", strict: true)
85
+ assert CNPJ.valid?("12ABC34501DE35", strict: true)
69
86
  end
70
87
 
71
88
  test "compare objects by their numeric value" do
@@ -80,8 +97,9 @@ class CnpjTest < Minitest::Test
80
97
  end
81
98
 
82
99
  test "returns number without verifier" do
83
- cnpj = CNPJ.new("54550752000155")
84
-
85
- assert_equal "545507520001", cnpj.number_without_verifier
100
+ assert_equal "545507520001",
101
+ CNPJ.new("54550752000155").number_without_verifier
102
+ assert_equal "12ABC34501DE",
103
+ CNPJ.new("12.ABC.345/01DE-35").number_without_verifier
86
104
  end
87
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpf_cnpj
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
@@ -110,7 +110,6 @@ files:
110
110
  - lib/cpf/verifier_digit.rb
111
111
  - lib/cpf_cnpj.rb
112
112
  - lib/cpf_cnpj/cli.rb
113
- - lib/cpf_cnpj/generator.rb
114
113
  - lib/cpf_cnpj/version.rb
115
114
  - test/cnpj/cli_test.rb
116
115
  - test/cnpj/formatter_test.rb
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CpfCnpj
4
- class Generator
5
- NUMBERS = Array(0..9).freeze
6
-
7
- def self.generate(size, verifier_digit_generator)
8
- numbers = Array.new(size) { NUMBERS.sample }
9
- numbers << verifier_digit_generator.generate(numbers)
10
- numbers << verifier_digit_generator.generate(numbers)
11
- numbers.join
12
- end
13
- end
14
- end