-
Notifications
You must be signed in to change notification settings - Fork 7
/
document.go
120 lines (97 loc) · 2.54 KB
/
document.go
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
package internal
import (
"github.com/brazanation/go-documents/internal/calculator"
"regexp"
)
type DocumentType string
type Formattable interface {
Format() string
}
// Document base structure
type Document struct {
label DocumentType
number string
digit string
length int
numberOfDigits int
regexFormatter string
regexValidator string
calculator calculator.DigitCalculatable
}
func NewDocument(
label DocumentType,
number string,
length int,
numberOfDigits int,
regexFormatter string,
regexValidation string,
calculator calculator.DigitCalculatable) (Document, error) {
regex := regexp.MustCompile(`\D`)
n := regex.ReplaceAllString(number, ``)
d := Document{
label: label,
number: n,
length: length,
numberOfDigits: numberOfDigits,
regexFormatter: regexFormatter,
regexValidator: regexValidation,
calculator: calculator,
}
d.digit = d.extractCheckerDigit()
err := d.Assert()
if err != nil {
return Document{label: label, number: number}, err
}
return d, nil
}
func (d Document) Is (t DocumentType) bool {
return d.label == t
}
// String returns a string with the Document number unformatted
func (d Document) String() string {
return d.number
}
// Format returns a string with the Document number formatted
func (d Document) Format() string {
regex := regexp.MustCompile(d.regexValidator)
return regex.ReplaceAllString(d.number, d.regexFormatter)
}
// extractCheckerDigit returns the verificator digit of a Document
func (d Document) extractCheckerDigit() string {
runes := []rune(d.number)
digits := d.length - d.numberOfDigits
return string(runes[digits:d.length])
}
// extractBaseNumber returns the base number of a Cpf
func (d Document) extractBaseNumber() string {
baseDocument := ""
for k, digit := range []byte(d.number) {
if k <= (len(d.number) - int(d.numberOfDigits) - 1) {
baseDocument += string(digit)
}
}
return baseDocument
}
// Assert do the verifications to know if a Cpf is valid and not empty
func (d *Document) Assert() error {
if d.number == "" {
return NewEmptyErr(d.label)
}
if !d.isValid() {
return NewInvalidErr(d)
}
return nil
}
func (d Document) isValid() bool {
baseNumber := d.extractBaseNumber()
regex := regexp.MustCompile("^[" + string(baseNumber[0]) + "]+$")
isRepeated := regex.MatchString(baseNumber)
if isRepeated {
return false
}
digit := d.calculator.CalculateDigit(baseNumber)
return d.isSameDigit(digit)
}
func (d *Document) isSameDigit(digit string) bool {
return d.digit == digit
}