br-utils 0.1.0 → 0.2.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +27 -0
  3. data/README.md +446 -22
  4. data/lib/brazilian-utils/area-code-utils.rb +60 -0
  5. data/lib/brazilian-utils/bank-account-utils.rb +82 -0
  6. data/lib/brazilian-utils/bank-utils.rb +61 -0
  7. data/lib/brazilian-utils/boleto-utils.rb +139 -0
  8. data/lib/brazilian-utils/caepf-utils.rb +91 -0
  9. data/lib/brazilian-utils/cbo-utils.rb +74 -0
  10. data/lib/brazilian-utils/cei-utils.rb +79 -0
  11. data/lib/brazilian-utils/cep-utils.rb +34 -1
  12. data/lib/brazilian-utils/certidao-utils.rb +171 -0
  13. data/lib/brazilian-utils/cfop-utils.rb +74 -0
  14. data/lib/brazilian-utils/cnae-utils.rb +104 -0
  15. data/lib/brazilian-utils/cnh-utils.rb +68 -15
  16. data/lib/brazilian-utils/cno-utils.rb +76 -0
  17. data/lib/brazilian-utils/cnpj-utils.rb +126 -13
  18. data/lib/brazilian-utils/cns-utils.rb +110 -0
  19. data/lib/brazilian-utils/cpf-utils.rb +14 -1
  20. data/lib/brazilian-utils/credit-card-utils.rb +47 -0
  21. data/lib/brazilian-utils/csosn-utils.rb +55 -0
  22. data/lib/brazilian-utils/cst-utils.rb +103 -0
  23. data/lib/brazilian-utils/currency-utils.rb +347 -226
  24. data/lib/brazilian-utils/data/area_codes.json +676 -0
  25. data/lib/brazilian-utils/data/banks.json +357 -0
  26. data/lib/brazilian-utils/data/cbo.json +1 -0
  27. data/lib/brazilian-utils/data/cfop.json +1 -0
  28. data/lib/brazilian-utils/data/cnae.json +1 -0
  29. data/lib/brazilian-utils/data/csosn.json +42 -0
  30. data/lib/brazilian-utils/data/cst.json +294 -0
  31. data/lib/brazilian-utils/data/legal_nature.json +900 -0
  32. data/lib/brazilian-utils/data/municipalities.json +1 -0
  33. data/lib/brazilian-utils/data/ncm.json +1 -0
  34. data/lib/brazilian-utils/data/states.json +218 -0
  35. data/lib/brazilian-utils/date-utils.rb +504 -244
  36. data/lib/brazilian-utils/email-utils.rb +20 -9
  37. data/lib/brazilian-utils/iban-utils.rb +120 -0
  38. data/lib/brazilian-utils/ie-utils.rb +84 -0
  39. data/lib/brazilian-utils/legal-nature-utils.rb +238 -235
  40. data/lib/brazilian-utils/legal-process-utils.rb +35 -5
  41. data/lib/brazilian-utils/license-plate-utils.rb +24 -4
  42. data/lib/brazilian-utils/municipality-utils.rb +58 -0
  43. data/lib/brazilian-utils/ncm-utils.rb +91 -0
  44. data/lib/brazilian-utils/nfe-key-utils.rb +158 -0
  45. data/lib/brazilian-utils/number-utils.rb +123 -0
  46. data/lib/brazilian-utils/passport-utils.rb +65 -0
  47. data/lib/brazilian-utils/phone-utils.rb +491 -272
  48. data/lib/brazilian-utils/pis-utils.rb +16 -1
  49. data/lib/brazilian-utils/pix-key-utils.rb +70 -0
  50. data/lib/brazilian-utils/pix-payload-utils.rb +253 -0
  51. data/lib/brazilian-utils/registro-profissional-utils.rb +112 -0
  52. data/lib/brazilian-utils/renavam-utils.rb +14 -0
  53. data/lib/brazilian-utils/state-utils.rb +105 -0
  54. data/lib/brazilian-utils/text-utils.rb +105 -0
  55. data/lib/brazilian-utils/vin-utils.rb +46 -0
  56. data/lib/brazilian-utils/voter-id-utils.rb +70 -19
  57. metadata +54 -2
  58. data/.travis.yml +0 -5
