Skip to content

Commit 99e9eee

Browse files
committed
Add support for Azerbaijan TIN
Closes arthurdejong#200.
1 parent 2907676 commit 99e9eee

File tree

3 files changed

+329
-0
lines changed

3 files changed

+329
-0
lines changed

stdnum/az/__init__.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# __init__.py - collection of Azerbaijan numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 Leandro Regueiro
5+
#
6+
# This library is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU Lesser General Public
8+
# License as published by the Free Software Foundation; either
9+
# version 2.1 of the License, or (at your option) any later version.
10+
#
11+
# This library is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
# Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public
17+
# License along with this library; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
# 02110-1301 USA
20+
21+
"""Collection of Azerbaijan numbers."""
22+
23+
# provide aliases
24+
from stdnum.az import voen as vat # noqa: F401

stdnum/az/voen.py

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# voen.py - functions for handling Azerbaijan VOEN numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 Leandro Regueiro
5+
#
6+
# This library is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU Lesser General Public
8+
# License as published by the Free Software Foundation; either
9+
# version 2.1 of the License, or (at your option) any later version.
10+
#
11+
# This library is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
# Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public
17+
# License along with this library; if not, write to the Free Software
18+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19+
# 02110-1301 USA
20+
21+
"""VÖEN (Vergi ödəyicisinin eyniləşdirmə nömrəsi, Azerbaijan tax number).
22+
23+
This number consists of 10 digits.
24+
25+
The first two digits are the code for the territorial administrative unit. The
26+
following six digits are a serial number. The ninth digit is determined by some
27+
special algorithm. The tenth digit represents the legal status of a taxpayer:
28+
1 for legal persons and 2 for natural persons.
29+
30+
31+
More information:
32+
33+
* https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Azerbaijan-TIN.pdf
34+
* https://www.e-taxes.gov.az/ebyn/payerOrVoenChecker.jsp
35+
36+
>>> validate('1400057421')
37+
'1400057421'
38+
>>> validate('140 155 5071')
39+
'1401555071'
40+
>>> validate('12345')
41+
Traceback (most recent call last):
42+
...
43+
InvalidLength: ...
44+
>>> validate('1400057424')
45+
Traceback (most recent call last):
46+
...
47+
InvalidComponent: ...
48+
>>> format('140 155 5071')
49+
'1401555071'
50+
""" # noqa: E501
51+
52+
from stdnum.exceptions import *
53+
from stdnum.util import clean, isdigits
54+
55+
56+
def compact(number):
57+
"""Convert the number to the minimal representation.
58+
59+
This strips the number of any valid separators and removes surrounding
60+
whitespace.
61+
"""
62+
return clean(number, ' ')
63+
64+
65+
def validate(number):
66+
"""Check if the number is a valid Azerbaijan VÖEN number.
67+
68+
This checks the length and formatting.
69+
"""
70+
number = compact(number)
71+
if len(number) != 10:
72+
raise InvalidLength()
73+
if not isdigits(number):
74+
raise InvalidFormat()
75+
if number[-1] not in ('1', '2'):
76+
raise InvalidComponent()
77+
return number
78+
79+
80+
def is_valid(number):
81+
"""Check if the number is a valid Azerbaijan VÖEN number."""
82+
try:
83+
return bool(validate(number))
84+
except ValidationError:
85+
return False
86+
87+
88+
def format(number):
89+
"""Reformat the number to the standard presentation format."""
90+
return compact(number)

tests/test_az_voen.doctest

