cnpj-alfanumerico 0.1.4 → 0.1.5
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 +4 -4
- data/CHANGELOG.md +33 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/lib/cnpj/alfanumerico/version.rb +5 -0
- data/lib/cnpj/alfanumerico.rb +91 -0
- metadata +7 -4
- data/test/cnpj_alfanumerico_test.rb +0 -46
- data/test/test_helper.rb +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5174d975e12103d3b6bc60b68e3e0be63ceb56d0d58b914beb26c8e56f506d54
|
|
4
|
+
data.tar.gz: ff0dd2c5e4306d21541da9bbcf4c4579b89669c9331041f4b3215130fed1b20b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c571ca00452a58c0d519b9622e7b3b914db69a2874f01d359c4c88ab32b4fc0dcb9dbf50aca0402db5d78424a6a40cbf2ffdcae11f759ea6d582f48afcf58cb
|
|
7
|
+
data.tar.gz: 3df158439adbb6b9f73b01259afc1eab1dfe807d8a363f3ef99fbf3cb68108cb168e448bcc2bc0e10d137719bff4b6ca5e7c4ba11612de5121ab89ccc7e29455
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
- Corrige o empacotamento da gem para incluir os arquivos em `lib/cnpj/**`.
|
|
6
|
+
- Resolve o `LoadError` ao carregar a gem em projetos Rails e Ruby `3.4`.
|
|
7
|
+
|
|
8
|
+
## 0.1.4
|
|
9
|
+
|
|
10
|
+
- Passa a usar o environment `PROD` no workflow de publish para consumir `RUBYGEMS_AUTH_TOKEN` com escopo explícito.
|
|
11
|
+
- Alinha a próxima tag de release ao fluxo final de publicação automática no RubyGems.
|
|
12
|
+
|
|
13
|
+
## 0.1.3
|
|
14
|
+
|
|
15
|
+
- Atualiza os workflows do GitHub Actions para `actions/checkout@v5` e `ruby/setup-ruby@v1`.
|
|
16
|
+
- Corrige compatibilidade do CI com `ubuntu-24.04` e versões Ruby `3.3` e `3.4`.
|
|
17
|
+
- Mantém o fluxo de release baseado em tag com a infraestrutura de CI já corrigida.
|
|
18
|
+
|
|
19
|
+
## 0.1.2
|
|
20
|
+
|
|
21
|
+
- Simplifica a execução do CI para rodar testes sem depender de Bundler no GitHub Actions.
|
|
22
|
+
- Alinha a próxima tag de release com os workflows corrigidos de teste e publicação.
|
|
23
|
+
|
|
24
|
+
## 0.1.1
|
|
25
|
+
|
|
26
|
+
- Adiciona `Gemfile` para integração mais previsível com Bundler e GitHub Actions.
|
|
27
|
+
- Atualiza a matriz de CI para Ruby `2.7`, `3.0`, `3.2`, `3.3` e `3.4`.
|
|
28
|
+
- Ajusta o workflow de release para publicar apenas por tag de versão.
|
|
29
|
+
- Documenta suporte oficial às versões modernas do Ruby.
|
|
30
|
+
|
|
31
|
+
## 0.1.0
|
|
32
|
+
|
|
33
|
+
- Primeira versão com cálculo de DV, validação, geração e formatação de CNPJ numérico e alfanumérico.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Miguel C. Honorio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# cnpj-alfanumerico-ruby
|
|
2
|
+
|
|
3
|
+
Gem Ruby para validar, calcular, gerar e formatar CNPJ numérico e alfanumérico conforme as regras publicadas pela Receita Federal para vigência a partir de julho de 2026.
|
|
4
|
+
|
|
5
|
+
## Compatibilidade
|
|
6
|
+
|
|
7
|
+
- Ruby `2.7`
|
|
8
|
+
- Ruby `3.0`
|
|
9
|
+
- Ruby `3.2`
|
|
10
|
+
- Ruby `3.3`
|
|
11
|
+
- Ruby `3.4`
|
|
12
|
+
|
|
13
|
+
O projeto usa apenas recursos básicos da linguagem e mantém CI para versões modernas do Ruby MRI.
|
|
14
|
+
|
|
15
|
+
## Instalação
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gem install cnpj-alfanumerico
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Uso
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require "cnpj-alfanumerico"
|
|
25
|
+
|
|
26
|
+
Cnpj::Alfanumerico.calculate_check_digits("12ABC34501DE")
|
|
27
|
+
# "35"
|
|
28
|
+
|
|
29
|
+
Cnpj::Alfanumerico.generate("12ABC34501DE")
|
|
30
|
+
# "12ABC34501DE35"
|
|
31
|
+
|
|
32
|
+
Cnpj::Alfanumerico.format("12ABC34501DE35")
|
|
33
|
+
# "12.ABC.345/01DE-35"
|
|
34
|
+
|
|
35
|
+
Cnpj::Alfanumerico.valid?("12.ABC.345/01DE-35")
|
|
36
|
+
# true
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
- `Cnpj::Alfanumerico.normalize(value)`
|
|
42
|
+
- `Cnpj::Alfanumerico.char_value(char)`
|
|
43
|
+
- `Cnpj::Alfanumerico.calculate_check_digits(base12)`
|
|
44
|
+
- `Cnpj::Alfanumerico.generate(base12)`
|
|
45
|
+
- `Cnpj::Alfanumerico.valid?(cnpj)`
|
|
46
|
+
- `Cnpj::Alfanumerico.assert_valid!(cnpj)`
|
|
47
|
+
- `Cnpj::Alfanumerico.format(cnpj)`
|
|
48
|
+
- `Cnpj::Alfanumerico.formatted?(cnpj)`
|
|
49
|
+
- `Cnpj::Alfanumerico.split(cnpj)`
|
|
50
|
+
|
|
51
|
+
## CLI
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
exe/cnpj-alfanumerico validate 12.ABC.345/01DE-35
|
|
55
|
+
exe/cnpj-alfanumerico generate 12ABC34501DE
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Publicação
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
gem build cnpj-alfanumerico.gemspec
|
|
62
|
+
gem push cnpj-alfanumerico-0.1.5.gem
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Para release automatizada via GitHub Actions, publique uma tag no formato `vX.Y.Z` que corresponda exatamente a `Cnpj::Alfanumerico::VERSION`.
|
|
66
|
+
|
|
67
|
+
## Referências
|
|
68
|
+
|
|
69
|
+
- Receita Federal: projeto CNPJ alfanumérico
|
|
70
|
+
- Receita Federal: manual de cálculo do DV
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require_relative "alfanumerico/version"
|
|
2
|
+
|
|
3
|
+
module Cnpj
|
|
4
|
+
module Alfanumerico
|
|
5
|
+
BODY_LENGTH = 12
|
|
6
|
+
FULL_LENGTH = 14
|
|
7
|
+
FIRST_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze
|
|
8
|
+
SECOND_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze
|
|
9
|
+
BODY_PATTERN = /\A[0-9A-Z]{12}\z/.freeze
|
|
10
|
+
FULL_PATTERN = /\A[0-9A-Z]{12}[0-9]{2}\z/.freeze
|
|
11
|
+
FORMATTED_PATTERN = /\A([0-9A-Z]{2})([0-9A-Z]{3})([0-9A-Z]{3})([0-9A-Z]{4})([0-9]{2})\z/.freeze
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def normalize(value)
|
|
16
|
+
value.to_s.gsub(/[^0-9A-Za-z]/, "").upcase
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def formatted?(value)
|
|
20
|
+
/\A[0-9A-Z]{2}\.[0-9A-Z]{3}\.[0-9A-Z]{3}\/[0-9A-Z]{4}-[0-9]{2}\z/.match?(value.to_s.upcase)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def char_value(char)
|
|
24
|
+
code = char.to_s.upcase.ord
|
|
25
|
+
return code - 48 if code.between?(48, 57)
|
|
26
|
+
return code - 48 if code.between?(65, 90)
|
|
27
|
+
|
|
28
|
+
raise ArgumentError, "Invalid CNPJ character: #{char}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def calculate_check_digits(base)
|
|
32
|
+
normalized = normalize(base)
|
|
33
|
+
raise ArgumentError, "Base CNPJ must contain exactly 12 alphanumeric characters." unless BODY_PATTERN.match?(normalized)
|
|
34
|
+
|
|
35
|
+
first_digit = compute_digit(normalized, FIRST_WEIGHTS)
|
|
36
|
+
second_digit = compute_digit("#{normalized}#{first_digit}", SECOND_WEIGHTS)
|
|
37
|
+
|
|
38
|
+
"#{first_digit}#{second_digit}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def generate(base)
|
|
42
|
+
normalized = normalize(base)
|
|
43
|
+
"#{normalized}#{calculate_check_digits(normalized)}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def valid?(value)
|
|
47
|
+
normalized = normalize(value)
|
|
48
|
+
return false unless FULL_PATTERN.match?(normalized)
|
|
49
|
+
|
|
50
|
+
base = normalized[0, BODY_LENGTH]
|
|
51
|
+
dv = normalized[BODY_LENGTH, 2]
|
|
52
|
+
calculate_check_digits(base) == dv
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def assert_valid!(value)
|
|
56
|
+
normalized = normalize(value)
|
|
57
|
+
raise ArgumentError, "Invalid CNPJ." unless valid?(normalized)
|
|
58
|
+
|
|
59
|
+
normalized
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def format(value)
|
|
63
|
+
normalized = normalize(value)
|
|
64
|
+
raise ArgumentError, "CNPJ must contain 12 alphanumeric characters followed by 2 numeric check digits." unless FULL_PATTERN.match?(normalized)
|
|
65
|
+
|
|
66
|
+
match = FORMATTED_PATTERN.match(normalized)
|
|
67
|
+
"#{match[1]}.#{match[2]}.#{match[3]}/#{match[4]}-#{match[5]}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def split(value)
|
|
71
|
+
normalized = normalize(value)
|
|
72
|
+
raise ArgumentError, "Invalid CNPJ." unless FULL_PATTERN.match?(normalized)
|
|
73
|
+
|
|
74
|
+
{
|
|
75
|
+
raiz: normalized[0, 8],
|
|
76
|
+
ordem: normalized[8, 4],
|
|
77
|
+
dv: normalized[12, 2]
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def compute_digit(base, weights)
|
|
82
|
+
sum = base.chars.each_with_index.sum do |char, index|
|
|
83
|
+
char_value(char) * weights[index]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
remainder = sum % 11
|
|
87
|
+
remainder < 2 ? 0 : 11 - remainder
|
|
88
|
+
end
|
|
89
|
+
private_class_method :compute_digit
|
|
90
|
+
end
|
|
91
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cnpj-alfanumerico
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miguel C. Honorio
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -47,10 +47,13 @@ executables:
|
|
|
47
47
|
extensions: []
|
|
48
48
|
extra_rdoc_files: []
|
|
49
49
|
files:
|
|
50
|
+
- CHANGELOG.md
|
|
51
|
+
- LICENSE
|
|
52
|
+
- README.md
|
|
50
53
|
- exe/cnpj-alfanumerico
|
|
51
54
|
- lib/cnpj-alfanumerico.rb
|
|
52
|
-
-
|
|
53
|
-
-
|
|
55
|
+
- lib/cnpj/alfanumerico.rb
|
|
56
|
+
- lib/cnpj/alfanumerico/version.rb
|
|
54
57
|
homepage: https://github.com/miguelcarloshonorio/cpnj_ruby_2026
|
|
55
58
|
licenses:
|
|
56
59
|
- MIT
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require "test_helper"
|
|
2
|
-
|
|
3
|
-
class CnpjAlfanumericoTest < Minitest::Test
|
|
4
|
-
def test_normalizes_punctuation_and_lowercase
|
|
5
|
-
assert_equal "12ABC34501DE35", Cnpj::Alfanumerico.normalize("12.abc.345/01de-35")
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def test_maps_alphanumeric_values_using_ascii_minus_48
|
|
9
|
-
assert_equal 0, Cnpj::Alfanumerico.char_value("0")
|
|
10
|
-
assert_equal 9, Cnpj::Alfanumerico.char_value("9")
|
|
11
|
-
assert_equal 17, Cnpj::Alfanumerico.char_value("A")
|
|
12
|
-
assert_equal 42, Cnpj::Alfanumerico.char_value("Z")
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def test_calculates_official_receita_example
|
|
16
|
-
assert_equal "35", Cnpj::Alfanumerico.calculate_check_digits("12ABC34501DE")
|
|
17
|
-
assert_equal "12ABC34501DE35", Cnpj::Alfanumerico.generate("12ABC34501DE")
|
|
18
|
-
assert_equal "12.ABC.345/01DE-35", Cnpj::Alfanumerico.format("12ABC34501DE35")
|
|
19
|
-
assert Cnpj::Alfanumerico.valid?("12.ABC.345/01DE-35")
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def test_validates_legacy_numeric_cnpj
|
|
23
|
-
assert Cnpj::Alfanumerico.valid?("11.444.777/0001-61")
|
|
24
|
-
assert_equal "11.444.777/0001-61", Cnpj::Alfanumerico.format("11444777000161")
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def test_rejects_invalid_values
|
|
28
|
-
refute Cnpj::Alfanumerico.valid?("12.ABC.345/01DE-36")
|
|
29
|
-
refute Cnpj::Alfanumerico.valid?("12.ABC.345/01DE-3X")
|
|
30
|
-
assert_raises(ArgumentError) { Cnpj::Alfanumerico.calculate_check_digits("ABC") }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def test_splits_and_asserts_valid_cnpj
|
|
34
|
-
assert_equal(
|
|
35
|
-
{ raiz: "12ABC345", ordem: "01DE", dv: "35" },
|
|
36
|
-
Cnpj::Alfanumerico.split("12.ABC.345/01DE-35")
|
|
37
|
-
)
|
|
38
|
-
assert_equal "12ABC34501DE35", Cnpj::Alfanumerico.assert_valid!("12.ABC.345/01DE-35")
|
|
39
|
-
assert_raises(ArgumentError) { Cnpj::Alfanumerico.assert_valid!("12.ABC.345/01DE-36") }
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def test_detects_formatted_values
|
|
43
|
-
assert Cnpj::Alfanumerico.formatted?("12.ABC.345/01DE-35")
|
|
44
|
-
refute Cnpj::Alfanumerico.formatted?("12ABC34501DE35")
|
|
45
|
-
end
|
|
46
|
-
end
|
data/test/test_helper.rb
DELETED