Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions stdnum/cz/ico.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# ico.py - functions for handling Czech organisation identifiers
# coding: utf-8
#
# Copyright (C) 2026 Devashish Moghe
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <https://www.gnu.org/licenses/>.

"""IČO (Identifikační číslo osoby, Czech organisation identifier).

The IČO (Identifikační číslo osoby, also abbreviated IČ) is an 8-digit
number (including a trailing check digit) that uniquely identifies a legal
entity or sole trader registered in the Czech Republic. It is assigned by
the Czech Statistical Office and is listed in the public business register
(ARES).

The number is the same as the digits of the legal entity's Czech VAT number
(DIČ, see stdnum.cz.dic) without the ``CZ`` prefix.

More information:

* https://cs.wikipedia.org/wiki/Identifikační_číslo_osoby
* https://ares.gov.cz/

>>> validate('00177041')
'00177041'
>>> validate('001 77 041')
'00177041'
>>> validate('00177042') # invalid check digit
Traceback (most recent call last):
...
InvalidChecksum: ...
>>> validate('0017704') # too short
Traceback (most recent call last):
...
InvalidLength: ...
>>> validate('0017704X')
Traceback (most recent call last):
...
InvalidFormat: ...
"""

from __future__ import annotations

from stdnum.exceptions import *
from stdnum.util import clean, isdigits


def compact(number: str) -> str:
"""Convert the number to the minimal representation. This strips the
number of any valid separators and removes surrounding whitespace."""
return clean(number, ' /').strip()


def calc_check_digit(number: str) -> str:
"""Calculate the check digit. The number passed should not have the
check digit included."""
# weighted modulo 11 checksum; this is the same algorithm used for the
# 8-digit (legal entity) form of the Czech DIČ, see stdnum.cz.dic
check = (11 - sum((8 - i) * int(n) for i, n in enumerate(number))) % 11
return str((check or 1) % 10)


def validate(number: str) -> str:
"""Check if the number is a valid IČO. This checks the length,
formatting and check digit."""
number = compact(number)
if not isdigits(number):
raise InvalidFormat()
if len(number) != 8:
raise InvalidLength()
if number[-1] != calc_check_digit(number[:-1]):
raise InvalidChecksum()
return number


def is_valid(number: str) -> bool:
"""Check if the number is a valid IČO."""
try:
return bool(validate(number))
except ValidationError:
return False
52 changes: 52 additions & 0 deletions stdnum/sk/ico.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# ico.py - functions for handling Slovak organisation identifiers
# coding: utf-8
#
# Copyright (C) 2026 Devashish Moghe
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <https://www.gnu.org/licenses/>.

"""IČO (Identifikačné číslo organizácie, Slovak organisation identifier).

The IČO (Identifikačné číslo organizácie) is an 8-digit number (including a
trailing check digit) that identifies an organisation or sole trader
registered in Slovakia. It is listed in the Slovak business register (ORSR)
and the Register of Legal Entities (RPO).

This number is identical to the Czech counterpart (until 1993 the Czech
Republic and Slovakia were one country) and uses the same format and check
digit.

>>> validate('31322832')
'31322832'
>>> validate('31 322 832')
'31322832'
>>> validate('31322833') # invalid check digit
Traceback (most recent call last):
...
InvalidChecksum: ...
>>> validate('313228') # too short
Traceback (most recent call last):
...
InvalidLength: ...
"""

# since this number is essentially the same as the Czech counterpart
# (until 1993 the Czech Republic and Slovakia were one country)

from __future__ import annotations

from stdnum.cz.ico import calc_check_digit, compact, is_valid, validate


__all__ = ['compact', 'calc_check_digit', 'validate', 'is_valid']
80 changes: 80 additions & 0 deletions tests/test_cz_ico.doctest
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
test_cz_ico.doctest - more detailed doctests for the stdnum.cz.ico module

Copyright (C) 2026 Devashish Moghe

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <https://www.gnu.org/licenses/>.


This file contains more detailed doctests for the stdnum.cz.ico module. It
tries to validate a number of numbers that have been found online.

>>> from stdnum.cz import ico
>>> from stdnum.exceptions import *


Tests for some corner cases.

>>> ico.validate('00177041')
'00177041'
>>> ico.validate('001 77 041')
'00177041'
>>> ico.compact('001 77 041')
'00177041'
>>> ico.is_valid('00177041')
True
>>> ico.is_valid('00177042')
False
>>> ico.validate('00177042')
Traceback (most recent call last):
...
InvalidChecksum: ...
>>> ico.validate('123')
Traceback (most recent call last):
...
InvalidLength: ...
>>> ico.validate('2616868A')
Traceback (most recent call last):
...
InvalidFormat: ...


These have been found online and should all be valid numbers.

>>> numbers = '''
...
... 00001350
... 00006947
... 00177041
... 00514152
... 01377281
... 24704415
... 25063677
... 25672720
... 26168685
... 26185610
... 28195329
... 27082440
... 45244782
... 45272956
... 45274649
... 45317054
... 45357366
... 47114983
... 49240901
... 60193336
... 70994226
...
... '''
>>> [x for x in numbers.splitlines() if x and not ico.is_valid(x)]
[]
78 changes: 78 additions & 0 deletions tests/test_sk_ico.doctest
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
test_sk_ico.doctest - more detailed doctests for the stdnum.sk.ico module

Copyright (C) 2026 Devashish Moghe

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <https://www.gnu.org/licenses/>.


This file contains more detailed doctests for the stdnum.sk.ico module. It
tries to validate a number of numbers that have been found online.

>>> from stdnum.sk import ico
>>> from stdnum.exceptions import *


Tests for some corner cases.

>>> ico.validate('31322832')
'31322832'
>>> ico.validate('31 322 832')
'31322832'
>>> ico.is_valid('31322832')
True
>>> ico.is_valid('31322833')
False
>>> ico.validate('31322833')
Traceback (most recent call last):
...
InvalidChecksum: ...
>>> ico.validate('313228')
Traceback (most recent call last):
...
InvalidLength: ...
>>> ico.validate('3132283A')
Traceback (most recent call last):
...
InvalidFormat: ...


These have been found online and should all be valid numbers.

>>> numbers = '''
...
... 00151653
... 00151742
... 00686930
... 31320155
... 31321828
... 31322832
... 31333532
... 31364501
... 35697270
... 35743565
... 35757442
... 35763469
... 35790253
... 35815256
... 35829052
... 35848863
... 35876832
... 35971894
... 36199222
... 36631124
... 44483767
...
... '''
>>> [x for x in numbers.splitlines() if x and not ico.is_valid(x)]
[]
Loading