br-utils 0.1.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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +120 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +348 -0
  8. data/Rakefile +6 -0
  9. data/examples/boleto_usage_example.rb +79 -0
  10. data/examples/cep_usage_example.rb +148 -0
  11. data/examples/cnh_usage_example.rb +120 -0
  12. data/examples/cnpj_usage_example.rb +227 -0
  13. data/examples/cpf_usage_example.rb +237 -0
  14. data/examples/currency_usage_example.rb +266 -0
  15. data/examples/date_usage_example.rb +259 -0
  16. data/examples/email_usage_example.rb +321 -0
  17. data/examples/legal_nature_usage_example.rb +437 -0
  18. data/examples/legal_process_usage_example.rb +444 -0
  19. data/examples/license_plate_usage_example.rb +440 -0
  20. data/examples/phone_usage_example.rb +595 -0
  21. data/examples/pis_usage_example.rb +588 -0
  22. data/examples/renavam_usage_example.rb +499 -0
  23. data/examples/voter_id_usage_example.rb +573 -0
  24. data/lib/brazilian-utils/boleto-utils.rb +176 -0
  25. data/lib/brazilian-utils/cep-utils.rb +330 -0
  26. data/lib/brazilian-utils/cnh-utils.rb +88 -0
  27. data/lib/brazilian-utils/cnpj-utils.rb +202 -0
  28. data/lib/brazilian-utils/cpf-utils.rb +192 -0
  29. data/lib/brazilian-utils/currency-utils.rb +226 -0
  30. data/lib/brazilian-utils/data/legal_process_ids.json +38 -0
  31. data/lib/brazilian-utils/date-utils.rb +244 -0
  32. data/lib/brazilian-utils/email-utils.rb +54 -0
  33. data/lib/brazilian-utils/legal-nature-utils.rb +235 -0
  34. data/lib/brazilian-utils/legal-process-utils.rb +240 -0
  35. data/lib/brazilian-utils/license-plate-utils.rb +279 -0
  36. data/lib/brazilian-utils/phone-utils.rb +272 -0
  37. data/lib/brazilian-utils/pis-utils.rb +151 -0
  38. data/lib/brazilian-utils/renavam-utils.rb +113 -0
  39. data/lib/brazilian-utils/voter-id-utils.rb +165 -0
  40. metadata +123 -0
