-
Notifications
You must be signed in to change notification settings - Fork 1
/
document.go
executable file
·180 lines (159 loc) · 4.17 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
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
package boleto
import (
"strconv"
"time"
)
const (
// min multiplier for module 10
minModule10 = 1
// Max multiplier for module 10
maxModule10 = 2
// min multiplier for module 11
minModule11 = 2
// Max multiplier for module 11
maxModule11 = 9
)
// Defines a document type,
// holds the data of the billet itself
// @Id identifier of your program orders/payments
// @FebrabanType is the document type according FEBRABAN,
// the default used is "DM" (Duplicata mercantil),
// Source: (http://www.bb.com.br/docs/pub/emp/empl/dwn/011DescrCampos.pdf)
// @Value valor do boleto
// @ValueTax taxa do boleto
// @ValueDiscount abatimento/desconto
// @ValueForfeit juros/multa
// @OurNumber Nosso numero
type Document struct {
Id int
Date time.Time
DateDue time.Time
Value int
ValueTax int
ValueDiscount int
ValueForfeit int
OurNumber int
FebrabanType string
Instructions [6]string
Payer Payer
}
// dateDueFactor use a DateDue type time.Time to return a int,
// with is the quantity of days subsequents from 1997-10-07
func dateDueFactor(dateDue time.Time) int {
var dateDueFixed = time.Date(1997, 10, 07, 0, 0, 0, 0, time.UTC)
dif := dateDue.Sub(dateDueFixed)
factor := int(dif.Hours() / 24)
if factor <= 0 {
panic("Document.DateDue must be in the future")
}
return factor
}
// module10 takes a number and returns his verifier digit (spect an string
// because it may contain left zeros and pad numbers)
// Each digit that makes the Barcode digitable number is multiplied by his multiplier weight,
// the multipliers range from 2 to 1, from left to right
// Multiplication results are summed and divided by ten
func module10(s string, p int) int {
// initial multiplier weight, verify if range match
if p < minModule10 || p > maxModule10 {
p = maxModule10
}
// Create a slice with the numbers
total := 0
for _, r := range s {
c := string(r)
n, isDot := strconv.Atoi(c)
// if the multiplier weight is lower then minimal
if p < minModule10 {
p = maxModule10
}
// if the number could not be found, equals to "."
if isDot != nil {
p--
continue
}
// Multiply all numbers using multiplier weight
m := n * p
// If the multiplication result is higher then 9,
// the numbers must be summed between then,
// For example: m == 18, need to sum 1+8
if m > 9 {
// Convert to string and create a range
multipliers := strconv.Itoa(m)
numbers := []int{}
for _, number := range multipliers {
i, _ := strconv.Atoi(string(number))
numbers = append(numbers, i)
}
// Sum the slice of integers
m = 0
for _, number := range numbers {
m += number
}
}
total += m
p--
}
// End by dividing
dv := total % 10
if dv >= 10 {
dv = 0
}
return dv
}
// module11 takes a number and returns his verifier digit (spect an string
// because it may contain left zeros and pad numbers)
// Each digit that makes up our number is multiplied by his multiplier weight,
// the multipliers range from 9 to 2, from right to left
// Multiplication results are summed and divided by eleven
func module11(s string) int {
// Create a slice with the numbers
numbers := make([]int, len(s))
for i, r := range s {
c := string(r)
n, _ := strconv.Atoi(c)
numbers[i] = n
}
numbersLen := len(numbers)
// initial multiplier weight
var p = maxModule11
if numbersLen > 11 {
p = minModule11
}
// Inverse the numbers creating for loop
// Multiply all numbers using multiplier weight
total := 0
for i := len(numbers) - 1; i >= 0; i-- {
n := numbers[i]
total += n * p
// If the numbers length is higher than 11,
// we need to inverse the min and max
if numbersLen > 11 {
p++
// if the multiplier weight is higher then max
if p > maxModule11 {
p = minModule11
}
continue
}
p--
// if the multiplier weight is lower then minimal
if p < minModule11 {
p = maxModule11
}
}
// If the numbers length is higher than 11,
// we need to divide also by 11
if numbersLen > 11 {
dv := total % 11
dv = 11 - dv
// If the verifier digit is equal 0, 10, 11,
// need to be always 1
if dv == 0 || dv == 10 || dv == 11 {
dv = 1
}
return dv
}
// End by dividing
return total % 11
}