brazilian_documents 0.1.1 → 0.1.2

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +263 -15
  4. data/br_documents.gemspec +5 -5
  5. data/lib/br_documents.rb +3 -0
  6. data/lib/br_documents/documents/cnpj.rb +7 -10
  7. data/lib/br_documents/documents/cpf.rb +7 -10
  8. data/lib/br_documents/documents/ie.rb +43 -0
  9. data/lib/br_documents/documents/ie/ac.rb +15 -0
  10. data/lib/br_documents/documents/ie/al.rb +50 -0
  11. data/lib/br_documents/documents/ie/am.rb +12 -0
  12. data/lib/br_documents/documents/ie/ap.rb +61 -0
  13. data/lib/br_documents/documents/ie/ba.rb +84 -0
  14. data/lib/br_documents/documents/ie/ba/base.rb +37 -0
  15. data/lib/br_documents/documents/ie/ba/digits8/modulo_10.rb +12 -0
  16. data/lib/br_documents/documents/ie/ba/digits8/modulo_11.rb +12 -0
  17. data/lib/br_documents/documents/ie/ba/digits9/modulo_10.rb +19 -0
  18. data/lib/br_documents/documents/ie/ba/digits9/modulo_11.rb +20 -0
  19. data/lib/br_documents/documents/ie/ba/modulo_10.rb +19 -0
  20. data/lib/br_documents/documents/ie/ba/modulo_11.rb +18 -0
  21. data/lib/br_documents/documents/ie/base.rb +79 -0
  22. data/lib/br_documents/documents/ie/ce.rb +14 -0
  23. data/lib/br_documents/documents/ie/df.rb +16 -0
  24. data/lib/br_documents/documents/ie/es.rb +12 -0
  25. data/lib/br_documents/documents/ie/go.rb +14 -0
  26. data/lib/br_documents/documents/ie/ma.rb +14 -0
  27. data/lib/br_documents/documents/ie/mg.rb +66 -0
  28. data/lib/br_documents/documents/ie/ms.rb +14 -0
  29. data/lib/br_documents/documents/ie/mt.rb +14 -0
  30. data/lib/br_documents/documents/ie/pa.rb +14 -0
  31. data/lib/br_documents/documents/ie/pb.rb +14 -0
  32. data/lib/br_documents/documents/ie/pe.rb +38 -0
  33. data/lib/br_documents/documents/ie/pe/current.rb +13 -0
  34. data/lib/br_documents/documents/ie/pe/legacy.rb +12 -0
  35. data/lib/br_documents/documents/ie/pi.rb +14 -0
  36. data/lib/br_documents/documents/ie/pr.rb +13 -0
  37. data/lib/br_documents/documents/ie/rj.rb +25 -0
  38. data/lib/br_documents/documents/ie/rn.rb +14 -0
  39. data/lib/br_documents/documents/ie/ro.rb +44 -0
  40. data/lib/br_documents/documents/ie/ro/current.rb +24 -0
  41. data/lib/br_documents/documents/ie/ro/legacy.rb +13 -0
  42. data/lib/br_documents/documents/ie/rr.rb +19 -0
  43. data/lib/br_documents/documents/ie/rs.rb +12 -0
  44. data/lib/br_documents/documents/ie/sc.rb +12 -0
  45. data/lib/br_documents/documents/ie/se.rb +14 -0
  46. data/lib/br_documents/documents/ie/sp.rb +38 -0
  47. data/lib/br_documents/documents/ie/sp/industry.rb +22 -0
  48. data/lib/br_documents/documents/ie/sp/rural.rb +21 -0
  49. data/lib/br_documents/documents/ie/to.rb +14 -0
  50. data/lib/br_documents/version.rb +1 -1
  51. metadata +47 -5
