This commit is contained in:
Andrey Parhomenko 2024-03-27 12:51:48 +05:00
commit c54d17ee30
5 changed files with 294 additions and 0 deletions

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module vultras.su/core/biz
go 1.21.8

11
inns/errors.go Normal file
View file

@ -0,0 +1,11 @@
package inns
import (
"errors"
)
var (
IncorrectFormatErr = errors.New("incorrect INN format")
IncorrectLenErr = errors.New("incorrect INN length")
SumsNotMatchErr = errors.New("control sums do not match")
)

80
inns/inns_test.go Normal file
View file

@ -0,0 +1,80 @@
package inns
import (
"testing"
)
var (
testStrInns = []string{
"663802 397223",
"8252 47222169",
"8712530 92145",
"0873 820 72512",
"227 62 3382327",
"886 62 2222010",
"464 350 209157",
"758956582077",
"212551260755",
"0432444 61455",
"428880301819",
"61309 59 33498",
"667344101205",
"6189115998",
"426 1455105",
"562 5340715",
"6588135629",
"253 7102466",
"8195196 357",
"23838 17246",
"812 5976843",
"4710 107563",
"3732 71726",
"2170 439945",
"2193865 820",
"8122 281402",
}
testStrInnsErr = []string{
"66380a2397223",
"825247222eu169",
"8712530921457553",
"087753382072512",
"22762hetu3382327",
"886ao622222010",
"4643he50209157",
"75895 te 6582077",
"2asn12551260755",
"043abc244461455",
"428880err301819",
"0x613095933498",
"667344101205h",
"618911xerr5998",
"426x1455105",
"562x5340715",
"658813moreerr5629",
"253x7102466",
"8195196x357",
"23check838 17246",
"8check12x5976843",
"4710x107563",
"03732x71726",
"2170x439945",
"2193865x820",
"81shit2 281402",
}
)
func TestInnFromStr(t *testing.T) {
for _, rawInn := range testStrInns {
_, err := NewFromStr(rawInn)
if err != nil {
t.Fatalf("InnFromStr(%q), err == %q", rawInn, err)
}
}
for _, rawInn := range testStrInnsErr {
_, err := NewFromStr(rawInn)
if err == nil {
t.Fatalf("InnFromStr(%q), err == %v, must be though", rawInn, err)
}
}
}

193
inns/main.go Normal file
View file

@ -0,0 +1,193 @@
package inns
// The package implements the basic
// Russian Federation INN format
// storing it in int64 to keep
// searching and storing as
// quick as possible.
import (
"strings"
"unicode"
"strconv"
"fmt"
"slices"
)
type InnType uint8
const (
IncorrectInnType InnType = iota
LegalInnType
IndividualInnType
)
func removeSpaces(s string) string {
return strings.Map(func(r rune) rune{
if unicode.IsSpace(r) {
return -1
}
return r
}, s)
}
type Inn int64
func NewFromInt64(innRaw int64) (Inn, error) {
inn := Inn(innRaw)
if !inn.isCorrectLen() {
return -1, IncorrectLenErr
}
if !inn.isSumCorrect() {
return -1, SumsNotMatchErr
}
return inn, nil
}
// Convert string with spaces into the INN
// and return error if anything is wrong with it.
func NewFromStr(str string) (Inn, error) {
str = removeSpaces(str)
innRaw, err := strconv.ParseInt(str, 10, 64)
if err != nil {
return -1, IncorrectFormatErr
}
return NewFromInt64(innRaw)
}
func (inn Inn) Type() InnType {
ln := inn.length()
switch ln {
case 9, 10:
return LegalInnType
case 11, 12:
return IndividualInnType
}
return IncorrectInnType
}
func (inn Inn) length() int {
ln := 0
for {
if inn == 0 {
break
}
inn /= 10
ln++
}
if ln == 9 || ln == 11 {
ln++
}
return ln
}
func (inn Inn) isCorrectLen() bool {
ln := inn.length()
if ln == 9 || ln == 11 {
ln++
}
return ln == 10 || ln == 12
}
var (
// Koefs for the control sum.
innSum10 = [9]int64{
2, 4, 10, 3, 5, 9, 4, 6, 8,
}
innSum11 = [10]int64{
7, 2, 4, 10, 3, 5, 9, 4, 6, 8,
}
innSum12 = [11]int64{
3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8,
}
)
// Get the integer representation of digits in string INN.
func (inn Inn) digits() []int64 {
ln := inn.length()
v := int64(inn)
ret := make([]int64, ln)
for i := 0 ; i<ln ; i++{
ret[i] = v % 10
v /= 10
}
slices.Reverse(ret)
return ret
}
//
func (inn Inn) specifiedSum() int64 {
ln := inn.length()
v := int64(inn)
switch ln {
case 10:
return v%10
case 12:
return v%100
default:
return -1
}
}
// Returns the supposed control sum rune. (the last number)
func (inn Inn) sum() int64 {
d := inn.digits()
ln := inn.length()
switch ln {
case 10 :
var n10 int64
for i, ni := range d[:9] {
n10 += innSum10[i] * ni
}
n10 = (n10 % 11) % 10
return n10
case 12 :
var n11 int64
for i, ni := range d[:10] {
n11 += innSum11[i] * ni
}
n11 = (n11 % 11) % 10
var n12 int64
for i, ni := range d[:10] {
n12 += innSum12[i] * ni
}
n12 += innSum12[10] * n11
n12 = (n12 % 11) % 10
return n11*10 + n12
}
return -1
}
func (inn Inn) isSumCorrect() bool {
return inn.specifiedSum() == inn.sum()
}
func (inn Inn) String() string {
return fmt.Sprintf("%d", inn)
}
// Fancy way to print INN with space delimiters.
func (inn Inn) Fancy() string {
ln := inn.length()
str := fmt.Sprintf("%d", inn)
// Adding zero depending on length.
if len(str) == 9 || len(str) == 11 {
str = "0"+str
}
switch ln {
case 10 :
return fmt.Sprintf("%s %s %s", str[:4], str[4:9], str[9:])
case 12 :
return fmt.Sprintf("%s %s %s", str[:4], str[4:10], str[10:])
}
// Reaching the point if the length is incorrect.
return "<"+IncorrectLenErr.Error()+">"
}

7
main.go Normal file
View file

@ -0,0 +1,7 @@
package main
// The package contains
// business related types and functions
// that are used across related applications
// and packages.