+215
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
test_az_voen.doctest - more detailed doctests for stdnum.az.voen module
2+
3+
Copyright (C) 2022 Leandro Regueiro
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+
02110-1301 USA
19+
20+
21+
This file contains more detailed doctests for the stdnum.az.voen module. It
22+
tries to test more corner cases and detailed functionality that is not really
23+
useful as module documentation.
24+
25+
>>> from stdnum.az import voen
26+
27+
28+
Tests for some corner cases.
29+
30+
>>> voen.validate('1400057421')
31+
'1400057421'
32+
>>> voen.validate('140 155 5071')
33+
'1400057421'
34+
>>> voen.format('140 155 5071')
35+
'1400057421'
36+
>>> voen.validate('12345')
37+
Traceback (most recent call last):
38+
...
39+
InvalidLength: ...
40+
>>> voen.validate('ZZ00057421')
41+
Traceback (most recent call last):
42+
...
43+
InvalidFormat: ...
44+
>>> voen.validate('1400057424')
45+
Traceback (most recent call last):
46+
...
47+
InvalidComponent: ...
48+
49+
50+
These have been found online and should all be valid numbers.
51+
52+
>>> numbers = '''
53+
...
54+
... 1400057421
55+
... 1301703781
56+
... 9900019651
57+
... 1400064171
58+
... 9900007981
59+
... 9900006651
60+
... 9900006111
61+
... 1700792251
62+
... 1302164881
63+
... 1700038881
64+
... 9900001901
65+
... 9900006241
66+
... 9900001881
67+
... 1500031691
68+
... 1700028531
69+
... 9900003611
70+
... 1400122681
71+
... 1700130681
72+
... 9900014901
73+
... 1700767721
74+
... 9900001061
75+
... 1300016391
76+
... 1300017201
77+
... 1400117231
78+
... 2000296061
79+
... 9900009021
80+
... 1300036291
81+
... 0200432771
82+
... 9900037711
83+
... 1401771462
84+
... 1402852602
85+
... 2000358551
86+
... 1004534711
87+
... 1405043991
88+
... 1700986181
89+
... 1503353191
90+
... 1306005971
91+
... 1301368971
92+
... 1700807221
93+
... 1001142901
94+
... 3600027681
95+
... 4100019441
96+
... 1504360601
97+
... 1700852341
98+
... 9900071001
99+
... 1700093011
100+
... 1401555071
101+
... 1300407191
102+
... 1300532321
103+
... 1300286111
104+
... 1504535831
105+
... 1701393691
106+
... 9900001751
107+
... 1405631661
108+
... 1102637081
109+
... 2006058931
110+
... 6800002652
111+
... 1000121291
112+
... 2001093601
113+
... 9900059321
114+
... 2003883291
115+
... 1702670911
116+
... 1300144431
117+
... 1802926652
118+
... 1504653351
119+
... 140 155 5071
120+
... 1602473621
121+
... 9900038911
122+
... 9900003871
123+
... 1304587951
124+
... 2201161381
125+
... 2201161401
126+
... 1602636641
127+
... 3001292891
128+
... 2903923051
129+
... 2903924251
130+
... 5500988351
131+
... 2903924121
132+
... 1304590181
133+
... 5500988911
134+
... 5101071601
135+
... 7000953511
136+
... 5500988891
137+
... 5500988761
138+
... 1602637021
139+
... 2903924531
140+
... 1701989041
141+
... 1503264611
142+
... 2701084371
143+
... 5500989271
144+
... 5500984111
145+
... 6401437941
146+
... 5500984091
147+
... 1403476291
148+
... 5700713511
149+
... 1503250411
150+
... 2003891821
151+
... 1304571761
152+
... 5101051961
153+
... 6401437791
154+
... 1803045621
155+
... 4001457271
156+
... 8400745451
157+
... 1803045751
158+
... 1503250391
159+
... 3600595211
160+
... 1503252121
161+
... 1403478281
162+
... 1902814561
163+
... 2003893941
164+
... 2003894171
165+
... 2003893661
166+
... 1403477361
167+
... 1101405391
168+
... 2003893791
169+
... 1004314621
170+
... 2300145391
171+
... 1500020011
172+
... 1305541031
173+
... 2005166971
174+
... 2001198091
175+
... 1301710961
176+
... 1504488051
177+
... 1903366791
178+
... 1305081121
179+
... 1504145001
180+
... 1403530841
181+
... 1603712731
182+
... 1404508591
183+
... 5100586482
184+
... 2903864031
185+
... 2900643472
186+
... 1504433821
187+
... 1800491542
188+
... 1302566022
189+
... 7000787682
190+
... 4500309622
191+
... 1901757602
192+
... 5500044912
193+
... 4100350032
194+
... 1302568832
195+
... 2903016902
196+
... 1300528202
197+
... 1100725982
198+
... 1603234892
199+
... 5000205052
200+
... 1305904782
201+
... 1304124702
202+
... 4501001792
203+
... 2000185312
204+
... 6700193682
205+
... 4501238042
206+
... 1400299381
207+
... 2001150911
208+
... 1004732761
209+
... 1402298061
210+
... 1305393411
211+
... 3600108051
212+
...
213+
... '''
214+
>>> [x for x in numbers.splitlines() if x and not voen.is_valid(x)]
215+
[]

0 commit comments

Comments
 (0)