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,588 @@
1
+ require 'brazilian-utils/pis-utils'
2
+
3
+ include BrazilianUtils::PISUtils
4
+
5
+ puts "=" * 80
6
+ puts "Brazilian PIS Utils - Usage Examples"
7
+ puts "=" * 80
8
+
9
+ # ============================================================================
10
+ # Section 1: Removing Symbols
11
+ # ============================================================================
12
+ puts "\n1. Removing Symbols"
13
+ puts "-" * 80
14
+
15
+ pis_with_symbols = [
16
+ '123.45678.90-9',
17
+ '987.65432.10-0',
18
+ '12345678909',
19
+ '123.456.789.09',
20
+ '12345678-909',
21
+ '1-2-3.4-5.6-7-8.9-0-9'
22
+ ]
23
+
24
+ pis_with_symbols.each do |pis|
25
+ clean = remove_symbols(pis)
26
+ puts " #{pis.ljust(25)} → #{clean}"
27
+ end
28
+
29
+ # ============================================================================
30
+ # Section 2: Using the sieve Alias
31
+ # ============================================================================
32
+ puts "\n2. Using the sieve Alias"
33
+ puts "-" * 80
34
+
35
+ puts " sieve('123.45678.90-9') → #{sieve('123.45678.90-9')}"
36
+ puts " sieve('987.65432.10-0') → #{sieve('987.65432.10-0')}"
37
+
38
+ # ============================================================================
39
+ # Section 3: Formatting Valid PIS Numbers
40
+ # ============================================================================
41
+ puts "\n3. Formatting Valid PIS Numbers"
42
+ puts "-" * 80
43
+
44
+ # Generate some valid PIS to demonstrate formatting
45
+ valid_pis_numbers = 5.times.map { generate }
46
+
47
+ valid_pis_numbers.each do |pis|
48
+ formatted = format_pis(pis)
49
+ puts " #{pis.ljust(15)} → #{formatted}"
50
+ end
51
+
52
+ # ============================================================================
53
+ # Section 4: Formatting Known Valid PIS
54
+ # ============================================================================
55
+ puts "\n4. Formatting Known Valid PIS"
56
+ puts "-" * 80
57
+
58
+ known_valid = ['12345678909', '98765432100', '01234567890']
59
+
60
+ known_valid.each do |pis|
61
+ formatted = format_pis(pis)
62
+ if formatted
63
+ puts " #{pis.ljust(15)} → #{formatted}"
64
+ else
65
+ puts " #{pis.ljust(15)} → Cannot format (invalid)"
66
+ end
67
+ end
68
+
69
+ # ============================================================================
70
+ # Section 5: Using the format Alias
71
+ # ============================================================================
72
+ puts "\n5. Using the format Alias"
73
+ puts "-" * 80
74
+
75
+ test_pis = generate
76
+ puts " Generated: #{test_pis}"
77
+ puts " format(#{test_pis}) → #{format(test_pis)}"
78
+
79
+ # ============================================================================
80
+ # Section 6: Formatting Invalid PIS (Returns nil)
81
+ # ============================================================================
82
+ puts "\n6. Formatting Invalid PIS (Returns nil)"
83
+ puts "-" * 80
84
+
85
+ invalid_pis = [
86
+ '12345678900',
87
+ '123456789',
88
+ '123456789012',
89
+ '1234567890A'
90
+ ]
91
+
92
+ invalid_pis.each do |pis|
93
+ formatted = format_pis(pis)
94
+ puts " #{pis.ljust(15)} → #{formatted.inspect}"
95
+ end
96
+
97
+ # ============================================================================
98
+ # Section 7: Validating Valid PIS Numbers
99
+ # ============================================================================
100
+ puts "\n7. Validating Valid PIS Numbers"
101
+ puts "-" * 80
102
+
103
+ valid_numbers = [
104
+ '12345678909',
105
+ '98765432100',
106
+ '01234567890',
107
+ '12082043600',
108
+ '17033259504'
109
+ ]
110
+
111
+ valid_numbers.each do |pis|
112
+ valid = is_valid(pis)
113
+ status = valid ? '✓ VALID' : '✗ INVALID'
114
+ puts " #{pis.ljust(15)} → #{status}"
115
+ end
116
+
117
+ # ============================================================================
118
+ # Section 8: Validating Invalid PIS Numbers
119
+ # ============================================================================
120
+ puts "\n8. Validating Invalid PIS Numbers"
121
+ puts "-" * 80
122
+
123
+ invalid_numbers = [
124
+ '12345678900', # Wrong checksum
125
+ '12345678908', # Wrong checksum
126
+ '123456789', # Too short
127
+ '123456789012', # Too long
128
+ '1234567890A', # Contains letter
129
+ '123.45678.90-9', # Contains symbols
130
+ '00000000000', # All zeros
131
+ '11111111111' # All ones
132
+ ]
133
+
134
+ invalid_numbers.each do |pis|
135
+ valid = is_valid(pis)
136
+ status = valid ? '✓ VALID' : '✗ INVALID'
137
+ puts " #{pis.ljust(20)} → #{status}"
138
+ end
139
+
140
+ # ============================================================================
141
+ # Section 9: Using the valid? Alias
142
+ # ============================================================================
143
+ puts "\n9. Using the valid? Alias"
144
+ puts "-" * 80
145
+
146
+ test_numbers = ['12345678909', '98765432100', '12345678900']
147
+
148
+ test_numbers.each do |pis|
149
+ if valid?(pis)
150
+ puts " ✓ #{pis} is valid"
151
+ else
152
+ puts " ✗ #{pis} is invalid"
153
+ end
154
+ end
155
+
156
+ # ============================================================================
157
+ # Section 10: Generating Random PIS Numbers
158
+ # ============================================================================
159
+ puts "\n10. Generating Random PIS Numbers"
160
+ puts "-" * 80
161
+
162
+ puts " Generating 10 random PIS numbers:"
163
+ 10.times do
164
+ pis = generate
165
+ formatted = format(pis)
166
+ puts " #{formatted.ljust(20)} (#{pis})"
167
+ end
168
+
169
+ # ============================================================================
170
+ # Section 11: Verifying Generated PIS Are Valid
171
+ # ============================================================================
172
+ puts "\n11. Verifying Generated PIS Are Valid"
173
+ puts "-" * 80
174
+
175
+ puts " Generating 5 PIS and validating each:"
176
+ 5.times do |i|
177
+ pis = generate
178
+ valid = is_valid(pis)
179
+ status = valid ? '✓' : '✗'
180
+ puts " #{status} PIS #{i + 1}: #{format(pis)}"
181
+ end
182
+
183
+ # ============================================================================
184
+ # Section 12: Complete Workflow - User Input with Symbols
185
+ # ============================================================================
186
+ puts "\n12. Complete Workflow - User Input with Symbols"
187
+ puts "-" * 80
188
+
189
+ user_input = '123.45678.90-9'
190
+
191
+ puts " User input: #{user_input}"
192
+ puts
193
+
194
+ # Step 1: Remove symbols
195
+ clean = remove_symbols(user_input)
196
+ puts " 1. After remove_symbols: #{clean}"
197
+
198
+ # Step 2: Validate
199
+ if is_valid(clean)
200
+ puts " 2. Validation: ✓ VALID"
201
+
202
+ # Step 3: Format for display
203
+ formatted = format_pis(clean)
204
+ puts " 3. Formatted: #{formatted}"
205
+
206
+ # Step 4: Store cleaned version
207
+ puts " 4. Store in database: #{clean}"
208
+ else
209
+ puts " 2. Validation: ✗ INVALID"
210
+ end
211
+
212
+ # ============================================================================
213
+ # Section 13: Complete Workflow - Invalid Input
214
+ # ============================================================================
215
+ puts "\n13. Complete Workflow - Invalid Input"
216
+ puts "-" * 80
217
+
218
+ invalid_input = '123.45678.90-0'
219
+
220
+ puts " User input: #{invalid_input}"
221
+ puts
222
+
223
+ # Step 1: Remove symbols
224
+ clean = remove_symbols(invalid_input)
225
+ puts " 1. After remove_symbols: #{clean}"
226
+
227
+ # Step 2: Validate
228
+ if is_valid(clean)
229
+ puts " 2. Validation: ✓ VALID"
230
+ formatted = format_pis(clean)
231
+ puts " 3. Formatted: #{formatted}"
232
+ else
233
+ puts " 2. Validation: ✗ INVALID (wrong checksum)"
234
+ puts " 3. Cannot format invalid PIS"
235
+ end
236
+
237
+ # ============================================================================
238
+ # Section 14: Validating PIS List
239
+ # ============================================================================
240
+ puts "\n14. Validating PIS List"
241
+ puts "-" * 80
242
+
243
+ pis_list = [
244
+ '123.45678.90-9',
245
+ '98765432100',
246
+ '12345678900',
247
+ '123456789',
248
+ '12082043600',
249
+ '17033259504',
250
+ '00000000000'
251
+ ]
252
+
253
+ puts " Validating #{pis_list.length} PIS numbers:"
254
+ puts
255
+
256
+ valid_count = 0
257
+ invalid_count = 0
258
+
259
+ pis_list.each do |pis|
260
+ # Clean if needed
261
+ clean = remove_symbols(pis)
262
+
263
+ if valid?(clean)
264
+ valid_count += 1
265
+ formatted = format(clean)
266
+ puts " ✓ #{formatted.ljust(20)}"
267
+ else
268
+ invalid_count += 1
269
+ puts " ✗ #{pis.ljust(20)} [INVALID]"
270
+ end
271
+ end
272
+
273
+ puts
274
+ puts " Summary:"
275
+ puts " Valid: #{valid_count}"
276
+ puts " Invalid: #{invalid_count}"
277
+ puts " Total: #{pis_list.length}"
278
+
279
+ # ============================================================================
280
+ # Section 15: Generating Test Data
281
+ # ============================================================================
282
+ puts "\n15. Generating Test Data"
283
+ puts "-" * 80
284
+
285
+ puts " Generating test dataset with 10 PIS numbers:"
286
+ puts
287
+
288
+ test_data = 10.times.map { generate }
289
+
290
+ test_data.each_with_index do |pis, index|
291
+ formatted = format(pis)
292
+ puts " #{(index + 1).to_s.rjust(2)}. #{formatted} (#{pis})"
293
+ end
294
+
295
+ # ============================================================================
296
+ # Section 16: Format and Clean Are Inverse Operations
297
+ # ============================================================================
298
+ puts "\n16. Format and Clean Are Inverse Operations"
299
+ puts "-" * 80
300
+
301
+ puts " Testing format → clean → format cycle:"
302
+ 5.times do |i|
303
+ original = generate
304
+ formatted = format(original)
305
+ cleaned = remove_symbols(formatted)
306
+ reformatted = format(cleaned)
307
+
308
+ match = (original == cleaned && formatted == reformatted)
309
+ status = match ? '✓' : '✗'
310
+
311
+ puts " #{status} Cycle #{i + 1}: #{original} → #{formatted} → #{cleaned} → #{reformatted}"
312
+ end
313
+
314
+ # ============================================================================
315
+ # Section 17: Checksum Verification
316
+ # ============================================================================
317
+ puts "\n17. Checksum Verification"
318
+ puts "-" * 80
319
+
320
+ puts " Understanding checksum calculation:"
321
+ puts
322
+
323
+ # Generate a PIS and explain its checksum
324
+ pis = generate
325
+ base = pis[0..9]
326
+ checksum_digit = pis[10]
327
+
328
+ puts " PIS: #{format(pis)}"
329
+ puts " Base (first 10 digits): #{base}"
330
+ puts " Checksum digit (11th digit): #{checksum_digit}"
331
+ puts
332
+ puts " Checksum calculation:"
333
+ puts " Digits: #{base.chars.join(' ')}"
334
+ puts " Weights: 3 2 9 8 7 6 5 4 3 2"
335
+ puts
336
+ puts " Algorithm:"
337
+ puts " 1. Multiply each digit by its weight"
338
+ puts " 2. Sum all products"
339
+ puts " 3. Calculate: 11 - (sum % 11)"
340
+ puts " 4. If result is 10 or 11, use 0"
341
+ puts " 5. Result is the checksum digit"
342
+
343
+ # ============================================================================
344
+ # Section 18: PIS Starting with Zeros
345
+ # ============================================================================
346
+ puts "\n18. PIS Starting with Zeros"
347
+ puts "-" * 80
348
+
349
+ puts " PIS numbers can start with zeros:"
350
+ puts
351
+
352
+ # Generate until we get one starting with 0 (or create examples)
353
+ examples = []
354
+ 50.times do
355
+ pis = generate
356
+ examples << pis if pis[0] == '0'
357
+ break if examples.length >= 3
358
+ end
359
+
360
+ if examples.any?
361
+ examples.each do |pis|
362
+ formatted = format(pis)
363
+ puts " #{formatted} (#{pis})"
364
+ end
365
+ else
366
+ puts " (Generating PIS with leading zeros is rare but valid)"
367
+ puts " Example format: 012.34567.89-0"
368
+ end
369
+
370
+ # ============================================================================
371
+ # Section 19: Batch Processing
372
+ # ============================================================================
373
+ puts "\n19. Batch Processing"
374
+ puts "-" * 80
375
+
376
+ puts " Processing batch of user inputs:"
377
+ puts
378
+
379
+ user_inputs = [
380
+ '123.45678.90-9',
381
+ '987.65432.10-0',
382
+ '12345678900',
383
+ '123456789',
384
+ '12082043600',
385
+ '987-654-321-00'
386
+ ]
387
+
388
+ results = {
389
+ valid: [],
390
+ invalid: []
391
+ }
392
+
393
+ user_inputs.each do |input|
394
+ clean = remove_symbols(input)
395
+
396
+ if valid?(clean)
397
+ results[:valid] << { original: input, clean: clean, formatted: format(clean) }
398
+ else
399
+ results[:invalid] << { original: input, clean: clean }
400
+ end
401
+ end
402
+
403
+ puts " Valid PIS (#{results[:valid].length}):"
404
+ results[:valid].each do |item|
405
+ puts " ✓ #{item[:formatted]}"
406
+ end
407
+
408
+ puts
409
+ puts " Invalid PIS (#{results[:invalid].length}):"
410
+ results[:invalid].each do |item|
411
+ puts " ✗ #{item[:original]} (cleaned: #{item[:clean]})"
412
+ end
413
+
414
+ # ============================================================================
415
+ # Section 20: Error Handling
416
+ # ============================================================================
417
+ puts "\n20. Error Handling"
418
+ puts "-" * 80
419
+
420
+ edge_cases = [
421
+ nil,
422
+ '',
423
+ 12345678909,
424
+ 'ABC123DEF456',
425
+ '123.45678.90-9',
426
+ '12345678909 '
427
+ ]
428
+
429
+ edge_cases.each do |input|
430
+ puts " Input: #{input.inspect.ljust(25)}"
431
+ puts " is_valid: #{is_valid(input)}"
432
+ puts " format_pis: #{format_pis(input).inspect}"
433
+
434
+ if input.is_a?(String) && !input.empty?
435
+ clean = remove_symbols(input)
436
+ puts " remove_symbols: #{clean.inspect}"
437
+ end
438
+
439
+ puts
440
+ end
441
+
442
+ # ============================================================================
443
+ # Section 21: PIS Structure Visualization
444
+ # ============================================================================
445
+ puts "\n21. PIS Structure Visualization"
446
+ puts "-" * 80
447
+
448
+ sample_pis = generate
449
+ formatted = format(sample_pis)
450
+
451
+ puts " PIS: #{formatted}"
452
+ puts
453
+ puts " Structure breakdown:"
454
+ puts " #{formatted}"
455
+ puts " │ │ │ └─ Checksum digit (calculated)"
456
+ puts " │ │ └──── Digits 9-10"
457
+ puts " │ └────────── Digits 4-8 (5 digits)"
458
+ puts " └────────────── Digits 1-3 (3 digits)"
459
+ puts
460
+ puts " Raw format: #{sample_pis}"
461
+ puts " Positions: 1234567890X (X = checksum)"
462
+
463
+ # ============================================================================
464
+ # Section 22: Statistics on Generated PIS
465
+ # ============================================================================
466
+ puts "\n22. Statistics on Generated PIS"
467
+ puts "-" * 80
468
+
469
+ puts " Generating 100 PIS and analyzing:"
470
+ puts
471
+
472
+ generated = 100.times.map { generate }
473
+
474
+ # Check how many start with each digit
475
+ digit_distribution = Hash.new(0)
476
+ generated.each do |pis|
477
+ digit_distribution[pis[0]] += 1
478
+ end
479
+
480
+ puts " First digit distribution:"
481
+ ('0'..'9').each do |digit|
482
+ count = digit_distribution[digit]
483
+ percentage = (count * 100.0 / generated.length).round(1)
484
+ bar = '█' * (count / 2)
485
+ puts " #{digit}: #{bar} #{count} (#{percentage}%)"
486
+ end
487
+
488
+ # Check all are valid
489
+ all_valid = generated.all? { |pis| is_valid(pis) }
490
+ puts
491
+ puts " All generated PIS are valid: #{all_valid ? '✓ YES' : '✗ NO'}"
492
+
493
+ # ============================================================================
494
+ # Section 23: Comparison with Formatted Input
495
+ # ============================================================================
496
+ puts "\n23. Comparison with Formatted Input"
497
+ puts "-" * 80
498
+
499
+ puts " Comparing raw and formatted input validation:"
500
+ puts
501
+
502
+ comparison_pis = generate
503
+
504
+ puts " Original: #{comparison_pis}"
505
+ puts " is_valid(#{comparison_pis}): #{is_valid(comparison_pis)}"
506
+ puts
507
+
508
+ formatted_pis = format(comparison_pis)
509
+ puts " Formatted: #{formatted_pis}"
510
+ puts " is_valid(#{formatted_pis}): #{is_valid(formatted_pis)}"
511
+ puts
512
+
513
+ cleaned_pis = remove_symbols(formatted_pis)
514
+ puts " Cleaned: #{cleaned_pis}"
515
+ puts " is_valid(#{cleaned_pis}): #{is_valid(cleaned_pis)}"
516
+ puts
517
+ puts " Note: Validation requires cleaned (digits-only) input"
518
+
519
+ # ============================================================================
520
+ # Section 24: Database Storage Example
521
+ # ============================================================================
522
+ puts "\n24. Database Storage Example"
523
+ puts "-" * 80
524
+
525
+ puts " Best practices for storing PIS in database:"
526
+ puts
527
+
528
+ user_form_input = '123.45678.90-9'
529
+
530
+ puts " 1. User enters: #{user_form_input}"
531
+
532
+ # Clean
533
+ stored_value = remove_symbols(user_form_input)
534
+ puts " 2. Store in database: #{stored_value} (digits only)"
535
+
536
+ # Validate before storing
537
+ if valid?(stored_value)
538
+ puts " 3. Validation: ✓ Valid - safe to store"
539
+
540
+ # When displaying
541
+ display_value = format(stored_value)
542
+ puts " 4. Display to user: #{display_value}"
543
+ else
544
+ puts " 3. Validation: ✗ Invalid - reject input"
545
+ end
546
+
547
+ # ============================================================================
548
+ # Section 25: Integration with Other Systems
549
+ # ============================================================================
550
+ puts "\n25. Integration with Other Systems"
551
+ puts "-" * 80
552
+
553
+ puts " Example: Processing PIS from external API:"
554
+ puts
555
+
556
+ # Simulate API response
557
+ api_responses = [
558
+ { name: 'João Silva', pis: '123.45678.90-9' },
559
+ { name: 'Maria Santos', pis: '98765432100' },
560
+ { name: 'Pedro Costa', pis: '12345678900' } # Invalid
561
+ ]
562
+
563
+ puts " Processing #{api_responses.length} records:"
564
+ puts
565
+
566
+ valid_records = []
567
+ invalid_records = []
568
+
569
+ api_responses.each do |record|
570
+ clean_pis = remove_symbols(record[:pis])
571
+
572
+ if valid?(clean_pis)
573
+ valid_records << record.merge(clean_pis: clean_pis, formatted_pis: format(clean_pis))
574
+ puts " ✓ #{record[:name].ljust(20)} - PIS: #{format(clean_pis)}"
575
+ else
576
+ invalid_records << record
577
+ puts " ✗ #{record[:name].ljust(20)} - PIS: #{record[:pis]} [INVALID]"
578
+ end
579
+ end
580
+
581
+ puts
582
+ puts " Summary:"
583
+ puts " Valid records: #{valid_records.length}"
584
+ puts " Invalid records: #{invalid_records.length}"
585
+
586
+ puts "\n" + "=" * 80
587
+ puts "PIS Utils Examples Complete!"
588
+ puts "=" * 80