From 5937622ca28939c99d3ecfe5e2911d332938b15f Mon Sep 17 00:00:00 2001 From: Semen Shaplygin Date: Sun, 7 Jan 2024 20:30:43 +0100 Subject: [PATCH 01/10] Update README.md --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index d85475c..21c295f 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,6 @@ It is not production ready public API! It is API could be change it the future. Status of implementation by code package: -- [ ] OGRN - - [ ] Generate method - - [x] Validate method -- [ ] OGRNIP - - [ ] Generate method - - [x] Validate method - [ ] OKATO - [ ] Generate method - [ ] Validate method @@ -25,7 +19,7 @@ Status of implementation by code package: - [ ] Generate method - [x] Validate method -Full supported codes: BIK, INN, KPP +Full supported codes: BIK, INN, KPP, OGRN, OGRNIP ## Usage From 7c53bf5656b4cd0b721417d401d7317c4bbc912c Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Sun, 7 Jan 2024 21:47:29 +0100 Subject: [PATCH 02/10] add: snils --- BENCHMARKS.md | 20 ++++++++++ README.md | 5 +-- generate.go | 3 ++ snils/models.go | 91 +++++++++++++++++++++++++++++++++++++++++++++ snils/snils.go | 35 +++-------------- snils/snils_test.go | 21 +++++++++-- types.go | 1 + utils/helpers.go | 2 +- validate.go | 3 ++ 9 files changed, 142 insertions(+), 39 deletions(-) diff --git a/BENCHMARKS.md b/BENCHMARKS.md index 1d1b523..8354b6f 100644 --- a/BENCHMARKS.md +++ b/BENCHMARKS.md @@ -1,5 +1,13 @@ # Benchmarks +## Notice + +Command to update result: + +```bash +go test -benchmem -run=^$ -bench . github.com/sshaplygin/docs-code/snils >> BENCHMARKS.md +``` + ## BIK ``` @@ -62,3 +70,15 @@ BenchmarkGenerate-10 403179 3100 ns/op 1010 B/op 46 PASS ok github.com/sshaplygin/docs-code/ogrnip 3.411s ``` + +## SNILS + +``` +goos: darwin +goarch: arm64 +pkg: github.com/sshaplygin/docs-code/snils +BenchmarkValidateCorrect-10 4451258 263.2 ns/op 336 B/op 5 allocs/op +BenchmarkGenerate-10 1302042 895.3 ns/op 568 B/op 25 allocs/op +PASS +ok github.com/sshaplygin/docs-code/snils 3.768s +``` diff --git a/README.md b/README.md index 21c295f..52a2721 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,8 @@ Status of implementation by code package: - [ ] OKATO - [ ] Generate method - [ ] Validate method -- [ ] SNILS - - [ ] Generate method - - [x] Validate method -Full supported codes: BIK, INN, KPP, OGRN, OGRNIP +Full supported codes: BIK, INN, KPP, OGRN, OGRNIP, SNILS ## Usage diff --git a/generate.go b/generate.go index e5f6345..2d7b16e 100644 --- a/generate.go +++ b/generate.go @@ -6,6 +6,7 @@ import ( "github.com/sshaplygin/docs-code/kpp" "github.com/sshaplygin/docs-code/ogrn" "github.com/sshaplygin/docs-code/ogrnip" + "github.com/sshaplygin/docs-code/snils" ) type GenerateFunc func() string @@ -23,6 +24,8 @@ func Generate(docType DocType) string { callFunc = ogrn.Generate case OGRNIP: callFunc = ogrnip.Generate + case SNILS: + callFunc = snils.Generate } if callFunc == nil { diff --git a/snils/models.go b/snils/models.go index a7c2471..06918ce 100644 --- a/snils/models.go +++ b/snils/models.go @@ -1,3 +1,94 @@ package snils +import ( + "fmt" + "strconv" + "strings" + + "github.com/sshaplygin/docs-code/models" + "github.com/sshaplygin/docs-code/utils" +) + const packageName = "snils" + +type Numbers []int + +const checkSumLength = 2 + +type checkSum int + +type SNILSStruct struct { + numbers Numbers + checkSum checkSum +} + +func (ss *SNILSStruct) String() string { + var res strings.Builder + res.Grow(snilsFullLength) + + for i := 0; i < len(ss.numbers); i++ { + if i%3 == 0 && i != 0 { + res.WriteString("-") + } + res.WriteString(strconv.Itoa(ss.numbers[i])) + } + + res.WriteString(" ") + res.WriteString(utils.StrCode(int(ss.checkSum), checkSumLength)) + + return res.String() +} + +func (ss *SNILSStruct) IsValid() (bool, error) { + return ss.calculateCheckSum() == ss.checkSum, nil +} + +const ( + snilsFullLength = 14 + snilsShrinkLength = 11 +) + +func ParseSNILS(snils string) (*SNILSStruct, error) { + if len(snils) != snilsFullLength { + return nil, &models.CommonError{ + Method: packageName, + Err: models.ErrInvalidLength, + } + } + + fSnils := strings.ReplaceAll(snils, "-", "") + fSnils = strings.ReplaceAll(fSnils, " ", "") + + if len(fSnils) != snilsShrinkLength { + return nil, ErrInvalidFormattedLength + } + + snilsArr, err := utils.StrToArr(fSnils) + if err != nil { + return nil, fmt.Errorf("parse raw %s: %w", packageName, err) + } + + return &SNILSStruct{ + numbers: Numbers(snilsArr[:len(snilsArr)-2]), + checkSum: checkSum(utils.SliceToInt(snilsArr[len(snilsArr)-2:])), + }, nil +} + +func NewSNILS() *SNILSStruct { + data := &SNILSStruct{ + numbers: Numbers(utils.CodeToInts(int(utils.RandomDigits(9)))), + } + + data.checkSum = data.calculateCheckSum() + + return data +} + +func (ss *SNILSStruct) calculateCheckSum() checkSum { + var hashSum int + for i, v := range ss.numbers { + hashSum += v * (len(ss.numbers) - i) + } + + return checkSum(hashSum % 101 % 100) +} diff --git a/snils/snils.go b/snils/snils.go index 82b9d5c..09f7f1f 100644 --- a/snils/snils.go +++ b/snils/snils.go @@ -1,46 +1,21 @@ package snils import ( - "strconv" - "strings" - - "github.com/sshaplygin/docs-code/models" - "github.com/sshaplygin/docs-code/utils" + "fmt" ) // Validate check to valid SNILS format // example: input format is 112-233-445 95 func Validate(snils string) (bool, error) { - if len(snils) != 14 { - return false, &models.CommonError{ - Method: packageName, - Err: models.ErrInvalidLength, - } - } - - fSnils := strings.ReplaceAll(snils, "-", "") - fSnils = strings.ReplaceAll(fSnils, " ", "") - - if len(fSnils) != 11 { - return false, ErrInvalidFormattedLength - } - - snilsArr, err := utils.StrToArr(fSnils) + snilsData, err := ParseSNILS(snils) if err != nil { - return false, err - } - - hashSum := 0 - hashLen := len(fSnils) - 2 - code, _ := strconv.Atoi(fSnils[hashLen:]) - for i, v := range snilsArr[:hashLen] { - hashSum += v * (hashLen - i) + return false, fmt.Errorf("parse %s model: %w", packageName, err) } - return hashSum%101 == code, nil + return snilsData.IsValid() } // Generate generate random func Generate() string { - panic("not implemented!") + return NewSNILS().String() } diff --git a/snils/snils_test.go b/snils/snils_test.go index 9666213..de5e78b 100644 --- a/snils/snils_test.go +++ b/snils/snils_test.go @@ -75,7 +75,6 @@ func TestValidate(t *testing.T) { }, { Code: "112-233-445 98", - Error: nil, IsValid: false, }, { @@ -85,7 +84,6 @@ func TestValidate(t *testing.T) { }, { Code: "112-233-445 95", - Error: nil, IsValid: true, }, { @@ -109,7 +107,22 @@ func TestValidate(t *testing.T) { } func Test_Generate(t *testing.T) { - require.Panics(t, func() { + for i := 0; i < 10; i++ { + snils := Generate() + isValid, err := Validate(snils) + require.NoError(t, err, fmt.Sprintf("invalid ogrnip value: %s", snils)) + + assert.True(t, isValid) + } +} + +func BenchmarkValidateCorrect(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = Validate("112-233-445 95") + } +} +func BenchmarkGenerate(b *testing.B) { + for i := 0; i < b.N; i++ { Generate() - }) + } } diff --git a/types.go b/types.go index 4075b3f..db22b59 100644 --- a/types.go +++ b/types.go @@ -8,4 +8,5 @@ const ( KPP OGRN OGRNIP + SNILS ) diff --git a/utils/helpers.go b/utils/helpers.go index cef0a99..56f4037 100644 --- a/utils/helpers.go +++ b/utils/helpers.go @@ -81,7 +81,7 @@ func StrCode(val, length int) string { n := length if len(code) > length { - panic(fmt.Sprintf("invalid int code length: %d, %d", len(code), length)) + panic(fmt.Sprintf("invalid int code '%s' length: %d, %d", code, len(code), length)) } str.Grow(n) diff --git a/validate.go b/validate.go index ccde492..bc4c1ce 100644 --- a/validate.go +++ b/validate.go @@ -6,6 +6,7 @@ import ( "github.com/sshaplygin/docs-code/kpp" "github.com/sshaplygin/docs-code/ogrn" "github.com/sshaplygin/docs-code/ogrnip" + "github.com/sshaplygin/docs-code/snils" ) type ValidateFunc func(code string) (bool, error) @@ -23,6 +24,8 @@ func Validate(docType DocType, code string) (bool, error) { callFunc = ogrn.Validate case OGRNIP: callFunc = ogrnip.Validate + case SNILS: + callFunc = snils.Validate } if callFunc == nil { From e37151cc8b0b33d52123115924236168601f6483 Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Sun, 7 Jan 2024 22:07:05 +0100 Subject: [PATCH 03/10] fix --- fts/fts.go | 2 +- fts/tax_departs.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/fts/fts.go b/fts/fts.go index 6843060..0761c18 100644 --- a/fts/fts.go +++ b/fts/fts.go @@ -150,7 +150,7 @@ func (csc ConstitutionRegionCode) Ints() []int { } func GenerateConstitutionSubjectCode() ConstitutionRegionCode { - return regionsCodes[utils.Random(0, len(regionsCodes)-1)] + return supportedRegionsCodes[utils.Random(0, len(supportedRegionsCodes)-1)] } type RegionTaxServiceNumber int diff --git a/fts/tax_departs.go b/fts/tax_departs.go index 9caefb0..c9dfae3 100644 --- a/fts/tax_departs.go +++ b/fts/tax_departs.go @@ -5,6 +5,8 @@ type TaxDepart struct { Branches map[RegionTaxServiceNumber]string } +var supportedRegionsCodes []ConstitutionRegionCode + var SupportedTaxDepartments = map[ConstitutionRegionCode]TaxDepart{ 0: { Name: `Федеральная налоговая служба`, @@ -1556,8 +1558,7 @@ var SupportedTaxDepartments = map[ConstitutionRegionCode]TaxDepart{ }, }, 84: { - Name: `Межрайонная инспекция Федеральной налоговой службы №2 по Красноярскому краю, Таймырскому (Долгано-Ненецкому) и Эвенкийскому автономным округам`, - Branches: map[RegionTaxServiceNumber]string{}, + Name: `Межрайонная инспекция Федеральной налоговой службы №2 по Красноярскому краю, Таймырскому (Долгано-Ненецкому) и Эвенкийскому автономным округам`, }, 86: { Name: `Управление Федеральной налоговой службы по Ханты-Мансийскому автономному округу - Югре`, @@ -1588,8 +1589,7 @@ var SupportedTaxDepartments = map[ConstitutionRegionCode]TaxDepart{ }, }, 88: { - Name: `Межрайонная инспекция Федеральной налоговой службы №3 по Красноярскому краю, Таймырскому (Долгано-Ненецкому) и Эвенкийскому автономным округам`, - Branches: map[RegionTaxServiceNumber]string{}, + Name: `Межрайонная инспекция Федеральной налоговой службы №3 по Красноярскому краю, Таймырскому (Долгано-Ненецкому) и Эвенкийскому автономным округам`, }, 89: { Name: `Управление Федеральной налоговой службы по Ямало-Ненецкому автономному округу`, @@ -1628,3 +1628,10 @@ var SupportedTaxDepartments = map[ConstitutionRegionCode]TaxDepart{ }, }, } + +func init() { + supportedRegionsCodes = make([]ConstitutionRegionCode, 0, len(SupportedTaxDepartments)) + for region := range SupportedTaxDepartments { + supportedRegionsCodes = append(supportedRegionsCodes, region) + } +} From 5bd165d7d7c521f049d7a697587761bf57692b9e Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 21:08:23 +0100 Subject: [PATCH 04/10] chore: update go mod --- go.mod | 2 +- parser/okato-states/go.mod | 8 +++--- parser/okato-states/go.sum | 55 +++++++++++++++++++++++++++++++------- parser/subjects/go.mod | 9 ++++--- parser/subjects/go.sum | 45 +++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index d40aa7a..ed2b6f1 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/sshaplygin/docs-code -go 1.21 +go 1.25 require github.com/stretchr/testify v1.8.4 diff --git a/parser/okato-states/go.mod b/parser/okato-states/go.mod index d1f2525..c2a33f5 100644 --- a/parser/okato-states/go.mod +++ b/parser/okato-states/go.mod @@ -1,10 +1,10 @@ module github.com/sshaplygin/docs-code/parser/okato-html -go 1.21.5 +go 1.25.0 require ( - github.com/PuerkitoBio/goquery v1.8.1 - golang.org/x/net v0.19.0 // indirect + github.com/PuerkitoBio/goquery v1.12.0 + golang.org/x/net v0.52.0 // indirect ) -require github.com/andybalholm/cascadia v1.3.1 // indirect +require github.com/andybalholm/cascadia v1.3.3 // indirect diff --git a/parser/okato-states/go.sum b/parser/okato-states/go.sum index e87cc27..bf43075 100644 --- a/parser/okato-states/go.sum +++ b/parser/okato-states/go.sum @@ -1,36 +1,71 @@ -github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= -github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= -github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= -github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= +github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo= +github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ= +github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= +github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/parser/subjects/go.mod b/parser/subjects/go.mod index 0ddc543..39a381d 100644 --- a/parser/subjects/go.mod +++ b/parser/subjects/go.mod @@ -1,9 +1,10 @@ module github.com/sshaplygin/docs-code/parser/subjects -go 1.21.5 +go 1.25.0 + +require github.com/PuerkitoBio/goquery v1.12.0 require ( - github.com/PuerkitoBio/goquery v1.8.1 // indirect - github.com/andybalholm/cascadia v1.3.1 // indirect - golang.org/x/net v0.7.0 // indirect + github.com/andybalholm/cascadia v1.3.3 // indirect + golang.org/x/net v0.52.0 // indirect ) diff --git a/parser/subjects/go.sum b/parser/subjects/go.sum index b83ff16..5127444 100644 --- a/parser/subjects/go.sum +++ b/parser/subjects/go.sum @@ -1,19 +1,45 @@ github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= +github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo= +github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= +github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= +github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -21,15 +47,34 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From ab7c2cbac03946e1e6100816ce87e9f21dd9d9f8 Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 21:10:31 +0100 Subject: [PATCH 05/10] ref: support protobuf enum compatibility --- types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types.go b/types.go index db22b59..941cf95 100644 --- a/types.go +++ b/types.go @@ -3,7 +3,7 @@ package docs_code type DocType uint const ( - BIK DocType = iota + BIK DocType = iota + 1 INN KPP OGRN From 51c9259343922ec4bee70eb07d8ba6b154ff572b Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 22:44:43 +0100 Subject: [PATCH 06/10] ref: to golangci lint v2 --- .github/workflows/go.yml | 78 +++++++++++++++++++--------------------- .golangci.yml | 50 ++++++++++++-------------- bik/bik_test.go | 10 ++---- inn/inn_test.go | 20 +++++------ kpp/kpp_test.go | 12 ++----- ogrn/models.go | 1 - ogrn/ogrn_test.go | 10 ++---- ogrnip/ogrnip_test.go | 9 ++--- okato/okato_test.go | 2 -- parser/bik/main.go | 12 ++++--- snils/snils_test.go | 9 ++--- types.go | 2 +- utils/helpers_test.go | 5 --- 13 files changed, 91 insertions(+), 129 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 22dfcee..b06b80b 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -5,9 +5,9 @@ name: Go on: push: - branches: [ "master" ] + branches: ["master"] pull_request: - branches: [ "master" ] + branches: ["master"] permissions: contents: read @@ -17,42 +17,38 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.21' - - - name: Build - run: go build -v ./... - - - name: Go Format - run: gofmt -s -w . && git diff --exit-code - - - name: Go Tidy - run: go mod tidy && git diff --exit-code - - - name: Go mod verify - run: go mod verify - - - name: Run linter - uses: golangci/golangci-lint-action@v3 - with: - version: latest - skip-cache: true - skip-pkg-cache: true - skip-build-cache: true - args: --timeout 3m --verbose - - - name: Test - run: go test -v ./... - - - name: Update coverage report - uses: ncruces/go-coverage-report@v0 - with: - report: true - chart: true - amend: true - if: github.event_name == 'push' - continue-on-error: true + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Build + run: go build -v ./... + + - name: Go Format + run: gofmt -s -w . && git diff --exit-code + + - name: Go Tidy + run: go mod tidy && git diff --exit-code + + - name: Go mod verify + run: go mod verify + + - name: Run linter + uses: golangci/golangci-lint-action@v9 + with: + args: --timeout 3m --verbose + + - name: Test + run: go test -v ./... -count=10 + + - name: Update coverage report + uses: ncruces/go-coverage-report@v0 + with: + report: true + chart: true + amend: true + if: github.event_name == 'push' + continue-on-error: true diff --git a/.golangci.yml b/.golangci.yml index 6398ede..5f764b4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,48 +1,42 @@ # More info on config here: https://github.com/golangci/golangci-lint#config-file +version: "2" + run: - deadline: 10s - issues-exit-code: 1 + timeout: 10s tests: true - skip-dirs-use-default: true - skip-dirs: - - bin - - vendor - - tests output: - format: colored-line-number - print-issued-lines: true - print-linter-name: true - -linters-settings: - govet: - check-shadowing: true - golint: - min-confidence: 0 - dupl: - threshold: 100 - goconst: - min-len: 2 - min-occurrences: 2 - + formats: + text: + path: stdout + print-linter-name: true + colors: true linters: - disable-all: true + default: none enable: - unused - - stylecheck - - gosimple - govet - errcheck - ineffassign - - typecheck - dupl - goconst - - goimports - - megacheck - gosec - gocritic - staticcheck + settings: + govet: + enable: + - shadow + dupl: + threshold: 100 + goconst: + min-len: 2 + min-occurrences: 2 + +formatters: + enable: + - goimports issues: exclude-use-default: false diff --git a/bik/bik_test.go b/bik/bik_test.go index e16dce5..1a2897a 100644 --- a/bik/bik_test.go +++ b/bik/bik_test.go @@ -40,8 +40,6 @@ func TestValidate(t *testing.T) { } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) if err != nil { require.ErrorAs(t, err, &tc.Error, fmt.Sprintf("invalid test case %d: input: %s", i, tc.Code)) @@ -87,8 +85,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) if err != nil { require.ErrorAs(t, err, &tc.Error, fmt.Sprintf("invalid test case %d: input: %s", i, tc.Code)) @@ -102,7 +98,7 @@ func TestValidate(t *testing.T) { } func Test_Generate(t *testing.T) { - for i := 0; i < 10; i++ { + for range 10 { bik := Generate() isValid, err := Validate(bik) require.NoError(t, err, fmt.Sprintf("invalid bik value: %s", bik)) @@ -119,12 +115,12 @@ func Test_Exists(t *testing.T) { } func BenchmarkValidateCorrect(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("044525225") } } func BenchmarkGenerate(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Generate() } } diff --git a/inn/inn_test.go b/inn/inn_test.go index a317f08..a75f4b5 100644 --- a/inn/inn_test.go +++ b/inn/inn_test.go @@ -40,8 +40,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code) if err != nil { @@ -83,8 +81,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code) if err != nil { @@ -102,7 +98,7 @@ func TestGenerate(t *testing.T) { t.Run("generate legal inn", func(t *testing.T) { var inn string - for i := 0; i < 10; i++ { + for range 10 { inn = GenerateLegal() isValid, err := Validate(inn) require.NoError(t, err, inn) @@ -114,7 +110,7 @@ func TestGenerate(t *testing.T) { t.Run("generate physical inn", func(t *testing.T) { var inn string - for i := 0; i < 10; i++ { + for range 10 { inn = GeneratePhysical() isValid, err := Validate(inn) require.NoError(t, err, inn) @@ -126,7 +122,7 @@ func TestGenerate(t *testing.T) { t.Run("generate random inn", func(t *testing.T) { var inn string - for i := 0; i < 10; i++ { + for range 10 { inn = Generate() isValid, err := Validate(inn) require.NoError(t, err, inn) @@ -137,31 +133,31 @@ func TestGenerate(t *testing.T) { } func BenchmarkValidateCorrectLegal(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("7707083893") } } func BenchmarkValidateCorrectPhysical(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("526317984689") } } func BenchmarkGenerate(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Generate() } } func BenchmarkGenerateLegal(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { GenerateLegal() } } func BenchmarkGeneratePhysical(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { GeneratePhysical() } } diff --git a/kpp/kpp_test.go b/kpp/kpp_test.go index 819dce7..da15746 100644 --- a/kpp/kpp_test.go +++ b/kpp/kpp_test.go @@ -44,8 +44,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, isValid, tc.IsValid, fmt.Sprintf("invalid test case %d: input: %s", i, tc.Code)) if err != nil { @@ -86,8 +84,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, isValid, tc.IsValid, fmt.Sprintf("invalid test case %d: input: %s", i, tc.Code)) if err != nil { @@ -116,8 +112,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, isValid, tc.IsValid, fmt.Sprintf("invalid test case %d: input: %s", i, tc.Code)) if err != nil { @@ -130,7 +124,7 @@ func TestValidate(t *testing.T) { } func Test_Generate(t *testing.T) { - for i := 0; i < 10; i++ { + for range 10 { kpp := Generate() isValid, err := Validate(kpp) require.NoError(t, err, fmt.Sprintf("invalid kpp value: %s", kpp)) @@ -140,12 +134,12 @@ func Test_Generate(t *testing.T) { } func BenchmarkValidateCorrect(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("775001001") } } func BenchmarkGenerate(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Generate() } } diff --git a/ogrn/models.go b/ogrn/models.go index e5635da..7a61dbd 100644 --- a/ogrn/models.go +++ b/ogrn/models.go @@ -175,7 +175,6 @@ func ParseOGRN(requiredType OGRNType, ogrn string) (*OGRNStruct, error) { } if requiredType == Physical && len(ogrn) != physicalLength { - fmt.Println(requiredType, len(ogrn)) return nil, &models.CommonError{ Method: packageName, Err: models.ErrInvalidLength, diff --git a/ogrn/ogrn_test.go b/ogrn/ogrn_test.go index a369538..0ddd260 100644 --- a/ogrn/ogrn_test.go +++ b/ogrn/ogrn_test.go @@ -39,8 +39,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code) if err != nil { @@ -81,8 +79,6 @@ func TestValidate(t *testing.T) { } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code) if err != nil { @@ -95,7 +91,7 @@ func TestValidate(t *testing.T) { } func Test_Generate(t *testing.T) { - for i := 0; i < 10; i++ { + for range 10 { ogrn := Generate() isValid, err := Validate(ogrn) require.NoError(t, err, fmt.Sprintf("invalid ogrn value: %s", ogrn)) @@ -105,12 +101,12 @@ func Test_Generate(t *testing.T) { } func BenchmarkValidateCorrect(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("1027700132195") } } func BenchmarkGenerate(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Generate() } } diff --git a/ogrnip/ogrnip_test.go b/ogrnip/ogrnip_test.go index ca4b3b6..1a8ffaf 100644 --- a/ogrnip/ogrnip_test.go +++ b/ogrnip/ogrnip_test.go @@ -43,7 +43,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code) @@ -90,8 +89,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code, tc.IsValid) if err != nil { @@ -104,7 +101,7 @@ func TestValidate(t *testing.T) { } func Test_Generate(t *testing.T) { - for i := 0; i < 10; i++ { + for range 10 { ogrnip := Generate() isValid, err := Validate(ogrnip) require.NoError(t, err, fmt.Sprintf("invalid ogrnip value: %s", ogrnip)) @@ -114,12 +111,12 @@ func Test_Generate(t *testing.T) { } func BenchmarkValidateCorrect(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("304500116000157") } } func BenchmarkGenerate(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Generate() } } diff --git a/okato/okato_test.go b/okato/okato_test.go index 55adc12..17f7d7b 100644 --- a/okato/okato_test.go +++ b/okato/okato_test.go @@ -41,8 +41,6 @@ func Test_Validete(t *testing.T) { } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) if err != nil { require.ErrorAs(t, err, &tc.Error, fmt.Sprintf("invalid test case %d: input: %s", i, tc.Code)) diff --git a/parser/bik/main.go b/parser/bik/main.go index df6a3eb..664dd6d 100644 --- a/parser/bik/main.go +++ b/parser/bik/main.go @@ -19,17 +19,21 @@ func main() { checkErr(err) writer := devNull - fmt.Fprint(writer, "package main", "\n\n") + _, err = fmt.Fprint(writer, "package main", "\n\n") + checkErr(err) printAvailablesBiks(writer, &biks) } func printAvailablesBiks(writer io.Writer, biks *Biks) { - fmt.Fprint(writer, "var existsBIKs = map[string]string{", "\n") + _, err := fmt.Fprint(writer, "var existsBIKs = map[string]string{", "\n") + checkErr(err) for _, bik := range biks.BikRows { - fmt.Fprint(writer, "\t", `"`+bik.Bik+`": `+"`"+bik.Name+"`,", "\n") + _, err = fmt.Fprintf(writer, "\t\"%s\": `%s`,\n", bik.Bik, bik.Name) + checkErr(err) } - fmt.Fprint(writer, "}", "\n") + _, err = fmt.Fprint(writer, "}", "\n") + checkErr(err) } type Biks struct { diff --git a/snils/snils_test.go b/snils/snils_test.go index de5e78b..82dd678 100644 --- a/snils/snils_test.go +++ b/snils/snils_test.go @@ -43,7 +43,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code) @@ -93,8 +92,6 @@ func TestValidate(t *testing.T) { }, } for i, tc := range testCases { - tc := tc - isValid, err := Validate(tc.Code) assert.Equal(t, tc.IsValid, isValid, tc.Code, tc.IsValid) if err != nil { @@ -107,7 +104,7 @@ func TestValidate(t *testing.T) { } func Test_Generate(t *testing.T) { - for i := 0; i < 10; i++ { + for range 10 { snils := Generate() isValid, err := Validate(snils) require.NoError(t, err, fmt.Sprintf("invalid ogrnip value: %s", snils)) @@ -117,12 +114,12 @@ func Test_Generate(t *testing.T) { } func BenchmarkValidateCorrect(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = Validate("112-233-445 95") } } func BenchmarkGenerate(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Generate() } } diff --git a/types.go b/types.go index 941cf95..db22b59 100644 --- a/types.go +++ b/types.go @@ -3,7 +3,7 @@ package docs_code type DocType uint const ( - BIK DocType = iota + 1 + BIK DocType = iota INN KPP OGRN diff --git a/utils/helpers_test.go b/utils/helpers_test.go index 8b8950c..69fdb27 100644 --- a/utils/helpers_test.go +++ b/utils/helpers_test.go @@ -33,7 +33,6 @@ func Test_SliceToInt(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { assert.Equal(t, tc.want, SliceToInt(tc.in)) }) @@ -64,7 +63,6 @@ func Test_StrCode_ValidInput(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { assert.Equal(t, tc.want, StrCode(tc.val, tc.length)) }) @@ -92,7 +90,6 @@ func Test_Generate_InvalidInput(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.name, func(t *testing.T) { require.Panics(t, func() { StrCode(tc.val, tc.length) @@ -131,8 +128,6 @@ func Test_GenerateRandomDigits(t *testing.T) { var digits int64 for _, tc := range tests { - tc := tc - digits = RandomDigits(tc.len) assert.True(t, digits >= tc.min && digits <= tc.max) } From b6390e14ad45f9f71bd5d35b804e447028776c81 Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 22:47:59 +0100 Subject: [PATCH 07/10] fix: logic from unit tests --- fts/tax_departs.go | 3 +++ inn/models.go | 1 + 2 files changed, 4 insertions(+) diff --git a/fts/tax_departs.go b/fts/tax_departs.go index c9dfae3..e6b05ca 100644 --- a/fts/tax_departs.go +++ b/fts/tax_departs.go @@ -1632,6 +1632,9 @@ var SupportedTaxDepartments = map[ConstitutionRegionCode]TaxDepart{ func init() { supportedRegionsCodes = make([]ConstitutionRegionCode, 0, len(SupportedTaxDepartments)) for region := range SupportedTaxDepartments { + if _, ok := SupportedRegionsCodes[region]; !ok { + continue + } supportedRegionsCodes = append(supportedRegionsCodes, region) } } diff --git a/inn/models.go b/inn/models.go index 33bff18..7efbf98 100644 --- a/inn/models.go +++ b/inn/models.go @@ -124,6 +124,7 @@ func NewINN(innType INNType) *INNStruct { taxRegionCode: taxRegionCode, serialNumber: serialNumber, checkSums: GenerateCheckSums(innType, append(taxRegionCode.Ints(), serialNumber.Ints()...)), + t: innType, } } From afa72f53020c1710427eff7545f9480c4e0747c1 Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 22:54:47 +0100 Subject: [PATCH 08/10] ref: golangci lint --- .golangci.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5f764b4..3a3db86 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,6 +24,17 @@ linters: - gosec - gocritic - staticcheck + exclusions: + presets: + - comments + - std-error-handling + rules: + - linters: + - staticcheck + text: "ST1003" + - linters: + - staticcheck + text: "ST1000" settings: govet: enable: @@ -37,9 +48,3 @@ linters: formatters: enable: - goimports - -issues: - exclude-use-default: false - exclude: - - ST1003 - - ST1000 From bdf49f279b94205e57ab6771636533125a4260b3 Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 23:02:44 +0100 Subject: [PATCH 09/10] fix: lint errors --- inn/inn.go | 4 ++-- inn/models.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/inn/inn.go b/inn/inn.go index 194d3c2..3ab40fa 100644 --- a/inn/inn.go +++ b/inn/inn.go @@ -19,12 +19,12 @@ func Validate(inn string) (bool, error) { // Generate generate random type inn string value func Generate() string { - return NewINN(INNType(utils.RandomDigits(1) % 3)).String() + return NewINN(_supportedTypes[utils.Random(0, len(_supportedTypes)-1)]).String() } // GenerateLegal generate legal type inn string value func GenerateLegal() string { - return NewINN(INNType(utils.RandomDigits(1)%2 + 1)).String() + return NewINN(_supportedTypes[utils.Random(0, len(_supportedTypes)-1)]).String() } // GeneratePhysical generate physical type inn string value diff --git a/inn/models.go b/inn/models.go index 7efbf98..7731128 100644 --- a/inn/models.go +++ b/inn/models.go @@ -43,6 +43,12 @@ const ( ForeignLegal ) +var _supportedTypes = []INNType{ + Physical, + Legal, + ForeignLegal, +} + type SerialNumber struct { val int len int From 9d6a19cef3b508e04216dec0c326aabfbe79026b Mon Sep 17 00:00:00 2001 From: Saimon Shaplygin Date: Wed, 18 Mar 2026 23:12:59 +0100 Subject: [PATCH 10/10] update: docs --- README.md | 117 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 52a2721..88d9ba4 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,116 @@ # docs-code -[![GoDoc](https://godoc.org/github.com/sshaplygin/docs-code?status.svg)](https://godoc.org/github.com/sshaplygin/docs-code) [![Go Coverage](https://github.com/sshaplygin/docs-code/wiki/coverage.svg)](https://raw.githack.com/wiki/sshaplygin/docs-code/coverage.html) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/sshaplygin/docs-code/blob/master/LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/sshaplygin/docs-code)](https://goreportcard.com/report/github.com/sshaplygin/docs-code) +[![GoDoc](https://godoc.org/github.com/sshaplygin/docs-code?status.svg)](https://godoc.org/github.com/sshaplygin/docs-code) +[![Go Coverage](https://github.com/sshaplygin/docs-code/wiki/coverage.svg)](https://raw.githack.com/wiki/sshaplygin/docs-code/coverage.html) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/sshaplygin/docs-code/blob/master/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/sshaplygin/docs-code)](https://goreportcard.com/report/github.com/sshaplygin/docs-code) -It is validator about official of documents codes in Go +Go library for validation and generation of Russian official document codes. -## Alert +> **Note:** The API is not yet stable and may change in future versions. -It is not production ready public API! It is API could be change it the future. To be attentive for this. +## Supported Document Codes -## Status +| Code | Description | Validate | Generate | +|--------|------------------------------------------------------|:--------:|:--------:| +| BIK | Bank Identification Code (БИК) | + | + | +| INN | Taxpayer Identification Number (ИНН) | + | + | +| KPP | Tax Registration Reason Code (КПП) | + | + | +| OGRN | Primary State Registration Number (ОГРН) | + | + | +| OGRNIP | Primary State Registration Number for IE (ОГРНИП) | + | + | +| SNILS | Insurance Individual Account Number (СНИЛС) | + | + | +| OKATO | Russian Classification of Administrative Territories | - | - | -Status of implementation by code package: +## Requirements -- [ ] OKATO - - [ ] Generate method - - [ ] Validate method +- Go 1.25+ -Full supported codes: BIK, INN, KPP, OGRN, OGRNIP, SNILS +## Installation -## Usage - -``` bash +```bash go get github.com/sshaplygin/docs-code ``` -### Example +## Usage -```go +### Validate a document code +```go import ( "log" - - "github.com/sshaplygin/docs-code" -) -... + docs_code "github.com/sshaplygin/docs-code" +) isValid, err := docs_code.Validate(docs_code.INN, "526317984689") if err != nil { - log.Error(err) + log.Fatal(err) } if !isValid { - log.Println("INN is invalid") + log.Println("INN is invalid") } else { - log.Println("INN is valid") + log.Println("INN is valid") } ``` -## Documentation +### Generate a document code + +```go +import ( + "fmt" + + docs_code "github.com/sshaplygin/docs-code" +) + +code := docs_code.Generate(docs_code.INN) +fmt.Println("Generated INN:", code) +``` + +### Use a specific package directly + +Each document type also exposes its own package with additional functions: + +```go +import "github.com/sshaplygin/docs-code/inn" + +// Generate specific INN types +legalINN := inn.GenerateLegal() +physicalINN := inn.GeneratePhysical() + +// Validate +ok, err := inn.Validate("526317984689") +``` + +## Benchmarks + +See [BENCHMARKS.md](BENCHMARKS.md) for performance data. + +## Project Structure + +```text +docs-code/ +├── bik/ # BIK validation and generation +├── inn/ # INN validation and generation +├── kpp/ # KPP validation and generation +├── ogrn/ # OGRN validation and generation +├── ogrnip/ # OGRNIP validation and generation +├── okato/ # OKATO (in progress) +├── snils/ # SNILS validation and generation +├── fts/ # Federal Tax Service data (regions, departments) +├── models/ # Shared error types +├── utils/ # Internal helpers +└── parser/ # Data parsers (BIK, OKATO, subjects) +``` + +## References + +- [INN (ИНН)](https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80_%D0%BD%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%BF%D0%BB%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%89%D0%B8%D0%BA%D0%B0) +- [SNILS (СНИЛС)](http://www.consultant.ru/document/cons_doc_LAW_124607/68ac3b2d1745f9cc7d4332b63c2818ca5d5d20d0/) +- [OGRN (ОГРН)](https://ru.wikipedia.org/wiki/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B9_%D0%B3%D0%BE%D1%81%D1%83%D0%B4%D0%B0%D1%80%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D1%80%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80) +- [OGRNIP (ОГРНИП)](http://www.temabiz.com/terminy/chto-takoe-ogrnip.html) +- [BIK (БИК)](https://ru.wikipedia.org/wiki/%D0%91%D0%B0%D0%BD%D0%BA%D0%BE%D0%B2%D1%81%D0%BA%D0%B8%D0%B9_%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4) +- [KPP (КПП)](https://dic.academic.ru/dic.nsf/ruwiki/239834) + +## License -* Info about INN - [ИНН](https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80_%D0%BD%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%BF%D0%BB%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%89%D0%B8%D0%BA%D0%B0) -* Info about SNILS - [СНИЛС](http://www.consultant.ru/document/cons_doc_LAW_124607/68ac3b2d1745f9cc7d4332b63c2818ca5d5d20d0/) -* Info about OGRN - [ОГРН](https://ru.wikipedia.org/wiki/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B9_%D0%B3%D0%BE%D1%81%D1%83%D0%B4%D0%B0%D1%80%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D1%80%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%BE%D0%BC%D0%B5%D1%80) -* Info about OGRNIP - [ОГРНИП](http://www.temabiz.com/terminy/chto-takoe-ogrnip.html) -* Info about BIK - [БИК](https://ru.wikipedia.org/wiki/%D0%91%D0%B0%D0%BD%D0%BA%D0%BE%D0%B2%D1%81%D0%BA%D0%B8%D0%B9_%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4) -* Info about KPP - [КПП](https://dic.academic.ru/dic.nsf/ruwiki/239834) +[MIT](LICENSE)