lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.14-5-gc5eb2d8

[Date Prev][Date Next] [Thread Prev][Thread Next]

python-stdnum branch master updated. 1.14-5-gc5eb2d8



This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-stdnum".

The branch, master has been updated
       via  c5eb2d89ae93bf3960f50f4a6f09e6aa022250a9 (commit)
       via  1f6c77fdc222b44ad8f371b48923d9179ab59e3e (commit)
       via  e0417f6b1c42400fd4bdd2f715e975f7447e87cc (commit)
      from  19d3f70c4835f8adecce2babcfec88177e82643a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://arthurdejong.org/git/python-stdnum/commit/?id=c5eb2d89ae93bf3960f50f4a6f09e6aa022250a9

commit c5eb2d89ae93bf3960f50f4a6f09e6aa022250a9
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Nov 1 16:46:28 2020 +0100

    Retain RO prefix in Romanian VAT numbers
    
    This does not strip the RO prefix from Romanian VAT numbers to be able
    to keep the distinction between a CUI/CIF that is registered for VAT
    (which commonly has the RO prefix) and those that don't.
    
    Closes https://github.com/arthurdejong/python-stdnum/issues/231

diff --git a/stdnum/eu/vat.py b/stdnum/eu/vat.py
index 987d8fc..27d47c6 100644
--- a/stdnum/eu/vat.py
+++ b/stdnum/eu/vat.py
@@ -74,20 +74,28 @@ def compact(number):
     """Convert the number to the minimal representation. This strips the
     number of any valid separators and removes surrounding whitespace."""
     number = clean(number, '').upper().strip()
-    module = _get_cc_module(number[:2])
+    cc = number[:2]
+    module = _get_cc_module(cc)
     if not module:
         raise InvalidComponent()
-    return number[:2] + module.compact(number[2:])
+    number = module.compact(number)
+    if not number.startswith(cc):
+        number = cc + number
+    return number
 
 
 def validate(number):
     """Check if the number is a valid VAT number. This performs the
     country-specific check for the number."""
     number = clean(number, '').upper().strip()
-    module = _get_cc_module(number[:2])
+    cc = number[:2]
+    module = _get_cc_module(cc)
     if not module:
         raise InvalidComponent()
-    return number[:2] + module.validate(number[2:])
+    number = module.validate(number)
+    if not number.startswith(cc):
+        number = cc + number
+    return number
 
 
 def is_valid(number):
diff --git a/stdnum/ro/cf.py b/stdnum/ro/cf.py
index 4bf1d8f..7c8006f 100644
--- a/stdnum/ro/cf.py
+++ b/stdnum/ro/cf.py
@@ -23,7 +23,7 @@
 The Romanian CF is used for VAT purposes and can be from 2 to 10 digits long.
 
 >>> validate('RO 185 472 90')  # VAT CUI/CIF
-'18547290'
+'RO18547290'
 >>> validate('185 472 90')  # non-VAT CUI/CIF
 '18547290'
 >>> validate('1630615123457')  # CNP
@@ -38,10 +38,7 @@ from stdnum.util import clean
 def compact(number):
     """Convert the number to the minimal representation. This strips the
     number of any valid separators and removes surrounding whitespace."""
-    number = clean(number, ' -').upper().strip()
-    if number.startswith('RO'):
-        number = number[2:]
-    return number
+    return clean(number, ' -').upper().strip()
 
 
 # for backwards compatibility
@@ -52,11 +49,14 @@ def validate(number):
     """Check if the number is a valid VAT number. This checks the length,
     formatting and check digit."""
     number = compact(number)
-    if len(number) == 13:
+    cnumber = number
+    if cnumber.startswith('RO'):
+        cnumber = cnumber[2:]
+    if len(cnumber) == 13:
         # apparently a CNP can also be used (however, not all sources agree)
-        cnp.validate(number)
-    elif 2 <= len(number) <= 10:
-        cui.validate(number)
+        cnp.validate(cnumber)
+    elif 2 <= len(cnumber) <= 10:
+        cui.validate(cnumber)
     else:
         raise InvalidLength()
     return number
