# Posted By

mabafu on 10/27/11

# Statistics

Viewed 864 times
Favorited by 0 user(s)

# CPF and CNPJ validation classes using the Brazilian Government official algorithms

/ Published in: Ruby

CPF and CNPJ are self-validated codes generated by Brazilian government. Being the CPF used to identify persons and CNJP to enterprises, organizations and so on.

That said, I use to code the CPF/CNPJ algorithm when learning new programming languages. With Ruby, it got very clean and powerful because it's particular way to deal with "closures" (i.e. the ruby blocks, Procs and lambdas).

To use Cpf or Cnpj classes, just instantite the respective classes passing the numbers to be validated. CPF has 11 digits and CNPJ has 14. In both cases the last two digits are calculated based on the previous ones.

Module11 is the parent class of Cpf and Cnpj. You can use this class if you want to implement your own Module 11 validation algorithm. In this case, inherit from Module11 and initialize the new class with the proper parameters (i.e. input, formula, size, number_of_digits)

Copy this code and paste it in your HTML
1. # Generic Module 11 validator
2.
3. class Module11
4. protected
5. #returns the next validation 'digit' of the 'input'.
6. #It will calcultes the next 'digit' based on the
7. #given 'formula' (as block)
8. def Module11.getDigit (input, formula)
9. digit = 0
10. input.each_with_index do |item, index|
11. #passing the current item, its index and the whole array
12. #to the formula
13. digit += formula.call(item, index, input)
14. end
15. digit = 11 - (digit % 11)
16. digit = 0 if digit > 9
17.
18. return digit
19. end
20.
21. #calculates the new 'input' digits based on the given 'formula'
22. #and the 'size' of the desired 'output' array
23. def Module11.calculate (input, formula, size)
24. output = Array.new (input)
25. while output.size < size do
26. output << getDigit(output, formula)
27. end
28. return output
29. end
30.
31. public
33.
34. def initialize(input, formula, size, number_of_digits)
35. if input.kind_of? String
36. @value = input.scan(/\d/).collect{ |item| item.to_i }
37. else
38. @value = [0]
39. end
40.
41. if formula.kind_of? Proc
42. @formula = formula
43. else
44. @formula = nil
45. end
46.
47. if size.kind_of? Fixnum
48. @size = size
49. else
50. @size = 0
51. end
52.
53. if number_of_digits.kind_of? Fixnum
54. @number_of_digits = number_of_digits
55. else
56. @number_of_digits = 0
57. end
58.
59. if (@size > 0) and (@value.size > 0) and (@number_of_digits > 0) and (not @formula.nil?)
60. @result = Module11.calculate(@value[0,@size-@number_of_digits], @formula, @size)
61. else
62. @result = []
63. end
64. end
65.
66. def inspect
67. "< @value = " + @value.to_s + ">"
68. end
69.
70. def to_s
71. @value.join("")
72. end
73.
74. def is_valid?
75. @value == @result
76. end
77.
78. def validated
79. if is_valid?
80. self
81. else
82. Module11.new @result.join, @formula, @size, @number_of_digits
83. end
84. end
85.
86. def is_obvious?
87. @result.join("").to_i % ("1"*@size).to_i == 0
88. end
89.
90. def digits
91. if @value.size == @size
92. @value[@size-@number_of_digits, @number_of_digits]
93. else
94. []
95. end
96. end
97.
98. end
99.
100. class Cpf < Module11
101. private
102. def Cpf.formula
103. Proc.new do |item, index, updatedInput|
104. item * (updatedInput.size + 1 - index)
105. end
106. end
107.
108. public
109. def initialize(input)
110. super input, Cpf.formula, 11, 2
111. end
112.
113. def validated
114. if is_valid?
115. self
116. else
117. Cpf.new @result.join
118. end
119. end
120. end
121.
122. class Cnpj < Module11
123. private
124. def Cnpj.formula
125. Proc.new do |item, index, updatedInput|
126. coefs = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
127. item * coefs[index+13-updatedInput.size]
128. end
129. end
130.
131. public
132. def initialize(input)
133. super input, Cnpj.formula, 14, 2
134. end
135.
136. def validated
137. if is_valid?
138. self
139. else
140. Cnpj.new @result.join
141. end
142. end
143. end