Skip to content

Commit 1386f67

Browse files
nvmbrasseriearthurdejong
authored andcommitted
Add Russian ОГРН
Closes #459
1 parent 8519221 commit 1386f67

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

stdnum/ru/ogrn.py

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# ogrn.py - functions for handling Russian company registration numbers
2+
# coding: utf-8
3+
#
4+
# Copyright (C) 2024 Ivan Stavropoltsev
5+
# Copyright (C) 2025 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+
"""ОГРН, OGRN, PSRN, ОГРНИП, OGRNIP (Russian Primary State Registration Number).
23+
24+
The ОГРН (Основной государственный регистрационный номер, Primary State
25+
Registration Number) is a Russian identifier for legal entities. The number
26+
consists of 13 or 15 digits and includes information on the type of
27+
organisation, the registration year and a tax inspection code. The 15 digit
28+
variant is called ОГРНИП (Основной государственный регистрационный номер
29+
индивидуального предпринимателя, Primary State Registration Number of an
30+
Individual Entrepreneur).
31+
32+
More information:
33+
34+
* https://ru.wikipedia.org/wiki/Основной_государственный_регистрационный_номер
35+
* https://ru.wikipedia.org/wiki/Основной_государственный_регистрационный_номер_индивидуального_предпринимателя
36+
37+
>>> validate('1022200525819')
38+
'1022200525819'
39+
>>> validate('385768585948949')
40+
'385768585948949'
41+
>>> validate('1022500001328')
42+
Traceback (most recent call last):
43+
...
44+
InvalidChecksum: ...
45+
"""
46+
47+
from stdnum.exceptions import *
48+
from stdnum.util import clean, isdigits
49+
50+
51+
def compact(number):
52+
"""Convert the number to the minimal representation. This strips the
53+
number of any valid separators and removes surrounding whitespace."""
54+
return clean(number, ' ')
55+
56+
57+
def calc_check_digit(number):
58+
"""Calculate the control digit of the OGRN based on its length."""
59+
if len(number) == 13:
60+
return str(int(number[:-1]) % 11 % 10)
61+
else:
62+
return str(int(number[:-1]) % 13)
63+
64+
65+
def validate(number):
66+
"""Determine if the given number is a valid OGRN."""
67+
number = compact(number)
68+
if not isdigits(number):
69+
raise InvalidFormat()
70+
if len(number) == 13:
71+
if number[0] == '0':
72+
raise InvalidComponent()
73+
elif len(number) == 15:
74+
if number[0] not in '34':
75+
raise InvalidComponent()
76+
else:
77+
raise InvalidLength()
78+
if number[-1] != calc_check_digit(number):
79+
raise InvalidChecksum()
80+
return number
81+
82+
83+
def is_valid(number):
84+
"""Check if the number is a valid OGRN."""
85+
try:
86+
return bool(validate(number))
87+
except ValidationError:
88+
return False

tests/test_ru_ogrn.doctest

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
test_ru_ogrn.doctest - more detailed doctests for the stdnum.ru.ogrn module
2+
3+
Copyright (C) 2024 Ivan Stavropoltsev
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.ru.ogrn module.
22+
23+
These tests validate the format, normalisation, and validity of various
24+
OGRN numbers, ensuring they conform to expected behaviour.
25+
26+
>>> from stdnum.ru import ogrn
27+
>>> from stdnum.exceptions import *
28+
29+
30+
Checks of the 13 digit ОГРН, OGRN
31+
32+
>>> ogrn.validate('1022500001325')
33+
'1022500001325'
34+
>>> ogrn.validate('10277395526422') # 14 digits
35+
Traceback (most recent call last):
36+
...
37+
InvalidLength: ...
38+
>>> ogrn.validate('0022500001325') # starts with 0
39+
Traceback (most recent call last):
40+
...
41+
InvalidComponent: ...
42+
>>> ogrn.validate('102250000') # too short
43+
Traceback (most recent call last):
44+
...
45+
InvalidLength: ...
46+
>>> ogrn.validate('1022500001328')
47+
Traceback (most recent call last):
48+
...
49+
InvalidChecksum: ...
50+
51+
52+
Checks of the 13 digit ОГРНИП, OGRNIP
53+
54+
>>> ogrn.validate('985768585948944') # OGRNIP with invalid start digit
55+
Traceback (most recent call last):
56+
...
57+
InvalidComponent: ...
58+
>>> ogrn.validate('385768585948948')
59+
Traceback (most recent call last):
60+
...
61+
InvalidChecksum: ...
62+
63+
64+
This is a list of OGRNs that should all be valid numbers:
65+
66+
>>> valid_numbers = '''
67+
...
68+
... 1022300000502
69+
... 1022300001811
70+
... 1022400007508
71+
... 1022500000566
72+
... 1022600000092
73+
... 1027100000311
74+
... 1027739552642
75+
...
76+
... '''
77+
>>> [x for x in valid_numbers.splitlines() if x and not ogrn.is_valid(x)]
78+
[]

0 commit comments

Comments
 (0)