@@ -0,0 +1,46 @@
1
+ module BrazilianUtils
2
+ # Utilities for validating a VIN (chassi) structurally: 17 characters,
3
+ # none of the excluded letters `I`, `O`, `Q`, and the check digit at
4
+ # position 9 (the North American / ISO 3779 rule).
5
+ #
6
+ # Brazilian rules do not mandate the check digit, so many Brazilian-built
7
+ # VINs fail it; this validates structure only, as the contract does.
8
+ module VINUtils
9
+ TRANSLITERATION = {
10
+ 'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8,
11
+ 'J' => 1, 'K' => 2, 'L' => 3, 'M' => 4, 'N' => 5, 'P' => 7, 'R' => 9,
12
+ 'S' => 2, 'T' => 3, 'U' => 4, 'V' => 5, 'W' => 6, 'X' => 7, 'Y' => 8, 'Z' => 9
13
+ }.freeze
14
+
15
+ WEIGHTS = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2].freeze
16
+
17
+ EXCLUDED_LETTERS = %w[I O Q].freeze
18
+
19
+ # Validates a VIN structurally.
20
+ #
21
+ # @param value [String] Case-insensitive.
22
+ # @return [Boolean]
23
+ def self.is_valid(value)
24
+ return false unless value.is_a?(String)
25
+
26
+ vin = value.strip.upcase
27
+ return false unless vin.length == 17
28
+ return false unless vin.match?(/\A[A-Z0-9]{17}\z/)
29
+ return false if EXCLUDED_LETTERS.any? { |l| vin.include?(l) }
30
+ return false if vin.chars.uniq.length == 1
31
+
32
+ values = vin.chars.map { |c| c.match?(/\d/) ? c.to_i : TRANSLITERATION[c] }
33
+ return false if values.include?(nil)
34
+
35
+ sum = values.each_with_index.sum { |v, i| v * WEIGHTS[i] }
36
+ remainder = sum % 11
37
+ check_char = remainder == 10 ? 'X' : remainder.to_s
38
+
39
+ vin[8] == check_char
40
+ end
41
+
42
+ class << self
43
+ alias valid? is_valid
44
+ end
45
+ end
46
+ end
@@ -13,13 +13,11 @@ module BrazilianUtils
13
13
  'AP' => '25', 'RR' => '26', 'TO' => '27', 'ZZ' => '28'
14
14
  }.freeze
15
15
 
16
- module_function
17
-
18
16
  # Check if a Brazilian voter ID number is valid.
19
17
  #
20
18
  # @param voter_id [String] The voter ID to validate
21
19
  # @return [Boolean] true if valid, false otherwise
22
- def is_valid_voter_id(voter_id)
20
+ def self.is_valid_voter_id(voter_id)
23
21
  # Ensure voter_id is a string with only digits and valid length
24
22
  return false unless voter_id.is_a?(String)
25
23
  return false unless voter_id.match?(/^\d+$/)
@@ -44,27 +42,37 @@ module BrazilianUtils
44
42
  true
45
43
  end
46
44
 
47
- # Alias for is_valid_voter_id
48
- alias valid_voter_id? is_valid_voter_id
45
+ class << self
46
+ # Alias for is_valid_voter_id
47
+ alias valid_voter_id? is_valid_voter_id
48
+ end
49
49
 
50
50
  # Format a voter ID for display with visual spaces.
51
51
  #
52
52
  # @param voter_id [String] The voter ID to format
53
53
  # @return [String, nil] Formatted voter ID or nil if invalid
54
- def format_voter_id(voter_id)
54
+ def self.format_voter_id(voter_id)
55
55
  return nil unless is_valid_voter_id(voter_id)
56
56
 
57
- "#{voter_id[0..3]} #{voter_id[4..7]} #{voter_id[8..9]} #{voter_id[10..11]}"
57
+ # The 13-digit SP/MG variant has an extra sequential digit; grouping it
58
+ # as 4+4+2+2 (like the 12-digit case) silently drops the last digit.
59
+ if voter_id.length == 13
60
+ "#{voter_id[0..3]} #{voter_id[4..7]} #{voter_id[8]} #{voter_id[9..10]} #{voter_id[11..12]}"
61
+ else
62
+ "#{voter_id[0..3]} #{voter_id[4..7]} #{voter_id[8..9]} #{voter_id[10..11]}"
63
+ end
58
64
  end
59
65
 
60
- # Alias for format_voter_id
61
- alias format format_voter_id
66
+ class << self
67
+ # Alias for format_voter_id
68
+ alias format format_voter_id
69
+ end
62
70
 
63
71
  # Generate a random valid Brazilian voter ID.
64
72
  #
65
73
  # @param federative_union [String] The UF code (e.g., "SP", "MG", "ZZ")
66
74
  # @return [String, nil] A valid voter ID or nil if UF is invalid
67
- def generate(federative_union = 'ZZ')
75
+ def self.generate(federative_union = 'ZZ')
68
76
  federative_union = federative_union.upcase
69
77
  return nil unless UF_CODES.key?(federative_union)
70
78
 
@@ -72,7 +80,9 @@ module BrazilianUtils
72
80
  return nil unless is_federative_union_valid?(uf_number)
