diff options
author | Leandro Regueiro <leandro.regueiro@gmail.com> | 2019-06-23 15:00:56 +0200 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2019-07-23 22:19:04 +0200 |
commit | 2f38aaffb0577c945945c8a4b01aa9edc7240e9f (patch) | |
tree | bba4c74a2bcb32a47f8923b313b490be6525e9db | |
parent | db89d38f73725ad6dc1245228991f5abc1f8da5a (diff) |
Add Guatemalan NIT
Closes https://github.com/arthurdejong/python-stdnum/pull/149
Closes https://github.com/arthurdejong/python-stdnum/issues/132
-rw-r--r-- | stdnum/gt/__init__.py | 24 | ||||
-rw-r--r-- | stdnum/gt/nit.py | 96 | ||||
-rw-r--r-- | tests/test_gt_nit.doctest | 105 |
3 files changed, 225 insertions, 0 deletions
diff --git a/stdnum/gt/__init__.py b/stdnum/gt/__init__.py new file mode 100644 index 0000000..c1f38d9 --- /dev/null +++ b/stdnum/gt/__init__.py @@ -0,0 +1,24 @@ +# __init__.py - collection of Guatemalan numbers +# coding: utf-8 +# +# Copyright (C) 2019 Leandro Regueiro +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + +"""Collection of Guatemalan numbers.""" + +# provide aliases +from stdnum.gt import nit as vat # noqa: F401 diff --git a/stdnum/gt/nit.py b/stdnum/gt/nit.py new file mode 100644 index 0000000..efbe1b0 --- /dev/null +++ b/stdnum/gt/nit.py @@ -0,0 +1,96 @@ +# nit.py - functions for handling Guatemala NIT numbers +# coding: utf-8 +# +# Copyright (C) 2019 Leandro Regueiro +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + +"""NIT (Número de Identificación Tributaria, Guatemala tax number). + +The Número de Identificación Tributaria (NIT) is an identifier of legal +entities for tax purposes in Guatemala. + +The number consists of 2 to 12 characters, where the last one is the check +digit (a digit or the letter K) and the rest are digits. Leading zeroes are +usually omitted. Digits and check digit are usually separated with a hyphen. + +More information: + +* https://portal.sat.gob.gt/portal/descarga/6524/factura-electronica-fel/25542/fel-reglas-y-validaciones.pdf (page 58) +* https://portal.sat.gob.gt/portal/consulta-cui-nit/ + +>>> validate('576937-K') +'576937K' +>>> validate('7108-0') +'71080' +>>> validate('8977112-0') +Traceback (most recent call last): + ... +InvalidChecksum: ... +>>> validate('1234567890123') +Traceback (most recent call last): + ... +InvalidLength: ... +>>> format('39525503') +'3952550-3' +""" + +from stdnum.exceptions import * +from stdnum.util import clean, isdigits + + +def compact(number): + """Convert the number to the minimal representation. This strips the + number of any valid separators and removes surrounding whitespace.""" + return clean(number, ' -').upper().strip().lstrip('0') + + +def calc_check_digit(number): + """Calculate the check digit. The number passed should not have the + check digit included.""" + c = -sum(i * int(n) for i, n in enumerate(reversed(number), 2)) % 11 + return 'K' if c == 10 else str(c) + + +def validate(number): + """Check if the number is a valid Guatemala NIT number. + + This checks the length, formatting and check digit. + """ + number = compact(number) + if len(number) < 2 or len(number) > 12: + raise InvalidLength() + if not isdigits(number[:-1]): + raise InvalidFormat() + if number[-1] != 'K' and not isdigits(number[-1]): + raise InvalidFormat() + if number[-1] != calc_check_digit(number[:-1]): + raise InvalidChecksum() + return number + + +def is_valid(number): + """Check if the number is a valid Guatemala NIT number.""" + try: + return bool(validate(number)) + except ValidationError: + return False + + +def format(number): + """Reformat the number to the standard presentation format.""" + number = compact(number) + return '-'.join([number[:-1], number[-1]]) diff --git a/tests/test_gt_nit.doctest b/tests/test_gt_nit.doctest new file mode 100644 index 0000000..eff949b --- /dev/null +++ b/tests/test_gt_nit.doctest @@ -0,0 +1,105 @@ +test_gt_nit.doctest - more detailed doctests for stdnum.gt.nit module + +Copyright (C) 2019 Leandro Regueiro + +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA + + +This file contains more detailed doctests for the stdnum.gt.nit module. It +tries to test more corner cases and detailed functionality that is not really +useful as module documentation. + +>>> from stdnum.gt import nit + + +Tests for some corner cases. + +>>> nit.validate('576937-K') +'576937K' +>>> nit.validate('6946874-5') +'69468745' +>>> nit.validate('672681-K') +'672681K' +>>> nit.validate('1234567890123') +Traceback (most recent call last): + ... +InvalidLength: ... +>>> nit.validate('1') +Traceback (most recent call last): + ... +InvalidLength: ... +>>> nit.validate('FF12') # letters where there should be digits +Traceback (most recent call last): + ... +InvalidFormat: ... +>>> nit.validate('12D') # invalid check digit +Traceback (most recent call last): + ... +InvalidFormat: ... +>>> nit.validate('8170266-0') +Traceback (most recent call last): + ... +InvalidChecksum: ... + + +These have been found online and should all be valid numbers. + +>>> numbers = ''' +... +... 115203-3 +... 1245535-0 +... 1251368-7 +... 1510972-0 +... 164624-9 +... 29010438 +... 3-37772-5 +... 3013878-7 +... 3198595-5 +... 3213463 +... 32173-7 +... 3219690-3 +... 32233-4 +... 32439-6 +... 32644-5 +... 33038-8 +... 330651-8 +... 33155-4 +... 33291-7 +... 3602978-5 +... 36728519 +... 39525503 +... 418979-5 +... 4548327-2 +... 478433-2 +... 4863461 +... 4925343 +... 499184-2 +... 5187400 +... 576937-K +... 705526-9 +... 7108-0 +... 7127170 +... 718160-4 +... 72526-9 +... 748810-6 +... 7981182-5 +... 8263362-2 +... 8977112-5 +... 992929-0 +... +... ''' +>>> [x for x in numbers.splitlines() if x and not nit.is_valid(x)] +[] |