@@ -0,0 +1,43 @@
1
+ require_relative 'ie/base'
2
+
3
+ Dir[File.expand_path("ie/{**/**,**}.rb", File.dirname(__FILE__))].each {|file| require file }
4
+
5
+ module BRDocuments
6
+ module IE
7
+
8
+ AVAILABLE_STATES = [
9
+ 'AC',
10
+ 'AL',
11
+ 'AM',
12
+ 'AP',
13
+ 'BA',
14
+ 'CE',
15
+ 'DF',
16
+ 'ES',
17
+ 'GO',
18
+ 'MA',
19
+ 'MG',
20
+ 'MS',
21
+ 'MT',
22
+ 'PA',
23
+ 'PB',
24
+ 'PE',
25
+ 'PI',
26
+ 'PR',
27
+ 'RJ',
28
+ 'RN',
29
+ 'RO',
30
+ 'RR',
31
+ 'RS',
32
+ 'SE',
33
+ 'SP',
34
+ 'TO'
35
+ ]
36
+
37
+
38
+ def self.available_states
39
+ AVAILABLE_STATES
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ # http://www.sintegra.gov.br/Cad_Estados/cad_AC.html
2
+ module BRDocuments
3
+ class IE::AC < IE::Base
4
+
5
+ set_verify_digits_weights first: %w(4 3 2 9 8 7 6 5 4 3 2),
6
+ last: %w(5 4 3 2 9 8 7 6 5 4 3 2)
7
+
8
+ set_format_regexp %r{^(01)[-.]?(\d{3})[-.]?(\d{3})[\/-]?(\d{3})[-.]?(\d{2})}
9
+
10
+ set_pretty_format_mask %(%s.%s.%s/%s-%s)
11
+
12
+ set_fixed_digits [0, 1]
13
+
14
+ end
15
+ end
@@ -0,0 +1,50 @@
1
+ # http://www.sintegra.gov.br/Cad_Estados/cad_AL.html
2
+ module BRDocuments
3
+ class IE::AL < IE::Base
4
+
5
+ set_verify_digits_weights first: %w(9 8 7 6 5 4 3 2)
6
+
7
+ set_format_regexp %r{^(24)[-.]?(\d{3})[-.]?(\d{3})[-.]?(\d{1})}
8
+
9
+ set_pretty_format_mask %(%s.%s.%s-%s)
10
+
11
+ set_fixed_digits [2, 4]
12
+
13
+ COMPANIES_TYPES = {
14
+ "0": "Normal",
15
+ "3": "Produtor Rural",
16
+ "5": "Substituta",
17
+ "7": "Micro-Empresa Ambulante",
18
+ "8": "Micro-Empresa"
19
+ }
20
+
21
+ class << self
22
+ def companies_types_labels
23
+ COMPANIES_TYPES.values
24
+ end
25
+
26
+ def sample_company_type_digit
27
+ COMPANIES_TYPES.keys.sample.to_s
28
+ end
29
+
30
+ def generate_root_numbers
31
+ numbers = super
32
+ # force digit
33
+ numbers[2] = sample_company_type_digit.to_i
34
+
35
+ numbers
36
+ end
37
+
38
+ def company_type(number)
39
+ # .to_s.to_sym to avoid nil.to_sym
40
+ COMPANIES_TYPES[company_type_digit(number).to_s.to_sym]
41
+ end
42
+
43
+ def company_type_digit(number)
44
+ number = new(number).strip
45
+
46
+ number.match(/^\d{2}(\d{1})/) && $1
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ # http://www.sintegra.gov.br/Cad_Estados/cad_AM.html
2
+ module BRDocuments
3
+ class IE::AM < IE::Base
4
+
5
+ set_verify_digits_weights first: %w(9 8 7 6 5 4 3 2)
6
+
7
+ set_format_regexp %r{^(\d{2})[-.]?(\d{3})[-.]?(\d{3})[-.]?(\d{1})}
8
+
9
+ set_pretty_format_mask %(%s.%s.%s-%s)
10
+
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ # http://www.sintegra.gov.br/Cad_Estados/cad_AP.html
2
+ module BRDocuments
3
+ class IE::AP < IE::Base
4
+
5
+ set_verify_digits_weights first: %w(9 8 7 6 5 4 3 2)
6
+
7
+ set_format_regexp %r{^(03)[-.]?(\d{6})[-.]?(\d{1})}
8
+
9
+ set_pretty_format_mask %(%s.%s-%s)
10
+
11
+ set_fixed_digits [0, 3]
12
+
13
+ # In RANGE_VALUES we remove the first '0' character so
14
+ # numbers are't treated as octal numberss
15
+ # see: :obtain_range_aux_value method
16
+ RANGE_VALUES = {
17
+ 3000001..3017000 => [5, 0],
18
+ 3017001..3019022 => [9, 1]
19
+ }.freeze
20
+
21
+ DEFAULT_RANGE_CONF = [0, 0]
22
+
23
+ def range_aux_values_hash
24
+ range_conf = obtain_range_aux_value(@number.dup)
25
+
26
+ {
27
+ :p => range_conf[0],
28
+ :d => range_conf[1]
29
+ } # equivalent to Hash[[:p, :d].zip(range_conf)]
30
+ end
31
+
32
+ def reduce_digits_weights(number, weights)
33
+ range_aux_values_hash[:p] + super(number, weights)
34
+ end
35
+
36
+ def calc_verify_digit(quotient_rest)
37
+ if ([11].member?(get_division_modulo - quotient_rest))
38
+ return range_aux_values_hash[:d]
39
+ end
40
+
41
+ super
42
+ end
43
+
44
+ private
45
+ def obtain_range_aux_value(number)
46
+ remove_verify_digits(number)
47
+
48
+ # remove first '0' digit so number is not a octal
49
+ number = (stripped(number)[1..-1]).to_i
50
+
51
+ # We try to check if `number` is include in one of the pre defined range
52
+ range_conf = RANGE_VALUES.map do |range, aux_values|
53
+ range.include?(number) ? aux_values : nil
54
+ end.compact
55
+
56
+ # One of the configured values or the default
57
+ range_conf.shift || DEFAULT_RANGE_CONF
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,84 @@
1
+ # This class is a wrapper/interface to glue all Bahia IE generators and validators
2
+ module BRDocuments
3
+ module IE::BA
4
+ class << self
5
+
6
+ DIGITS_MOD_10 = [0,1,2,3,4,5,8]
7
+ DIGITS_MOD_11 = [6,7,9]
8
+
9
+ # Delegate all methods to specific class
10
+ def method_missing(method, *args)
11
+ class_for_number(args[0]).public_send(method, *args)
12
+ end
13
+
14
+ def generate(formatted = true, digits_count = 9, modulo = 10)
15
+ generator_class(digits_count, modulo).generate(formatted)
16
+ end
17
+
18
+ def generate_root_numbers(digits_count = 9, modulo = 10)
19
+ generator_class(digits_count, modulo).generate_root_numbers
20
+ end
21
+
22
+ def class_for_number(number)
23
+ class_name = class_name_for_number(number)
24
+ IE::BA.const_get(class_name)
25
+ end
26
+
27
+ def rand_generate(formatted = true)
28
+ generate(formatted, rand_digits_count, rand_modulo)
29
+ end
30
+
31
+ protected
32
+ def generator_class(digits_count = 9, modulo = 10)
33
+ IE::BA.const_get("Digits#{digits_count}::Modulo#{modulo}")
34
+ end
35
+
36
+ def class_name_for_number(number)
37
+ [
38
+ digits_module_for(number),
39
+ modulo_class_for(number)
40
+ ].join("::")
41
+ end
42
+
43
+ def digits_module_for(number)
44
+ eight_digits?(number) ? "Digits8" : "Digits9"
45
+ end
46
+
47
+ def modulo_class_for(number)
48
+ number = normalize_number(number)
49
+
50
+ # for eigth numbers documents, the first digit is cheched
51
+ # otherwhise the second digit is checked
52
+ check_position = eight_digits?(number) ? 0 : 1
53
+ check_digit = number.slice(check_position, 1).to_i
54
+
55
+ DIGITS_MOD_11.member?(check_digit) ? 'Modulo11' : 'Modulo10'
56
+ end
57
+
58
+ def eight_digits?(number)
59
+ normalize_number(number).size == 8
60
+ end
61
+
62
+ def nine_digits?(number)
63
+ normalize_number(number).size == 9
64
+ end
65
+
66
+ def normalize_number(number)
67
+ number.to_s.gsub(/[^\d+]/, '')
68
+ end
69
+
70
+ def rand_digits_count
71
+ rand_boolean ? 9 : 8
72
+ end
73
+
74
+ def rand_modulo
75
+ (rand_boolean ? 10 : 11)
76
+ end
77
+
78
+ def rand_boolean
79
+ # 50%/50% of chance
80
+ rand(2) > 0
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,37 @@
1
+ # http://www.sintegra.gov.br/Cad_Estados/cad_BA.html
2
+ module BRDocuments
3
+ module IE
4
+ module BA
5
+ class Base < IE::Base
6
+
7
+ set_format_regexp %r{(\d{3})[-.]?(\d{3})[-.]?(\d{2,3})}
8
+
9
+ set_pretty_format_mask %(%s.%s.%s)
10
+
11
+ # I don't know why in Bahia they calculate the LAST digit FIRST and
12
+ # the FIRST digit LAST, wtf
13
+ def calculate_verify_digits
14
+ super.reverse
15
+ end
16
+
17
+ def self.valid_fixed_digits?(number)
18
+ number = new(number).normalize
19
+ fixed_numbers = self.const_get('FIXED_INITIAL_NUMBERS')
20
+
21
+ fixed_numbers.member?(number[fixed_digits_positions].to_s)
22
+ end
23
+
24
+ def self.fixed_digits
25
+ [super.sample.to_i]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ module BRDocuments::IE::BA
33
+ module Digits8
34
+ end
35
+ module Digits9
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../modulo_10'
2
+
3
+ module BRDocuments
4
+ module IE
5
+ class BA::Digits8::Modulo10 < IE::BA::Modulo10
6
+
7
+ set_verify_digits_weights first: %w(7 6 5 4 3 2),
8
+ last: %w(8 7 6 5 4 3 2)
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../modulo_11'
2
+
3
+ module BRDocuments
4
+ module IE
5
+ class BA::Digits8::Modulo11 < IE::BA::Modulo11
6
+ set_verify_digits_weights first: %w(7 6 5 4 3 2),
7
+ last: %w(8 7 6 5 4 3 2)
8
+
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,19 @@
1
+ require_relative '../modulo_10'
2
+
3
+ module BRDocuments
4
+ module IE
5
+ class BA::Digits9::Modulo10 < IE::BA::Modulo10
6
+
7
+ set_verify_digits_weights first: %w(8 7 6 5 4 3 2),
8
+ last: %w(9 8 7 6 5 4 3 2)
9
+
10
+
11
+ # 9 digits IE from bahia have FIXED NUMBER in the second position
12
+ INITIAL_FIX_NUMBERS_POSITION = 1
13
+
14
+ def fixed_digits_positions
15
+ self.const_get('INITIAL_FIX_NUMBERS_POSITION')
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../modulo_11'
2
+
3
+ module BRDocuments
4
+ module IE
5
+ class BA::Digits9::Modulo11 < IE::BA::Modulo11
6
+
7
+ set_verify_digits_weights first: %w(8 7 6 5 4 3 2),
8
+ last: %w(9 8 7 6 5 4 3 2)
9
+
10
+
11
+ # 9 digits IE from bahia have FIXED NUMBER in the second position
12
+ INITIAL_FIX_NUMBERS_POSITION = 1
13
+
14
+ def fixed_digits_positions
15
+ self.const_get('INITIAL_FIX_NUMBERS_POSITION')
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,19 @@
1
+ require_relative 'base'
2
+
3
+ # http://www.sintegra.gov.br/Cad_Estados/cad_BA.html
4
+ module BRDocuments
5
+ module IE
6
+ module BA
7
+ class Modulo10 < IE::BA::Base
8
+
9
+ # All documents generated through modulo 11 may start
10
+ # with one of theses values
11
+ FIXED_INITIAL_NUMBERS = %w(0 1 2 3 4 5 8)
12
+
13
+ # Force modulo 10
14
+ set_division_modulo 10
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'base'
2
+
3
+ # http://www.sintegra.gov.br/Cad_Estados/cad_BA.html
4
+ module BRDocuments
5
+ module IE
6
+ module BA
7
+ class Modulo11 < IE::BA::Base
8
+
9
+ # All documents generated through modulo 11 may start
10
+ # with one of theses values
11
+ FIXED_INITIAL_NUMBERS = %w(6 7 9)
12
+
13
+ # Force modulo 11
14
+ set_division_modulo 11
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,79 @@
1
+ # http://www.sintegra.gov.br/insc_est.html
2
+ module BRDocuments
3
+ module IE
4
+ class Base < ::DigitChecksum::BaseDocument
5
+ # MOD 11
6
+ set_division_modulo 11
7
+
8
+ # remove any non digit from document number
9
+ set_clear_number_regexp %r{[^(\d+)]}
10
+
11
+ # numbers sampled to generate new document numbers
12
+ set_generator_numbers (0..9).to_a
13
+
14
+ # Start from first position
15
+ INITIAL_FIX_NUMBERS_POSITION = 0
16
+ # No one
17
+ FIXED_INITIAL_NUMBERS = []
18
+
19
+ def valid?
20
+ return false unless valid_fixed_digits?
21
+
22
+ return super
23
+ end
24
+
25
+ def valid_fixed_digits?
26
+ return true unless validate_fixed_digits?
27
+
28
+ self.class.valid_fixed_digits?(self.number)
29
+ end
30
+
31
+ def validate_fixed_digits?
32
+ true
33
+ end
34
+
35
+ class << self
36
+ def valid_fixed_digits?(number)
37
+ number = new(number).normalize
38
+
39
+ initial_pos = fixed_digits_positions
40
+ fixed_numbers = fixed_digits
41
+
42
+ return (number.slice(initial_pos, fixed_numbers.size) == fixed_numbers)
43
+ end
44
+
45
+ def generate_root_numbers
46
+ numbers = (root_digits_count - fixed_digits.size).times.map {
47
+ get_generator_numbers.sample.to_i
48
+ }
49
+
50
+ append_fixed_digits(numbers)
51
+
52
+ numbers
53
+ end
54
+
55
+ def fixed_digits_positions
56
+ self.const_get('INITIAL_FIX_NUMBERS_POSITION')
57
+ end
58
+
59
+ def fixed_digits
60
+ self.const_get('FIXED_INITIAL_NUMBERS')
61
+ end
62
+
63
+ def set_fixed_digits(initial_numbers)
64
+ self.const_set('FIXED_INITIAL_NUMBERS', initial_numbers).freeze
65
+ end
66
+
67
+ protected
68
+ def append_fixed_digits(numbers)
69
+ fixed_digits.each_with_index {|number, index|
70
+ numbers.insert(fixed_digits_positions + index, number)
71
+ }
72
+
73
+ numbers
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end