73
81
 
74
82
  # Generate random 8-digit sequential number
75
- sequential_number = format('%08d', rand(0..99_999_999))
83
+ # (uses rjust, not Kernel#format, since `format` is aliased to
84
+ # format_voter_id on this module's singleton class below)
85
+ sequential_number = rand(0..99_999_999).to_s.rjust(8, '0')
76
86
 
77
87
  # Calculate verification digits
78
88
  vd1 = calculate_vd1(sequential_number, uf_number)
@@ -81,11 +91,12 @@ module BrazilianUtils
81
91
  "#{sequential_number}#{uf_number}#{vd1}#{vd2}"
82
92
  end
83
93
 
84
- private
94
+ # PRIVATE METHODS
95
+ #################
85
96
 
86
97
  # Check if the length of the voter ID is valid.
87
98
  # Typically 12 digits, but can be 13 for SP and MG (edge case).
88
- def is_length_valid?(voter_id)
99
+ def self.is_length_valid?(voter_id)
89
100
  return true if voter_id.length == 12
90
101
 
91
102
  # Edge case: SP and MG can have 13 digits
@@ -94,22 +105,22 @@ module BrazilianUtils
94
105
  end
95
106
 
96
107
  # Extract the sequential number (first 8 digits).
97
- def get_sequential_number(voter_id)
108
+ def self.get_sequential_number(voter_id)
98
109
  voter_id[0..7]
99
110
  end
100
111
 
101
112
  # Extract the federative union (2 digits before last 2 digits).
102
- def get_federative_union(voter_id)
113
+ def self.get_federative_union(voter_id)
103
114
  voter_id[-4..-3]
104
115
  end
105
116
 
106
117
  # Extract the verifying digits (last 2 digits).
107
- def get_verifying_digits(voter_id)
118
+ def self.get_verifying_digits(voter_id)
108
119
  voter_id[-2..-1]
109
120
  end
110
121
 
111
122
  # Check if the federative union is valid (between '01' and '28').
112
- def is_federative_union_valid?(federative_union)
123
+ def self.is_federative_union_valid?(federative_union)
113
124
  num = federative_union.to_i
114
125
  num >= 1 && num <= 28
115
126
  end
@@ -119,7 +130,7 @@ module BrazilianUtils
119
130
  # @param sequential_number [String] First 8 digits
120
131
  # @param federative_union [String] 2-digit UF code
121
132
  # @return [Integer] The first verification digit
122
- def calculate_vd1(sequential_number, federative_union)
133
+ def self.calculate_vd1(sequential_number, federative_union)
123
134
  # Weights: 2, 3, 4, 5, 6, 7, 8, 9
124
135
  weights = (2..9).to_a
125
136
 
@@ -144,7 +155,7 @@ module BrazilianUtils
144
155
  # @param federative_union [String] 2-digit UF code
145
156
  # @param vd1 [Integer] First verification digit
146
157
  # @return [Integer] The second verification digit
147
- def calculate_vd2(federative_union, vd1)
158
+ def self.calculate_vd2(federative_union, vd1)
148
159
  # Weights: 7, 8, 9
149
160
  sum = (federative_union[0].to_i * 7) +
150
161
  (federative_union[1].to_i * 8) +
@@ -161,5 +172,45 @@ module BrazilianUtils
161
172
 
162
173
  vd2
163
174
  end
175
+
176
+ private_class_method :is_length_valid?, :get_sequential_number, :get_federative_union,
177
+ :get_verifying_digits, :is_federative_union_valid?, :calculate_vd1,
178
+ :calculate_vd2
179
+
180
+ # Removes the voter ID formatting symbols (spaces), keeping everything else.
181
+ #
182
+ # @param value [String] A voter ID, with or without spacing.
183
+ # @return [String] The value with spaces removed.
184
+ #
185
+ # @example
186
+ # remove_symbols("1234 5678 01 24") #=> "123456780124"
187
+ def self.remove_symbols(value)
188
+ return '' unless value.is_a?(String)
189
+
190
+ value.gsub(/\s/, '')
191
+ end
192
+
193
+ # Removes voter ID formatting and keeps only digits, capped to 12 digits
194
+ # (13 when the UF portion is SP or MG).
195
+ #
196
+ # @param value [String, Integer] A voter ID, with or without formatting.
197
+ # @return [String] The parsed digits.
198
+ #
199
+ # @example
200
+ # parse("1234 5678 01 24") #=> "123456780124"
201
+ # parse("1234 5678 8 01 91") #=> "1234567880191" (13-digit SP/MG form)
202
+ def self.parse(value)
203
+ return '' unless value.is_a?(String) || value.is_a?(Integer)
204
+
205
+ digits = value.to_s.gsub(/\D/, '')
206
+ return '' if digits.empty?
207
+
208
+ if digits.length > 12
209
+ candidate = digits[0, 13]
210
+ return candidate if candidate.length == 13 && %w[01 02].include?(candidate[-4..-3])
211
+ end
212
+
213
+ digits[0, 12]
214
+ end
164
215
  end