@@ -0,0 +1,202 @@
1
+ module BrazilianUtils
2
+ module CNPJUtils
3
+ # FORMATTING
4
+ ############
5
+
6
+ # Removes specific symbols from a CNPJ (Brazilian Company Registration Number) string.
7
+ #
8
+ # This function takes a CNPJ string as input and removes all occurrences of
9
+ # the '.', '/' and '-' characters from it.
10
+ #
11
+ # @param dirty [String] The CNPJ string containing symbols to be removed.
12
+ # @return [String] A new string with the specified symbols removed.
13
+ #
14
+ # @example
15
+ # sieve("12.345/6789-01") #=> "12345678901"
16
+ # sieve("98/76.543-2101") #=> "98765432101"
17
+ #
18
+ # @note This method should not be used in new code and is only provided for
19
+ # backward compatibility. Use {remove_symbols} instead.
20
+ def self.sieve(dirty)
21
+ dirty.to_s.delete('./-')
22
+ end
23
+
24
+ # Removes specific symbols from a CNPJ string.
25
+ #
26
+ # This function is an alias for the {sieve} function, offering a more
27
+ # descriptive name.
28
+ #
29
+ # @param dirty [String] The dirty string containing symbols to be removed.
30
+ # @return [String] A new string with the specified symbols removed.
31
+ #
32
+ # @example
33
+ # remove_symbols("12.345/6789-01") #=> "12345678901"
34
+ # remove_symbols("98/76.543-2101") #=> "98765432101"
35
+ def self.remove_symbols(dirty)
36
+ sieve(dirty)
37
+ end
38
+
39
+ # Formats a CNPJ string for visual display (legacy method).
40
+ #
41
+ # Will format an adequately formatted numbers-only CNPJ string,
42
+ # adding in standard formatting visual aid symbols for display.
43
+ #
44
+ # @param cnpj [String] The CNPJ string to be formatted for display.
45
+ # @return [String, nil] The formatted CNPJ with visual aid symbols if it's valid,
46
+ # nil if it's not valid.
47
+ #
48
+ # @example
49
+ # display("12345678901234") #=> "12.345.678/9012-34"
50
+ # display("98765432100100") #=> "98.765.432/1001-00"
51
+ #
52
+ # @note This method should not be used in new code and is only provided for
53
+ # backward compatibility. Use {format_cnpj} instead.
54
+ def self.display(cnpj)
55
+ return nil unless cnpj.to_s.match?(/^\d{14}$/)
56
+ return nil if cnpj.chars.uniq.length == 1
57
+
58
+ format('%s.%s.%s/%s-%s',
59
+ cnpj[0..1],
60
+ cnpj[2..4],
61
+ cnpj[5..7],
62
+ cnpj[8..11],
63
+ cnpj[12..13])
64
+ end
65
+
66
+ # Formats a CNPJ (Brazilian Company Registration Number) string for visual display.
67
+ #
68
+ # This function takes a CNPJ string as input, validates its format, and
69
+ # formats it with standard visual aid symbols for display purposes.
70
+ #
71
+ # @param cnpj [String] The CNPJ string to be formatted for display.
72
+ # @return [String, nil] The formatted CNPJ with visual aid symbols if it's valid,
73
+ # nil if it's not valid.
74
+ #
75
+ # @example
76
+ # format_cnpj("03560714000142") #=> "03.560.714/0001-42"
77
+ # format_cnpj("98765432100100") #=> nil
78
+ def self.format_cnpj(cnpj)
79
+ return nil unless valid?(cnpj)
80
+
81
+ format('%s.%s.%s/%s-%s',
82
+ cnpj[0..1],
83
+ cnpj[2..4],
84
+ cnpj[5..7],
85
+ cnpj[8..11],
86
+ cnpj[12..13])
87
+ end
88
+
89
+ # OPERATIONS
90
+ ############
91
+
92
+ # Validates a CNPJ by comparing its verifying checksum digits to its base number.
93
+ #
94
+ # This function checks the validity of a CNPJ by comparing its verifying
95
+ # checksum digits to its base number. The input should be a string of digits
96
+ # with the appropriate length.
97
+ #
98
+ # @param cnpj [String] The CNPJ to be validated.
99
+ # @return [Boolean] true if the checksum digits match the base number, false otherwise.
100
+ #
101
+ # @example
102
+ # validate("03560714000142") #=> true
103
+ # validate("00111222000133") #=> false
104
+ #
105
+ # @note This method should not be used in new code and is only provided for
106
+ # backward compatibility. Use {valid?} instead.
107
+ def self.validate(cnpj)
108
+ return false unless cnpj.to_s.match?(/^\d{14}$/)
109
+ return false if cnpj.chars.uniq.length == 1
110
+
111
+ (0..1).all? do |i|
112
+ hashdigit(cnpj, i + 13) == cnpj[12 + i].to_i
113
+ end
114
+ end
115
+
116
+ # Returns whether or not the verifying checksum digits of the given CNPJ
117
+ # match its base number.
118
+ #
119
+ # This function does not verify the existence of the CNPJ; it only
120
+ # validates the format of the string.
121
+ #
122
+ # @param cnpj [String] The CNPJ to be validated, a 14-digit string
123
+ # @return [Boolean] true if the checksum digits match the base number, false otherwise.
124
+ #
125
+ # @example
126
+ # valid?("03560714000142") #=> true
127
+ # valid?("00111222000133") #=> false
128
+ def self.valid?(cnpj)
129
+ cnpj.is_a?(String) && validate(cnpj)
130
+ end
131
+
132
+ # Generates a random valid CNPJ digit string.
133
+ #
134
+ # An optional branch number parameter can be given; it defaults to 1.
135
+ #
136
+ # @param branch [Integer] An optional branch number to be included in the CNPJ.
137
+ # @return [String] A randomly generated valid CNPJ string.
138
+ #
139
+ # @example
140
+ # generate() #=> "30180536000105"
141
+ # generate(1234) #=> "01745284123455"
142
+ def self.generate(branch: 1)
143
+ branch = branch % 10_000
144
+ branch = 1 if branch.zero?
145
+ branch_str = branch.to_s.rjust(4, '0')
146
+ base = format('%08d', rand(100_000_000)) + branch_str
147
+
148
+ base + checksum(base)
149
+ end
150
+
151
+ # PRIVATE METHODS
152
+ #################
153
+
154
+ # Calculates the checksum digit at the given position for the provided CNPJ.
155
+ #
156
+ # The input must contain all elements before position.
157
+ #
158
+ # @param cnpj [String] The CNPJ for which the checksum digit is calculated.
159
+ # @param position [Integer] The position of the checksum digit to be calculated.
160
+ # @return [Integer] The calculated checksum digit.
161
+ #
162
+ # @example
163
+ # hashdigit("12345678901234", 13) #=> 3
164
+ # hashdigit("98765432100100", 14) #=> 9
165
+ #
166
+ # @private
167
+ def self.hashdigit(cnpj, position)
168
+ # Generate weights: from (position - 8) down to 2, then from 9 down to 2
169
+ weights = []
170
+ (position - 8).downto(2) { |w| weights << w }
171
+ 9.downto(2) { |w| weights << w }
172
+
173
+ val = cnpj.chars.zip(weights).sum do |digit, weight|
174
+ digit.to_i * weight
175
+ end % 11
176
+
177
+ val < 2 ? 0 : 11 - val
178
+ end
179
+
180
+ # Calculates the verifying checksum digits for a given CNPJ base number.
181
+ #
182
+ # This function computes the verifying checksum digits for a provided CNPJ
183
+ # base number. The basenum should be a digit-string of the appropriate length.
184
+ #
185
+ # @param basenum [String] The base number of the CNPJ for which verifying
186
+ # checksum digits are calculated.
187
+ # @return [String] The verifying checksum digits.
188
+ #
189
+ # @example
190
+ # checksum("123456789012") #=> "30"
191
+ # checksum("987654321001") #=> "41"
192
+ #
193
+ # @private
194
+ def self.checksum(basenum)
195
+ first_digit = hashdigit(basenum, 13).to_s
196
+ second_digit = hashdigit(basenum + first_digit, 14).to_s
197
+ first_digit + second_digit
198
+ end
199
+
200
+ private_class_method :hashdigit, :checksum
201
+ end
202
+ end
@@ -0,0 +1,192 @@
1
+ module BrazilianUtils
2
+ module CPFUtils
3
+ # FORMATTING
4
+ ############
5
+
6
+ # Removes specific symbols from a CPF (Brazilian Individual Taxpayer Number) string.
7
+ #
8
+ # This function takes a CPF string as input and removes all occurrences of
9
+ # the '.', '-' characters from it.
10
+ #
11
+ # @param dirty [String] The CPF string containing symbols to be removed.
12
+ # @return [String] A new string with the specified symbols removed.
13
+ #
14
+ # @example
15
+ # sieve("123.456.789-01") #=> "12345678901"
16
+ # sieve("987-654-321.01") #=> "98765432101"
17
+ #
18
+ # @note This method should not be used in new code and is only provided for
19
+ # backward compatibility. Use {remove_symbols} instead.
20
+ def self.sieve(dirty)
21
+ dirty.to_s.delete('.-')
22
+ end
23
+
24
+ # Removes specific symbols from a CPF string.
25
+ #
26
+ # This function is an alias for the {sieve} function, offering a more
27
+ # descriptive name.
28
+ #
29
+ # @param dirty [String] The CPF string containing symbols to be removed.
30
+ # @return [String] A new string with the specified symbols removed.
31
+ #
32
+ # @example
33
+ # remove_symbols("123.456.789-01") #=> "12345678901"
34
+ # remove_symbols("987-654-321.01") #=> "98765432101"
35
+ def self.remove_symbols(dirty)
36
+ sieve(dirty)
37
+ end
38
+
39
+ # Formats a CPF for display with visual aid symbols (legacy method).
40
+ #
41
+ # This function takes a numbers-only CPF string as input and adds standard
42
+ # formatting visual aid symbols for display.
43
+ #
44
+ # @param cpf [String] A numbers-only CPF string.
45
+ # @return [String, nil] A formatted CPF string with standard visual aid symbols,
46
+ # nil if the input is invalid.
47
+ #
48
+ # @example
49
+ # display("12345678901") #=> "123.456.789-01"
50
+ # display("98765432101") #=> "987.654.321-01"
51
+ #
52
+ # @note This method should not be used in new code and is only provided for
53
+ # backward compatibility. Use {format_cpf} instead.
54
+ def self.display(cpf)
55
+ return nil unless cpf.to_s.match?(/^\d{11}$/)
56
+ return nil if cpf.chars.uniq.length == 1
57
+
58
+ format('%s.%s.%s-%s',
59
+ cpf[0..2],
60
+ cpf[3..5],
61
+ cpf[6..8],
62
+ cpf[9..10])
63
+ end
64
+
65
+ # Formats a CPF for display with visual aid symbols.
66
+ #
67
+ # This function takes a numbers-only CPF string as input and adds standard
68
+ # formatting visual aid symbols for display.
69
+ #
70
+ # @param cpf [String] A numbers-only CPF string.
71
+ # @return [String, nil] A formatted CPF string with standard visual aid symbols,
72
+ # nil if the input is invalid.
73
+ #
74
+ # @example
75
+ # format_cpf("82178537464") #=> "821.785.374-64"
76
+ # format_cpf("55550207753") #=> "555.502.077-53"
77
+ def self.format_cpf(cpf)
78
+ return nil unless valid?(cpf)
79
+
80
+ format('%s.%s.%s-%s',
81
+ cpf[0..2],
82
+ cpf[3..5],
83
+ cpf[6..8],
84
+ cpf[9..10])
85
+ end
86
+
87
+ # OPERATIONS
88
+ ############
89
+
90
+ # Validates the checksum digits of a CPF.
91
+ #
92
+ # This function checks whether the verifying checksum digits of the given CPF
93
+ # match its base number. The input should be a digit string of the proper length.
94
+ #
95
+ # @param cpf [String] A numbers-only CPF string.
96
+ # @return [Boolean] true if the checksum digits are valid, false otherwise.
97
+ #
98
+ # @example
99
+ # validate("82178537464") #=> true
100
+ # validate("55550207753") #=> true
101
+ #
102
+ # @note This method should not be used in new code and is only provided for
103
+ # backward compatibility. Use {valid?} instead.
104
+ def self.validate(cpf)
105
+ return false unless cpf.to_s.match?(/^\d{11}$/)
106
+ return false if cpf.chars.uniq.length == 1
107
+
108
+ (0..1).all? do |i|
109
+ hashdigit(cpf, i + 10) == cpf[9 + i].to_i
110
+ end
111
+ end
112
+
113
+ # Returns whether or not the verifying checksum digits of the given CPF
114
+ # match its base number.
115
+ #
116
+ # This function does not verify the existence of the CPF; it only
117
+ # validates the format of the string.
118
+ #
119
+ # @param cpf [String] The CPF to be validated, an 11-digit string
120
+ # @return [Boolean] true if the checksum digits match the base number, false otherwise.
121
+ #
122
+ # @example
123
+ # valid?("82178537464") #=> true
124
+ # valid?("55550207753") #=> true
125
+ # valid?("00000000000") #=> false
126
+ # valid?("123.456.789-01") #=> false (must be numbers only)
127
+ def self.valid?(cpf)
128
+ cpf.is_a?(String) && validate(cpf)
129
+ end
130
+
131
+ # Generates a random valid CPF digit string.
132
+ #
133
+ # This function generates a random valid CPF string.
134
+ #
135
+ # @return [String] A random valid CPF string.
136
+ #
137
+ # @example
138
+ # generate() #=> "10895948109"
139
+ # generate() #=> "52837606502"
140
+ def self.generate
141
+ base = format('%09d', rand(1..999_999_998))
142
+ base + checksum(base)
143
+ end
144
+
145
+ # PRIVATE METHODS
146
+ #################
147
+
148
+ # Computes the given position checksum digit for a CPF.
149
+ #
150
+ # This function computes the specified position checksum digit for the CPF input.
151
+ # The input needs to contain all elements previous to the position, or the
152
+ # computation will yield the wrong result.
153
+ #
154
+ # @param cpf [String] A CPF string.
155
+ # @param position [Integer] The position to calculate the checksum digit for.
156
+ # @return [Integer] The calculated checksum digit.
157
+ #
158
+ # @example
159
+ # hashdigit("52599927765", 11) #=> 5
160
+ # hashdigit("52599927765", 10) #=> 6
161
+ #
162
+ # @private
163
+ def self.hashdigit(cpf, position)
164
+ val = cpf.chars.zip(position.downto(2)).sum do |digit, weight|
165
+ digit.to_i * weight
166
+ end % 11
167
+
168
+ val < 2 ? 0 : 11 - val
169
+ end
170
+
171
+ # Computes the checksum digits for a given CPF base number.
172
+ #
173
+ # This function calculates the checksum digits for a given CPF base number.
174
+ # The base number should be a digit string of adequate length.
175
+ #
176
+ # @param basenum [String] A digit string of adequate length (9 digits).
177
+ # @return [String] The calculated checksum digits (2 digits).
178
+ #
179
+ # @example
180
+ # checksum("335451269") #=> "51"
181
+ # checksum("382916331") #=> "26"
182
+ #
183
+ # @private
184
+ def self.checksum(basenum)
185
+ first_digit = hashdigit(basenum, 10).to_s
186
+ second_digit = hashdigit(basenum + first_digit, 11).to_s
187
+ first_digit + second_digit
188
+ end
189
+
190
+ private_class_method :hashdigit, :checksum
191
+ end
192
+ end
@@ -0,0 +1,226 @@
1
+ require 'bigdecimal'
2
+
3
+ module BrazilianUtils
4
+ module CurrencyUtils
5
+ # Formats a numeric value as Brazilian currency (R$).
6
+ #
7
+ # @param value [Float, Integer, String, BigDecimal] The numeric value to format.
8
+ # @return [String, nil] Formatted currency string (e.g., "R$ 1.234,56") or nil if invalid.
9
+ #
10
+ # @example
11
+ # format_currency(1234.56) #=> "R$ 1.234,56"
12
+ # format_currency(0) #=> "R$ 0,00"
13
+ # format_currency(-9876.54) #=> "R$ -9.876,54"
14
+ # format_currency("invalid") #=> nil
15
+ def self.format_currency(value)
16
+ decimal_value = BigDecimal(value.to_s)
17
+
18
+ # Format with 2 decimal places and thousands separator
19
+ formatted = format('%.2f', decimal_value)
20
+
21
+ # Split into integer and decimal parts
22
+ integer_part, decimal_part = formatted.split('.')
23
+
24
+ # Add thousands separator to integer part
25
+ integer_part = integer_part.chars.reverse.each_slice(3).map(&:join).join('.').reverse
26
+
27
+ # Combine with Brazilian format
28
+ "R$ #{integer_part},#{decimal_part}"
29
+ rescue ArgumentError, TypeError
30
+ nil
31
+ end
32
+
33
+ # Converts a monetary value in Brazilian Reais to textual representation.
34
+ #
35
+ # @param amount [BigDecimal, Float, Integer, String] Monetary value to convert.
36
+ # @return [String, nil] Textual representation in Brazilian Portuguese, or nil if invalid.
37
+ #
38
+ # @note
39
+ # - Values are rounded down to 2 decimal places
40
+ # - Maximum supported value is 1 quadrillion reais
41
+ # - Negative values are prefixed with "Menos"
42
+ #
43
+ # @example
44
+ # convert_real_to_text(1523.45)
45
+ # #=> "Mil, quinhentos e vinte e três reais e quarenta e cinco centavos"
46
+ #
47
+ # convert_real_to_text(1.00)
48
+ # #=> "Um real"
49
+ #
50
+ # convert_real_to_text(0.50)
51
+ # #=> "Cinquenta centavos"
52
+ #
53
+ # convert_real_to_text(0.00)
54
+ # #=> "Zero reais"
55
+ def self.convert_real_to_text(amount)
56
+ # Convert to BigDecimal and round down to 2 decimal places
57
+ decimal_amount = BigDecimal(amount.to_s)
58
+ decimal_amount = decimal_amount.truncate(2)
59
+
60
+ # Check for invalid values
61
+ return nil if decimal_amount.nan? || decimal_amount.infinite?
62
+ return nil if decimal_amount.abs > BigDecimal('1000000000000000.00') # 1 quadrillion
63
+
64
+ negative = decimal_amount < 0
65
+ decimal_amount = decimal_amount.abs
66
+
67
+ reais = decimal_amount.to_i
68
+ centavos = ((decimal_amount - reais) * 100).to_i
69
+
70
+ parts = []
71
+
72
+ if reais > 0
73
+ reais_text = number_to_words(reais)
74
+ currency_text = reais == 1 ? 'real' : 'reais'
75
+ conector = reais_text.match?(/lhão|lhões$/) ? 'de ' : ''
76
+ parts << "#{reais_text} #{conector}#{currency_text}"
77
+ end
78
+
79
+ if centavos > 0
80
+ centavos_text = "#{number_to_words(centavos)} #{centavos == 1 ? 'centavo' : 'centavos'}"
81
+ if reais > 0
82
+ parts << "e #{centavos_text}"
83
+ else
84
+ parts << centavos_text
85
+ end
86
+ end
87
+
88
+ if reais == 0 && centavos == 0
89
+ parts << 'Zero reais'
90
+ end
91
+
92
+ result = parts.join(' ')
93
+ result = "Menos #{result}" if negative
94
+
95
+ result.capitalize
96
+ rescue ArgumentError, TypeError
97
+ nil
98
+ end
99
+
100
+ # Converts a number to its textual representation in Brazilian Portuguese.
101
+ #
102
+ # @param number [Integer] The number to convert (0 to 999,999,999,999,999,999)
103
+ # @return [String] The textual representation
104
+ #
105
+ # @private
106
+ def self.number_to_words(number)
107
+ return 'zero' if number.zero?
108
+
109
+ # Scale names
110
+ scales = [
111
+ '',
112
+ 'mil',
113
+ 'milhão',
114
+ 'bilhão',
115
+ 'trilhão',
116
+ 'quadrilhão'
117
+ ]
118
+
119
+ scales_plural = [
120
+ '',
121
+ 'mil',
122
+ 'milhões',
123
+ 'bilhões',
124
+ 'trilhões',
125
+ 'quadrilhões'
126
+ ]
127
+
128
+ # Break number into groups of 3 digits
129
+ groups = []
130
+ temp = number
131
+ while temp > 0
132
+ groups << temp % 1000
133
+ temp /= 1000
134
+ end
135
+
136
+ result = []
137
+ groups.each_with_index do |group, index|
138
+ next if group.zero?
139
+
140
+ group_text = convert_group(group)
141
+ scale_name = group == 1 ? scales[index] : scales_plural[index]
142
+
143
+ if scale_name.empty?
144
+ result << group_text
145
+ elsif index == 1 # "mil" doesn't need number before if it's exactly 1000
146
+ if group == 1
147
+ result << scale_name
148
+ else
149
+ result << "#{group_text} #{scale_name}"
150
+ end
151
+ else
152
+ result << "#{group_text} #{scale_name}"
153
+ end
154
+ end
155
+
156
+ # Join with "e" where appropriate
157
+ if result.length > 1
158
+ last = result.pop
159
+ result_text = result.reverse.join(', ')
160
+
161
+ # Check if we need "e" before the last part
162
+ if number % 1000 < 100 && number % 1000 > 0
163
+ "#{result_text} e #{last}"
164
+ else
165
+ "#{result_text}, #{last}"
166
+ end
167
+ else
168
+ result.first || 'zero'
169
+ end
170
+ end
171
+
172
+ # Converts a group of 3 digits (0-999) to words.
173
+ #
174
+ # @param number [Integer] Number between 0 and 999
175
+ # @return [String] The textual representation
176
+ #
177
+ # @private
178
+ def self.convert_group(number)
179
+ ones = %w[zero um dois três quatro cinco seis sete oito nove]
180
+ tens = %w[dez onze doze treze quatorze quinze dezesseis dezessete dezoito dezenove]
181
+ tens_multiples = %w[_ _ vinte trinta quarenta cinquenta sessenta setenta oitenta noventa]
182
+ hundreds = %w[
183
+ _
184
+ cento
185
+ duzentos
186
+ trezentos
187
+ quatrocentos
188
+ quinhentos
189
+ seiscentos
190
+ setecentos
191
+ oitocentos
192
+ novecentos
193
+ ]
194
+
195
+ return ones[number] if number < 10
196
+
197
+ if number < 20
198
+ return tens[number - 10]
199
+ end
200
+
201
+ if number < 100
202
+ tens_digit = number / 10
203
+ ones_digit = number % 10
204
+ if ones_digit.zero?
205
+ return tens_multiples[tens_digit]
206
+ else
207
+ return "#{tens_multiples[tens_digit]} e #{ones[ones_digit]}"
208
+ end
209
+ end
210
+
211
+ # 100-999
212
+ hundreds_digit = number / 100
213
+ remainder = number % 100
214
+
215
+ if number == 100
216
+ 'cem'
217
+ elsif remainder.zero?
218
+ hundreds[hundreds_digit]
219
+ else
220
+ "#{hundreds[hundreds_digit]} e #{convert_group(remainder)}"
221
+ end
222
+ end
223
+
224
+ private_class_method :number_to_words, :convert_group
225
+ end
226
+ end
@@ -0,0 +1,38 @@
1
+ {
2
+ "orgao_1": {
3
+ "id_tribunal": [1],
4
+ "id_foro": [0]
5
+ },
6
+ "orgao_2": {
7
+ "id_tribunal": [2],
8
+ "id_foro": [0]
9
+ },
10
+ "orgao_3": {
11
+ "id_tribunal": [3],
12
+ "id_foro": [0]
13
+ },
14
+ "orgao_4": {
15
+ "id_tribunal": [1, 2, 3, 4, 5],
16
+ "id_foro": [5120, 4100, 4101, 8200, 8201, 8202, 3600, 3601, 3602, 3603, 3100, 7200, 7201, 7202, 7203, 6181, 6182, 6183, 7205, 7206, 7207, 7208, 7209, 7211, 7213, 7214, 7215, 7216, 6201, 5190, 9810, 9305, 6126, 9830, 4200, 6127, 8300, 8302, 8303, 8304, 9330, 3700, 3701, 3702, 8308, 3200, 3201, 7310, 6301, 6302, 6303, 6304, 6305, 6306, 6307, 9380, 6308, 6309, 6310, 6311, 6312, 6313, 6314, 6315, 6316, 6317, 6318, 6319, 6320, 4300, 8400, 8401, 8402, 9710, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3812, 3813, 3814, 3815, 6401, 9720, 8500, 8501, 8502, 3900, 3901, 3902, 3903, 3904, 9700, 8000, 8001, 8002, 3400, 7000, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, 6501, 7013, 7014, 7015, 7016, 6001, 6002, 6003, 6004, 6005, 6006, 6007, 5001, 5002, 5003, 5004, 5005, 9621, 4000, 4001, 8100, 8101, 8102, 8103, 3500, 3501, 3502, 3503, 3504, 3000, 7100, 9661, 7101, 7102, 7103, 7104, 7105, 7106, 7107, 7108, 7109, 7110, 7111, 7112, 7113, 7115, 7116, 7117, 7118, 7119, 7120, 6100, 6102, 6103, 6104, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 5101, 5102, 5103, 5104, 6125, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119]
17
+ },
18
+ "orgao_5": {
19
+ "id_tribunal": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
20
+ "id_foro": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 161, 171, 172, 181, 182, 191, 192, 193, 194, 195, 201, 202, 203, 204, 205, 206, 207, 211, 221, 222, 223, 224, 225, 226, 231, 232, 233, 241, 242, 243, 244, 245, 246, 247, 251, 252, 253, 254, 255, 261, 262, 263, 264, 271, 281, 282, 291, 292, 301, 302, 303, 304, 305, 311, 312, 313, 314, 315, 316, 317, 318, 319, 321, 322, 325, 331, 332, 333, 341, 342, 343, 351, 352, 361, 371, 372, 373, 381, 382, 383, 384, 391, 401, 402, 403, 404, 411, 412, 413, 416, 421, 425, 426, 431, 432, 433, 434, 436, 441, 442, 443, 444, 445, 446, 447, 451, 459, 461, 462, 463, 464, 465, 466, 471, 472, 481, 482, 491, 492, 493, 501, 511, 512, 513, 521, 522, 531, 541, 551, 561, 562, 567, 571, 581, 585, 594, 601, 611, 612, 621, 631, 641, 643, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 668, 669, 670, 671, 672, 673, 678, 701, 702, 721, 731, 732, 733, 741, 749, 751, 761, 771, 781, 791, 801, 802, 9000, 811, 812, 821, 831, 841, 851, 861, 871, 872, 892, 895, 896, 897, 898, 899, 901, 902, 903, 904, 905, 965, 999]
21
+ },
22
+ "orgao_6": {
23
+ "id_tribunal": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27],
24
+ "id_foro": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422]
25
+ },
26
+ "orgao_7": {
27
+ "id_tribunal": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
28
+ "id_foro": [4, 101, 102, 103, 5, 201, 202, 203, 6, 301, 7, 303, 8, 401, 9, 10, 11, 12]
29
+ },
30
+ "orgao_8": {
31
+ "id_tribunal": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27],
32
+ "id_foro": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 6200, 62, 63, 64, 65, 66, 67, 68, 70, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 81, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 91, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 4200, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 132, 133, 134, 136, 137, 138, 131, 135, 141, 142, 139, 144, 145, 146, 140, 148, 4100, 149, 150, 2200, 151, 152, 153, 6300, 154, 155, 156, 157, 158, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 172, 173, 174, 175, 176, 177, 178, 171, 180, 181, 182, 179, 183, 184, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 4300, 204, 205, 206, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 2300, 252, 253, 254, 6400, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 280, 281, 283, 284, 279, 282, 287, 286, 288, 290, 291, 292, 294, 295, 296, 297, 299, 300, 301, 302, 303, 4400, 306, 309, 310, 311, 312, 313, 315, 317, 318, 319, 320, 321, 322, 323, 324, 325, 2100, 327, 326, 329, 330, 331, 332, 333, 334, 335, 337, 338, 340, 341, 342, 343, 344, 346, 347, 348, 349, 350, 351, 2400, 352, 355, 6500, 356, 358, 357, 360, 361, 362, 363, 366, 368, 369, 370, 371, 372, 374, 377, 378, 380, 381, 382, 383, 384, 386, 388, 390, 391, 392, 393, 394, 395, 396, 397, 398, 400, 401, 4500, 405, 404, 407, 408, 410, 411, 412, 414, 415, 416, 417, 418, 420, 421, 422, 424, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 438, 439, 440, 441, 443, 444, 445, 446, 447, 449, 450, 451, 2500, 452, 453, 6600, 456, 457, 459, 460, 461, 458, 462, 464, 466, 467, 470, 471, 472, 473, 474, 476, 477, 479, 480, 481, 482, 483, 484, 486, 487, 488, 490, 491, 493, 495, 498, 499, 500, 501, 4600, 505, 506, 508, 510, 511, 512, 514, 515, 516, 517, 518, 520, 521, 522, 523, 525, 526, 527, 528, 529, 530, 531, 533, 534, 538, 539, 540, 541, 542, 543, 547, 549, 550, 551, 2600, 553, 554, 555, 6700, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 567, 568, 566, 570, 571, 572, 575, 576, 577, 579, 580, 581, 582, 584, 586, 587, 588, 589, 590, 592, 595, 596, 597, 598, 600, 601, 602, 603, 4700, 604, 606, 607, 609, 610, 611, 614, 615, 619, 620, 621, 624, 625, 627, 628, 629, 630, 631, 634, 637, 638, 640, 642, 643, 646, 647, 648, 650, 651, 2700, 653, 654, 655, 6800, 657, 659, 660, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 4800, 704, 705, 707, 708, 706, 710, 709, 713, 718, 143, 720, 730, 731, 147, 741, 740, 750, 751, 2800, 6900, 760, 761, 770, 775, 778, 780, 781, 790, 159, 800, 4900, 160, 9000, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 810, 9010, 820, 830, 831, 840, 850, 2900, 7000, 860, 870, 878, 879, 880, 881, 890, 900, 902, 903, 5000, 904, 905, 906, 907, 908, 910, 911, 909, 920, 930, 185, 940, 941, 950, 951, 3000, 7100, 960, 970, 980, 981, 990, 1000, 5100, 1010, 1020, 1030, 1040, 207, 1050, 3100, 7200, 1060, 1070, 1071, 1080, 1090, 1100, 5200, 1110, 1111, 1120, 1130, 1140, 1150, 3200, 7300, 1160, 1161, 1170, 1171, 1180, 1190, 1200, 1201, 5300, 1210, 1211, 1220, 1230, 1240, 1250, 3300, 7400, 1260, 1270, 1280, 1290, 1300, 5400, 1310, 1320, 1330, 1340, 1350, 3400, 7500, 1360, 1370, 1380, 1390, 1400, 5500, 1410, 1420, 1430, 1440, 1450, 3500, 7600, 1460, 1470, 1480, 1490, 1500, 5600, 1510, 1520, 1530, 1540, 1550, 3600, 1560, 1570, 1580, 1590, 1600, 5700, 1610, 1620, 1630, 3700, 7800, 5800, 3800, 5900, 9999, 3900, 6000, 4000, 2000, 2001, 2002, 2003, 6100, 2004, 2005]
33
+ },
34
+ "orgao_9": {
35
+ "id_tribunal": [21, 26, 13],
36
+ "id_foro": [0, 1, 2, 3, 4, 40, 10, 20, 21, 90, 91, 30]
37
+ }
38
+ }