python-stdnum branch master updated. 1.18-29-gf58e08d
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
python-stdnum branch master updated. 1.18-29-gf58e08d
- From: Commits of the python-stdnum project <python-stdnum-commits [at] lists.arthurdejong.org>
- To: python-stdnum-commits [at] lists.arthurdejong.org
- Reply-to: python-stdnum-users [at] lists.arthurdejong.org, python-stdnum-commits [at] lists.arthurdejong.org
- Subject: python-stdnum branch master updated. 1.18-29-gf58e08d
- Date: Sun, 13 Aug 2023 19:04:16 +0200 (CEST)
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 f58e08d1f082554d427da82bea9691872ea51dfa (commit)
from d0f4c1a5998b63a76089be5797acff1e489ccd86 (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=f58e08d1f082554d427da82bea9691872ea51dfa
commit f58e08d1f082554d427da82bea9691872ea51dfa
Author: Arthur de Jong <arthur@arthurdejong.org>
Date: Sun Aug 13 18:36:31 2023 +0200
Validate European VAT numbers with EU or IM prefix
Closes https://github.com/arthurdejong/python-stdnum/pull/417
diff --git a/stdnum/eu/oss.py b/stdnum/eu/oss.py
new file mode 100644
index 0000000..e9d0349
--- /dev/null
+++ b/stdnum/eu/oss.py
@@ -0,0 +1,120 @@
+# oss.py - functions for handling European VAT numbers
+# coding: utf-8
+#
+# Copyright (C) 2023 Arthur de Jong
+# Copyright (C) 2023 Sergi Almacellas Abellana
+#
+# 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
+
+"""OSS (European VAT on e-Commerce - One Stop Shop).
+
+This covers number that have been issued under the non-union scheme and the
+import scheme of the European VAT on e-Commerce one stop shop. Numbers under
+the non-union scheme are assigned to foreign companies providing digital
+services to European Union consumers. Numbers under the import scheme are
+assigned for importing goods from a third country (through an intermediary).
+
+This is also called MOSS (mini One Stop Shop) and VoeS (VAT on e-Services).
+The number under the import scheme is also called IOSS (Import One Stop Shop)
+number.
+
+Numbers under the non-union scheme are in the format EUxxxyyyyyz. For the
+import scheme the format is IMxxxyyyyyyz. An intermediary will also get an
+number in the format INxxxyyyyyyz but that may not be used as VAT
+identification number.
+
+There appears to be a check digit algorithm but the FITSDEV2-SC12-TS-Mini1SS
+(Mini-1SS – Technical Specifications) document that describes the algorithm
+appears to not be publicly available.
+
+More information:
+
+* https://vat-one-stop-shop.ec.europa.eu/one-stop-shop/register-oss_en
+*
https://europa.eu/youreurope/business/taxation/vat/vat-digital-services-moss-scheme/index_en.htm
+* https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32002L0038
+
+>>> validate('EU 372022452')
+'EU372022452'
+"""
+
+
+from stdnum.exceptions import *
+from stdnum.util import clean, isdigits
+
+
+ISO_3166_1_MEMBER_STATES = (
+ '040', # Austria
+ '056', # Belgium
+ '100', # Bulgaria
+ '191', # Croatia
+ '196', # Cyprus
+ '203', # Czechia
+ '208', # Denmark
+ '233', # Estonia
+ '246', # Finland
+ '250', # France
+ '276', # Germany
+ '300', # Greece
+ '348', # Hungary
+ '372', # Ireland
+ '380', # Italy
+ '428', # Latvia
+ '440', # Lithuania
+ '442', # Luxembourg
+ '470', # Malta
+ '528', # Netherland
+ '616', # Poland
+ '620', # Portugal
+ '642', # Romania
+ '703', # Slovakia
+ '705', # Slovenia
+ '724', # Spain
+ '752', # Sweden
+ '900', # N. Ireland
+)
+"""The collection of member state codes (for MSI) that may make up a VAT
number."""
+
+
+def compact(number):
+ """Compact European VAT Number"""
+ return clean(number, ' -').upper().strip()
+
+
+def validate(number):
+ """Validate European VAT Number"""
+ number = compact(number)
+ if number.startswith('EU'):
+ if len(number) != 11:
+ raise InvalidLength()
+ elif number.startswith('IM'):
+ if len(number) != 12:
+ raise InvalidLength()
+ else:
+ raise InvalidComponent()
+ if not isdigits(number[2:]):
+ raise InvalidFormat()
+ if number[2:5] not in ISO_3166_1_MEMBER_STATES:
+ raise InvalidComponent()
+ return number
+
+
+def is_valid(number):
+ """Check if the number is a valid VAT number. This performs the
+ country-specific check for the number."""
+ try:
+ return bool(validate(number))
+ except ValidationError:
+ return False
diff --git a/stdnum/eu/vat.py b/stdnum/eu/vat.py
index 074ec89..33d18b8 100644
--- a/stdnum/eu/vat.py
+++ b/stdnum/eu/vat.py
@@ -39,6 +39,7 @@ that country.
['nl']
"""
+from stdnum.eu import oss
from stdnum.exceptions import *
from stdnum.util import clean, get_cc_module, get_soap_client
@@ -62,6 +63,8 @@ def _get_cc_module(cc):
"""Get the VAT number module based on the country code."""
# Greece uses a "wrong" country code
cc = cc.lower()
+ if cc in ('eu', 'im'):
+ return oss
if cc == 'el':
cc = 'gr'
if cc not in MEMBER_STATES:
diff --git a/tests/test_eu_oss.doctest b/tests/test_eu_oss.doctest
new file mode 100644
index 0000000..23889a4
--- /dev/null
+++ b/tests/test_eu_oss.doctest
@@ -0,0 +1,68 @@
+test_eu_oss.doctest - more detailed doctests for the stdnum.eu.oss module
+
+Copyright (C) 2023 Arthur de Jong
+Copyright (C) 2023 Sergi Almacellas Abellana
+
+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.eu.oss module.
+
+>>> from stdnum.eu import oss
+
+#>>> from stdnum.exceptions import *
+
+
+Extra tests for some corner cases.
+
+>>> oss.validate('AA826010755') # first digits wrong
+Traceback (most recent call last):
+ ...
+InvalidComponent: ...
+>>> oss.validate('EU372A22452') # some digits not numeric
+Traceback (most recent call last):
+ ...
+InvalidFormat: ...
+>>> oss.validate('EU123010755') # MSI wrong
+Traceback (most recent call last):
+ ...
+InvalidComponent: ...
+>>> oss.validate('EU3720000224')
+Traceback (most recent call last):
+ ...
+InvalidLength: ...
+>>> oss.validate('IM372022452')
+Traceback (most recent call last):
+ ...
+InvalidLength: ...
+
+
+
+These have been found online and should all be valid numbers. Interestingly
+the VIES VAT number validation does not support validating numbers issued
+under the non-union or import schemes.
+
+https://en.wikipedia.org/wiki/VAT_identification_number also lists
+EU826010755 for Godaddy and EU826009064 for AWS but neither seem to be valid.
+
+>>> numbers = '''
+...
+... EU372022452
+... IM3720000224
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not oss.is_valid(x)]
+[]
diff --git a/tests/test_eu_vat.doctest b/tests/test_eu_vat.doctest
index cde37af..7f81ec4 100644
--- a/tests/test_eu_vat.doctest
+++ b/tests/test_eu_vat.doctest
@@ -258,6 +258,8 @@ These have been found online and should all be valid
numbers.
... EL: 094279805
... El 800 179 925
...
+... EU372022452
+...
... FI 02459042
... FI 0982651-1
... FI 10320534
-----------------------------------------------------------------------
Summary of changes:
stdnum/eu/oss.py | 120 ++++++++++++++++++++++++++++++++++++++++++++++
stdnum/eu/vat.py | 3 ++
tests/test_eu_oss.doctest | 68 ++++++++++++++++++++++++++
tests/test_eu_vat.doctest | 2 +
4 files changed, 193 insertions(+)
create mode 100644 stdnum/eu/oss.py
create mode 100644 tests/test_eu_oss.doctest
hooks/post-receive
--
python-stdnum
- python-stdnum branch master updated. 1.18-29-gf58e08d,
Commits of the python-stdnum project