8000 Add support for Montenegro TIN · unho/python-stdnum@2b6e087 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2b6e087

Browse files
unhoarthurdejong
authored andcommitted
Add support for Montenegro TIN
Closes arthurdejong#331 Closes arthurdejong#223
1 parent fbe094c commit 2b6e087

File tree

3 files changed

+265
-0
lines changed

3 files changed

+265
-0
lines changed

stdnum/me/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@
1919
# 02110-1301 USA
2020

2121
"""Collection of Montenegro numbers."""
22+
23+
# provide aliases
24+
from stdnum.me import pib as vat # noqa: F401

stdnum/me/pib.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# pib.py - functions for handling Montenegro PIB numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2022 Leandro Regueiro
5+
# Copyright (C) 2022 Arthur de Jong
6+
#
7+
# This library is free software; you can redistribute it and/or
8+
# modify it under the terms of the GNU Lesser General Public
9+
# License as published by the Free Software Foundation; either
10+
# version 2.1 of the License, or (at your option) any later version.
11+
#
12+
# This library is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
# Lesser General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser General Public
18+
# License along with this library; if not, write to the Free Software
19+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20+
# 02110-1301 USA
21+
22+
"""PIB (Poreski Identifikacioni Broj, Montenegro tax number).
23+
24+
This number consists of 8 digits.
25+
26+
More information:
27+
28+
* http://www.pretraga.crps.me:8083/
29+
* https://www.vatify.eu/montenegro-vat-number.html
30+
31+
>>> validate('02655284')
32+
'02655284'
33+
>>> validate('02655283')
34+
Traceback (most recent call last):
35+
...
36+
InvalidChecksum: ...
37+
>>> format('02655284')
38+
'02655284'
39+
"""
40+
41+
from stdnum.exceptions import *
42+
from stdnum.util import clean, isdigits
43+
44+
45+
def compact(number):
46+
"""Convert the number to the minimal representation.
47+
48+
This strips the number of any valid separators and removes surrounding
49+
whitespace.
50+
"""
51+
return clean(number, ' ')
52+
53+
54+
def calc_check_digit(number):
55+
"""Calculate the check digit for the number."""
56+
weights = (8, 7, 6, 5, 4, 3, 2)
57+
return str((-sum(w * int(n) for w, n in zip(weights, number))) % 11 % 10)
58+
59+
60+
def validate(number):
61+
"""Check if the number is a valid Montenegro PIB number."""
62+
number = compact(number)
63+
if len(number) != 8:
64+
raise InvalidLength()
65+
if not isdigits(number):
66+
raise InvalidFormat()
67+
if number[-1] != calc_check_digit(number):
68+
raise InvalidChecksum()
69+
return number
70+
71+
72+
def is_valid(number):
73+
"""Check if the number is a valid Montenegro PIB number."""
74+
try:
75+
return bool(validate(number))
76+
except ValidationError:
77+
return False
78+
79+
80+
def format(number):
81+
"""Reformat the number to the standard presentation format."""
82+
return compact(number)

tests/test_me_pib.doctest

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
test_me_pib.doctest - more detailed doctests for stdnum.me.pib 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.me.pib 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.me import pib
26+
27+
28+
Tests for some corner cases.
29+
30+
>>> pib.validate('02655284')
31+
'02655284'
32+
>>> pib.validate('12345')
33+
Traceback (most recent call last):
34+
...
35+
InvalidLength: ...
36+
>>> pib.validate('12345XYZ')
37+
Traceback (most recent call last):
38+
...
39+
InvalidFormat: ...
40+
>>> pib.format('02655284')
41+
'02655284'
42+
43+
44+
These have been found online and should all be valid numbers.
45+
46+
>>> numbers = ' F438 ;''
47+
...
48+
... 02000989
49+
... 02005115
50+
... 02005328
51+
... 02007479
52+
... 02008599
53+
... 02015099
54+
... 02017105
55+
... 02018560
56+
... 02026325
57+
... 02033143
58+
... 02033356
59+
... 02044188
60+
... 02046954
61+
... 02047403
62+
... 02051664
63+
... 02052822
64+
... 02082390
65+
... 02085020
66+
... 02087723
67+
... 02094754
68+
... 02096064
69+
... 02096099
70+
... 02106183
71+
... 02118912
72+
... 02126265
73+
... 02131013
74+
... 02132419
75+
... 02160102
76+
... 02171058
77+
... 02194007
78+
... 02196727
79+
... 02216078
80+
... 02219603
81+
... 02241102
82+
... 02259974
83+
... 02264811
84+
... 02265435
85+
... 02272296
86+
... 02291266
87+
... 02293099
88+
... 02303213
89+
... 02305054
90+
... 02305623
91+
... 02309084
92+
... 02310783
93+
... 02313987
94+
... 02335450
95+
... 02355388
96+
... 02357950
97+
... 02383136
98+
... 02384337
99+
... 02385040
100+
... 02389231
101+
... 02395673
102+
... 02404281
103+
... 02407515
104+
... 02436159
105+
... 02437643
106+
... 02440768
107+
... 02448076
108+
... 02454190
109+
... 02455455
110+
... 02462494
111+
... 02465787
112+
... 02467593
113+
... 02628988
114+
... 02630419
115+
... 02653753
116+
... 02656515
117+
... 02671930
118+
... 02694638
119+
... 02697904
120+
... 02702967
121+
... 02705001
122+
... 02707942
123+
... 02709392
124+
... 02717557
125+
... 02739500
126+
... 02751372
127+
... 02759519
128+
... 02766515
129+
... 02769336
130+
... 02783746
131+
... 02865971
132+
... 02868474
133+
... 02880474
134+
... 02894998
135+
... 02896753
136+
... 02904870
137+
... 02908433
138+
... 02952165
139+
... 02959801
140+
... 02983303
141+
... 03016480
142+
... 03022480
143+
... 03037002
144+
... 03099873
145+
... 03183246
146+
... 03313468
147+
... 03328139
148+
... 03350479
149+
... 03350487
150+
... 03350495
151+
... 03350509
152+
... 03350517
153+
... 03350525
154+
... 03350533
155+
... 03350541
156+
... 03350550
157+
... 03350568
158+
... 03350576
159+
... 03350584
160+
... 03350592
161+
... 03350606
162+
... 03350614
163+
... 03350622
164+
... 03350665
165+
... 03350673
166+
... 03350681
167+
... 03350690
168+
... 03350703
169+
... 03350789
170+
... 03351483
171+
... 03352480
172+
... 03353486
173+
... 03354482
174+
... 03355489
175+
... 03356485
176+
... 03357481
177+
...
178+
... '''
179+
>>> [x for x in numbers.splitlines() if x and not pib.is_valid(x)]
180+
[]

0 commit comments

Comments
 (0)
0