cnpjgen/cnpj/generate.go
2026-07-16 11:30:46 -03:00

88 lines
1.4 KiB
Go

package cnpj
import (
"fmt"
"math/rand"
"strings"
)
var (
cnpjP1 = []int{5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2}
cnpjP2 = []int{6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2}
)
const alphaChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
func Generate() string {
return generate(false)
}
func GenerateAlpha() string {
return generate(true)
}
func generate(alpha bool) string {
for {
var b strings.Builder
b.Grow(14)
for range 12 {
if alpha {
b.WriteByte(alphaChars[rand.Intn(len(alphaChars))])
} else {
b.WriteByte(byte('0' + rand.Intn(10)))
}
}
s := b.String()
if isRepetitive(s) {
continue
}
dv1 := computeDV(s, cnpjP1, alpha)
s2 := s + string(byte('0'+dv1))
dv2 := computeDV(s2, cnpjP2, alpha)
return s + string(byte('0'+dv1)) + string(byte('0'+dv2))
}
}
func computeDV(s string, table []int, alpha bool) int {
total := 0
for i, w := range table {
c := s[i]
var val int
if alpha {
val = alphaValue(rune(c))
} else {
val = int(c - '0')
}
total += val * w
}
r := total % 11
if r >= 2 {
return 11 - r
}
return 0
}
func alphaValue(r rune) int {
return int(r) - 48
}
func isRepetitive(s string) bool {
if len(s) == 0 {
return false
}
c := s[0]
for i := 1; i < len(s); i++ {
if s[i] != c {
return false
}
}
return true
}
func Format(cnpj string) string {
if len(cnpj) != 14 {
return cnpj
}
return fmt.Sprintf("%s.%s.%s/%s-%s",
cnpj[:2], cnpj[2:5], cnpj[5:8], cnpj[8:12], cnpj[12:])
}