Skip to content

Commit 2f8990b

Browse files
committed
add: kpp
1 parent 33417bd commit 2f8990b

File tree

4 files changed

+60
-103
lines changed

4 files changed

+60
-103
lines changed

kpp/data.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package kpp
22

3-
var supportedRegistrationReason = map[RegistrationReason]string{
3+
var registrationsReasonsCodes []RegistrationReason
4+
5+
var supportedRegistrationsReasons = map[RegistrationReason]string{
46
"01": "Постановка на учет в налоговом органе российской организации в качестве налогоплательщика по месту ее нахождения",
57
"02": "Постановка на учет налогоплательщика - российской организации по месту нахождения ее филиала, исполняющего обязанности организации по уплате налогов и сборов",
68
"03": "Постановка на учет налогоплательщика - российской организации по месту нахождения ее филиала, не исполняющего обязанности организации по уплате налогов и сборов",
@@ -49,3 +51,10 @@ var supportedRegistrationReason = map[RegistrationReason]string{
4951
"76": "Постановка на учет иностранной организации, выступающей в качестве инвестора по соглашению о разделе продукции или оператора соглашения",
5052
"87": "Cчет иностранной (международной) организации в связи с открытием счетов в банках на территории Российской Федерации",
5153
}
54+
55+
func init() {
56+
registrationsReasonsCodes = make([]RegistrationReason, 0, len(supportedRegistrationsReasons))
57+
for code := range supportedRegistrationsReasons {
58+
registrationsReasonsCodes = append(registrationsReasonsCodes, code)
59+
}
60+
}

kpp/errors.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,12 @@ var (
66
// ErrNilKPP try call methods for nil kpp struct
77
ErrNilKPP = errors.New("nil kpp struct")
88

9-
// ErrRegistrationReasonCode invalid registration reason code
10-
ErrRegistrationReasonCode = errors.New("invalid registration reason code")
9+
// ErrInvalidTaxRegion invalid tax region code
10+
ErrInvalidTaxRegion = errors.New("invalid tax region code")
1111

12-
// ErrInvalidSubjectCode
13-
ErrInvalidSubjectCode = errors.New("")
12+
// ErrInvalidReasonCode invalid reason code
13+
ErrInvalidReasonCode = errors.New("invalid reason code")
1414

15-
// ErrInvalidRecorderCode
16-
ErrInvalidRecorderCode = errors.New("")
17-
18-
// ErrInvalidReasonCode
19-
ErrInvalidReasonCode = errors.New("")
20-
21-
// ErrInvalidSerialNumber
22-
ErrInvalidSerialNumber = errors.New("")
15+
// ErrInvalidSerialNumber invalid serial number
16+
ErrInvalidSerialNumber = errors.New("invalid serial number")
2317
)

kpp/kpp_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,11 @@ func TestValidate(t *testing.T) {
107107

108108
testCases := []testCase{
109109
{
110-
Code: "773643301",
111-
Error: ErrRegistrationReasonCode,
112-
IsValid: false,
110+
Code: "775001001",
111+
IsValid: true,
113112
},
114113
{
115114
Code: "773642301",
116-
Error: nil,
117115
IsValid: true,
118116
},
119117
}
@@ -132,7 +130,9 @@ func TestValidate(t *testing.T) {
132130
}
133131

134132
func Test_Generate(t *testing.T) {
135-
require.Panics(t, func() {
136-
Generate()
137-
})
133+
kpp := Generate()
134+
isValid, err := Validate(kpp)
135+
require.NoError(t, err, fmt.Sprintf("invalid kpp value: %s", kpp))
136+
137+
assert.True(t, isValid)
138138
}

kpp/models.go

Lines changed: 37 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"fmt"
55
"strings"
66

7-
"github.com/sshaplygin/docs-code/data"
7+
"github.com/sshaplygin/docs-code/fts"
88
"github.com/sshaplygin/docs-code/models"
99
"github.com/sshaplygin/docs-code/utils"
1010
)
@@ -15,22 +15,6 @@ const codeLength = 9
1515

1616
const validateErrorTmpl = "%w: %s"
1717

18-
// recorderCode
19-
const (
20-
recorderCodeLength = 2
21-
22-
minRecorderCodeNumber = 0
23-
maxRecorderCodeNumber = 99
24-
)
25-
26-
// reasonCode. // Could be from 0 to 9 and A to Z.
27-
const (
28-
reasonCodeLength = 2
29-
30-
minReasonCodeNumbers = 0
31-
maxReasonCodeNumbers = 99
32-
)
33-
3418
// serialNumber
3519
const (
3620
serialNumberLength = 3
@@ -40,66 +24,39 @@ const (
4024
)
4125

4226
type (
43-
// RecorderCode required length 2.
44-
// код Государственной налоговой инспекции, которая осуществляла постановку на учёт организации по месту её нахождения,
45-
// месту нахождения её филиалов и (или)
46-
// представительств, расположенных на территории РФ или по месту нахождения принадлежащего ей недвижимого имущества и транспортных средств;
47-
RecorderCode int
48-
49-
// RegistrationReason required length 2.
50-
// Could be from 0 to 9 and A to Z.
51-
// для российской организации от 01 до 50 (01 — по месту её нахождения);
52-
// для иностранной организации от 51 до 99;
27+
// RegistrationReason required length 2. Could be from 0 to 9 and A to Z.
28+
// Для российской организации от 01 до 50 (01 — по месту её нахождения).
29+
// Для иностранной организации от 51 до 99;
5330
RegistrationReason string
5431

5532
// SerialNumber required length 3.
56-
// порядковый номер постановки на учёт по соответствующей причине.
33+
// Порядковый номер постановки на учёт по соответствующей причине.
5734
SerialNumber int
5835
)
5936

60-
func (rc RecorderCode) String() string {
61-
// TODO:
62-
return ""
63-
}
64-
65-
func (rc RecorderCode) IsValid() bool {
66-
// TODO:
67-
return false
68-
}
69-
70-
func GenerateRecorderCode() RecorderCode {
71-
// TODO:
72-
return 0
73-
}
74-
7537
func (rr RegistrationReason) String() string {
76-
// TODO:
77-
return ""
38+
return string(rr)
7839
}
7940

8041
func (rr RegistrationReason) IsValid() bool {
81-
// TODO:
82-
return false
42+
_, ok := supportedRegistrationsReasons[rr]
43+
return ok
8344
}
8445

8546
func GenerateRegistrationReason() RegistrationReason {
86-
// TODO:
87-
return ""
47+
return registrationsReasonsCodes[utils.Random(0, len(registrationsReasonsCodes)-1)]
8848
}
8949

9050
func (sn SerialNumber) IsValid() bool {
91-
// TODO:
92-
return false
51+
return sn >= minSerialNumberNumbers && sn <= maxSerialNumberNumbers
9352
}
9453

9554
func (sn SerialNumber) String() string {
96-
// TODO:
97-
return ""
55+
return utils.StrCode(int(sn), serialNumberLength)
9856
}
9957

10058
func GenerateSerialNumber() SerialNumber {
101-
// TODO:
102-
return 0
59+
return SerialNumber(utils.RandomDigits(serialNumberLength))
10360
}
10461

10562
func ParseKPP(kpp string) (*KPPStruct, error) {
@@ -110,14 +67,9 @@ func ParseKPP(kpp string) (*KPPStruct, error) {
11067
}
11168
}
11269

113-
subjectCodeArr, err := utils.StrToArr(kpp[0:2])
114-
if err != nil {
115-
return nil, fmt.Errorf("parse subject code raw %s: %w", packageName, err)
116-
}
117-
118-
recorderCodeArr, err := utils.StrToArr(kpp[2:4])
70+
taxRegionCode, err := fts.ParseTaxRegionCode(kpp[0:4])
11971
if err != nil {
120-
return nil, fmt.Errorf("parse recorder code raw %s: %w", packageName, err)
72+
return nil, fmt.Errorf("parse tax region code raw %s: %w", packageName, err)
12173
}
12274

12375
servialNumberArr, err := utils.StrToArr(kpp[6:])
@@ -126,43 +78,37 @@ func ParseKPP(kpp string) (*KPPStruct, error) {
12678
}
12779

12880
return &KPPStruct{
129-
subjectCode: data.ConstitutionSubjectCode(utils.SliceToInt(subjectCodeArr)),
130-
recorderCode: RecorderCode(utils.SliceToInt(recorderCodeArr)),
131-
reasonCode: RegistrationReason(kpp[4:6]),
132-
serialNumber: SerialNumber(utils.SliceToInt(servialNumberArr)),
81+
taxRegionCode: taxRegionCode,
82+
reasonCode: RegistrationReason(kpp[4:6]),
83+
serialNumber: SerialNumber(utils.SliceToInt(servialNumberArr)),
13384
}, nil
13485
}
13586

13687
type KPPStruct struct {
137-
subjectCode data.ConstitutionSubjectCode
138-
recorderCode RecorderCode
139-
reasonCode RegistrationReason
140-
serialNumber SerialNumber
88+
taxRegionCode *fts.TaxRegionCode
89+
reasonCode RegistrationReason
90+
serialNumber SerialNumber
14191
}
14292

14393
func NewKPP() *KPPStruct {
14494
return &KPPStruct{
145-
subjectCode: data.GenerateConstitutionSubjectCode(),
146-
recorderCode: GenerateRecorderCode(),
147-
reasonCode: GenerateRegistrationReason(),
148-
serialNumber: GenerateSerialNumber(),
95+
taxRegionCode: fts.GenerateTaxRegionCode(),
96+
reasonCode: GenerateRegistrationReason(),
97+
serialNumber: GenerateSerialNumber(),
14998
}
15099
}
151100

152-
// Примечание: для ускорения записи при голосовых переговорах используют термин «стандартный КПП» (иногда он подразумевается),
153-
// где первые четыре цифры соответствуют ИНН, с 5 по 9 «01001».
154-
// Организации присвоены ИНН 7750004168, КПП 7705 01001.
155101
func (kpp *KPPStruct) IsValid() (bool, error) {
156102
if kpp == nil {
157103
return false, ErrNilKPP
158104
}
159105

160-
if !kpp.subjectCode.IsValid() {
161-
return false, fmt.Errorf(validateErrorTmpl, ErrInvalidSubjectCode, kpp.subjectCode)
106+
if !kpp.taxRegionCode.IsValid() {
107+
return false, fmt.Errorf(validateErrorTmpl, ErrInvalidTaxRegion, kpp.taxRegionCode)
162108
}
163109

164-
if !kpp.recorderCode.IsValid() {
165-
return false, fmt.Errorf(validateErrorTmpl, ErrInvalidRecorderCode, kpp.recorderCode)
110+
if kpp.isSpecialCode() {
111+
return true, nil
166112
}
167113

168114
if !kpp.reasonCode.IsValid() {
@@ -180,10 +126,18 @@ func (kpp *KPPStruct) String() string {
180126
var res strings.Builder
181127
res.Grow(codeLength)
182128

183-
res.WriteString(kpp.subjectCode.String())
184-
res.WriteString(kpp.recorderCode.String())
129+
res.WriteString(kpp.taxRegionCode.String())
185130
res.WriteString(kpp.reasonCode.String())
186131
res.WriteString(kpp.serialNumber.String())
187132

188133
return res.String()
189134
}
135+
136+
// isSpecialCode - для ускорения записи при голосовых переговорах используют термин «стандартный КПП» (иногда он подразумевается),
137+
// где первые четыре цифры соответствуют ИНН(не всегда), с 5 по 9 «01001».
138+
func (kpp *KPPStruct) isSpecialCode() bool {
139+
const specialReasonCode RegistrationReason = "01"
140+
const specialSerialNumber SerialNumber = 1
141+
142+
return kpp.reasonCode == specialReasonCode && kpp.serialNumber == specialSerialNumber
143+
}

0 commit comments

Comments
 (0)