165
216
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: br-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rocha
@@ -10,6 +10,20 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 1980-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -61,9 +75,9 @@ executables: []
61
75
  extensions: []
62
76
  extra_rdoc_files: []
63
77
  files:
78
+ - ".github/workflows/ci.yml"
64
79
  - ".gitignore"
65
80
  - ".rspec"
66
- - ".travis.yml"
67
81
  - Gemfile
68
82
  - LICENSE.txt
69
83
  - README.md
@@ -83,21 +97,59 @@ files:
83
97
  - examples/pis_usage_example.rb
84
98
  - examples/renavam_usage_example.rb
85
99
  - examples/voter_id_usage_example.rb
100
+ - lib/brazilian-utils/area-code-utils.rb
101
+ - lib/brazilian-utils/bank-account-utils.rb
102
+ - lib/brazilian-utils/bank-utils.rb
86
103
  - lib/brazilian-utils/boleto-utils.rb
104
+ - lib/brazilian-utils/caepf-utils.rb
105
+ - lib/brazilian-utils/cbo-utils.rb
106
+ - lib/brazilian-utils/cei-utils.rb
87
107
  - lib/brazilian-utils/cep-utils.rb
108
+ - lib/brazilian-utils/certidao-utils.rb
109
+ - lib/brazilian-utils/cfop-utils.rb
110
+ - lib/brazilian-utils/cnae-utils.rb
88
111
  - lib/brazilian-utils/cnh-utils.rb
112
+ - lib/brazilian-utils/cno-utils.rb
89
113
  - lib/brazilian-utils/cnpj-utils.rb
114
+ - lib/brazilian-utils/cns-utils.rb
90
115
  - lib/brazilian-utils/cpf-utils.rb
116
+ - lib/brazilian-utils/credit-card-utils.rb
117
+ - lib/brazilian-utils/csosn-utils.rb
118
+ - lib/brazilian-utils/cst-utils.rb
91
119
  - lib/brazilian-utils/currency-utils.rb
120
+ - lib/brazilian-utils/data/area_codes.json
121
+ - lib/brazilian-utils/data/banks.json
122
+ - lib/brazilian-utils/data/cbo.json
123
+ - lib/brazilian-utils/data/cfop.json
124
+ - lib/brazilian-utils/data/cnae.json
125
+ - lib/brazilian-utils/data/csosn.json
126
+ - lib/brazilian-utils/data/cst.json
127
+ - lib/brazilian-utils/data/legal_nature.json
92
128
  - lib/brazilian-utils/data/legal_process_ids.json
129
+ - lib/brazilian-utils/data/municipalities.json
130
+ - lib/brazilian-utils/data/ncm.json
131
+ - lib/brazilian-utils/data/states.json
93
132
  - lib/brazilian-utils/date-utils.rb
94
133
  - lib/brazilian-utils/email-utils.rb
134
+ - lib/brazilian-utils/iban-utils.rb
135
+ - lib/brazilian-utils/ie-utils.rb
95
136
  - lib/brazilian-utils/legal-nature-utils.rb
96
137
  - lib/brazilian-utils/legal-process-utils.rb
97
138
  - lib/brazilian-utils/license-plate-utils.rb
139
+ - lib/brazilian-utils/municipality-utils.rb
140
+ - lib/brazilian-utils/ncm-utils.rb
141
+ - lib/brazilian-utils/nfe-key-utils.rb
142
+ - lib/brazilian-utils/number-utils.rb
143
+ - lib/brazilian-utils/passport-utils.rb
98
144
  - lib/brazilian-utils/phone-utils.rb
99
145
  - lib/brazilian-utils/pis-utils.rb
146
+ - lib/brazilian-utils/pix-key-utils.rb
147
+ - lib/brazilian-utils/pix-payload-utils.rb
148
+ - lib/brazilian-utils/registro-profissional-utils.rb
100
149
  - lib/brazilian-utils/renavam-utils.rb
150
+ - lib/brazilian-utils/state-utils.rb
151
+ - lib/brazilian-utils/text-utils.rb
152
+ - lib/brazilian-utils/vin-utils.rb
101
153
  - lib/brazilian-utils/voter-id-utils.rb
102
154
  homepage: https://github.com/brazilian-utils/ruby
103
155
  licenses:
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.3.0
5
- before_install: gem install bundler -v 1.12.5