diff --git a/tests/test_eu_vat.doctest b/tests/test_eu_vat.doctest
index d013f17..362f1de 100644
--- a/tests/test_eu_vat.doctest
+++ b/tests/test_eu_vat.doctest
@@ -912,3 +912,10 @@ These numbers should be mostly valid except that they have 
the wrong length.
 ... '''
 >>> [x for x in numbers.splitlines() if x and not caught(x, InvalidLength)]
 []
+
+
+Romanian CIF numbers assume that the RO prefix is part of the number so the
+EU VAT module should not return the prefix twice.
+
+>>> vat.compact('RO 21996566')
+'RO21996566'

https://arthurdejong.org/git/python-stdnum/commit/?id=1f6c77fdc222b44ad8f371b48923d9179ab59e3e

commit 1f6c77fdc222b44ad8f371b48923d9179ab59e3e
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Nov 1 15:53:38 2020 +0100

    Minor updates

diff --git a/stdnum/ro/cnp.py b/stdnum/ro/cnp.py
index 9247c9a..90ff313 100644
--- a/stdnum/ro/cnp.py
+++ b/stdnum/ro/cnp.py
@@ -52,7 +52,7 @@ 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()
+    return clean(number, ' -').strip()
 
 
 def calc_check_digit(number):
diff --git a/stdnum/ro/onrc.py b/stdnum/ro/onrc.py
index da153e9..21860f3 100644
--- a/stdnum/ro/onrc.py
+++ b/stdnum/ro/onrc.py
@@ -24,7 +24,8 @@
 All businesses in Romania have the to register with the National Trade
 Register Office to receive a registration number. The number contains
 information about the type of company, county, a sequence number and
-registration year.
+registration year. This number can change when registration information
+changes.
 
 >>> validate('J52/750/2012')
 'J52/750/2012'

https://arthurdejong.org/git/python-stdnum/commit/?id=e0417f6b1c42400fd4bdd2f715e975f7447e87cc

commit e0417f6b1c42400fd4bdd2f715e975f7447e87cc
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Nov 1 15:51:54 2020 +0100

    Add Romanian CUI/CIF number
    
    This module separates the validation of numbers assigned to companies
    (CUI or CIF) of those assigned to natural persons (CNP).

diff --git a/stdnum/ro/cf.py b/stdnum/ro/cf.py
index dbede72..4bf1d8f 100644
--- a/stdnum/ro/cf.py
+++ b/stdnum/ro/cf.py
@@ -1,7 +1,7 @@
 # cf.py - functions for handling Romanian CF (VAT) numbers
 # coding: utf-8
 #
-# Copyright (C) 2012-2015 Arthur de Jong
+# Copyright (C) 2012-2020 Arthur de Jong
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -22,19 +22,17 @@
 
 The Romanian CF is used for VAT purposes and can be from 2 to 10 digits long.
 
->>> validate('RO 185 472 90')
+>>> validate('RO 185 472 90')  # VAT CUI/CIF
 '18547290'
->>> validate('185 472 91')
-Traceback (most recent call last):
-    ...
-InvalidChecksum: ...
->>> validate('1630615123457')  # personal code
+>>> validate('185 472 90')  # non-VAT CUI/CIF
+'18547290'
+>>> validate('1630615123457')  # CNP
 '1630615123457'
 """
 
 from stdnum.exceptions import *
-from stdnum.ro import cnp
-from stdnum.util import clean, isdigits
+from stdnum.ro import cnp, cui
+from stdnum.util import clean
 
 
 def compact(number):
@@ -46,27 +44,19 @@ def compact(number):
     return number
 
 
-def calc_check_digit(number):
-    """Calculate the check digit for organisations. The number passed
-    should not have the check digit included."""
-    weights = (7, 5, 3, 2, 1, 7, 5, 3, 2)
-    number = (9 - len(number)) * '0' + number
-    check = 10 * sum(w * int(n) for w, n in zip(weights, number))
-    return str(check % 11 % 10)
+# for backwards compatibility
+calc_check_digit = cui.calc_check_digit
 
 
 def validate(number):
     """Check if the number is a valid VAT number. This checks the length,
     formatting and check digit."""
     number = compact(number)
-    if not isdigits(number) or number[0] == '0':
-        raise InvalidFormat()
     if len(number) == 13:
         # apparently a CNP can also be used (however, not all sources agree)
         cnp.validate(number)
     elif 2 <= len(number) <= 10:
-        if calc_check_digit(number[:-1]) != number[-1]:
-            raise InvalidChecksum()
+        cui.validate(number)
     else:
         raise InvalidLength()
     return number
diff --git a/stdnum/ro/cf.py b/stdnum/ro/cui.py
similarity index 61%
copy from stdnum/ro/cf.py
copy to stdnum/ro/cui.py
index dbede72..8e88840 100644
--- a/stdnum/ro/cf.py
+++ b/stdnum/ro/cui.py
@@ -1,7 +1,7 @@
-# cf.py - functions for handling Romanian CF (VAT) numbers
+# cui.py - functions for handling Romanian CUI and CIF numbers
 # coding: utf-8
 #
-# Copyright (C) 2012-2015 Arthur de Jong
+# Copyright (C) 2012-2020 Arthur de Jong
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -18,22 +18,32 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301 USA
 
-"""CF (Cod de înregistrare în scopuri de TVA, Romanian VAT number).
+"""CUI or CIF (Codul Unic de Înregistrare, Romanian company identifier).
 
-The Romanian CF is used for VAT purposes and can be from 2 to 10 digits long.
+The CUI (Codul Unic de Înregistrare) is assigned to companies that are
+required to register with the Romanian Trade Register. The CIF (Codul de
+identificare fiscală) is identical but assigned to entities that have no such
+requirement. The names seem to be used interchangeably and some sources
+suggest that CIF is the new name for CUI.
 
->>> validate('RO 185 472 90')
+This number can change under some conditions. The number can be prefixed with
+RO to indicate that the entity has been registered for VAT.
+
+More information:
+
+* https://ro.wikipedia.org/wiki/Cod_de_identificare_fiscală
+
+>>> validate('185 472 90')
 '18547290'
 >>> validate('185 472 91')
 Traceback (most recent call last):
     ...
 InvalidChecksum: ...
->>> validate('1630615123457')  # personal code
-'1630615123457'
+>>> validate('RO 185 472 90')  # the RO prefix is ignored
+'18547290'
 """
 
 from stdnum.exceptions import *
-from stdnum.ro import cnp
 from stdnum.util import clean, isdigits
 
 
@@ -47,8 +57,7 @@ def compact(number):
 
 
 def calc_check_digit(number):
-    """Calculate the check digit for organisations. The number passed
-    should not have the check digit included."""
+    """Calculate the check digit."""
     weights = (7, 5, 3, 2, 1, 7, 5, 3, 2)
     number = (9 - len(number)) * '0' + number
     check = 10 * sum(w * int(n) for w, n in zip(weights, number))
@@ -56,24 +65,20 @@ def calc_check_digit(number):
 
 
 def validate(number):
-    """Check if the number is a valid VAT number. This checks the length,
+    """Check if the number is a valid CUI or CIF number. This checks the 
length,
     formatting and check digit."""
     number = compact(number)
     if not isdigits(number) or number[0] == '0':
         raise InvalidFormat()
-    if len(number) == 13:
-        # apparently a CNP can also be used (however, not all sources agree)
-        cnp.validate(number)
-    elif 2 <= len(number) <= 10:
-        if calc_check_digit(number[:-1]) != number[-1]:
-            raise InvalidChecksum()
-    else:
+    if not (2 <= len(number) <= 10):
         raise InvalidLength()
+    if calc_check_digit(number[:-1]) != number[-1]:
+        raise InvalidChecksum()
     return number
 
 
 def is_valid(number):
-    """Check if the number is a valid VAT number."""
+    """Check if the number is a valid CUI or CIF number."""
     try:
         return bool(validate(number))
     except ValidationError:

-----------------------------------------------------------------------

Summary of changes:
 stdnum/eu/vat.py            | 16 ++++++++++++----
 stdnum/ro/cf.py             | 44 +++++++++++++++++---------------------------
 stdnum/ro/cnp.py            |  2 +-
 stdnum/ro/{cf.py => cui.py} | 43 ++++++++++++++++++++++++-------------------
 stdnum/ro/onrc.py           |  3 ++-
 tests/test_eu_vat.doctest   |  7 +++++++
 6 files changed, 63 insertions(+), 52 deletions(-)
 copy stdnum/ro/{cf.py => cui.py} (61%)


hooks/post-receive
-- 
python-stdnum