1# cnp.py - functions for handling Croatian OIB numbers
2# coding: utf-8
3#
4# Copyright (C) 2012, 2013 Arthur de Jong
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"""OIB (Osobni identifikacijski broj, Croatian identification number).
22
23The personal identification number is used to identify persons and legal
24entities in Croatia. It has 11 digits (sometimes prefixed by HR), contains
25no personal information and uses the ISO 7064 Mod 11, 10 checksum algorithm.
26
27>>> validate('HR 33392005961')
28'33392005961'
29>>> validate('33392005962')  # invalid check digit
30Traceback (most recent call last):
31    ...
32InvalidChecksum: ...
33"""
34
35from stdnum.exceptions import *
36from stdnum.iso7064 import mod_11_10
37from stdnum.util import clean, isdigits
38
39
40def compact(number):
41    """Convert the number to the minimal representation. This strips the
42    number of any valid separators and removes surrounding whitespace."""
43    number = clean(number, ' -').upper().strip()
44    if number.startswith('HR'):
45        number = number[2:]
46    return number
47
48
49def validate(number):
50    """Check if the number is a valid OIB number. This checks the length,
51    formatting and check digit."""
52    number = compact(number)
53    if not isdigits(number):
54        raise InvalidFormat()
55    if len(number) != 11:
56        raise InvalidLength()
57    mod_11_10.validate(number)
58    return number
59
60
61def is_valid(number):
62    """Check if the number is a valid OIB number."""
63    try:
64        return bool(validate(number))
65    except ValidationError:
66        return False
67