lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.1-29-g320ecea

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

python-stdnum branch master updated. 1.1-29-g320ecea



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  320ecea83701cf1a371e360542504414a6403249 (commit)
      from  ec9bcb0f13971b70e40dff7a6de3d4744ee4ea61 (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 -----------------------------------------------------------------
http://arthurdejong.org/git/python-stdnum/commit/?id=320ecea83701cf1a371e360542504414a6403249

commit 320ecea83701cf1a371e360542504414a6403249
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Thu Oct 8 14:30:57 2015 +0200

    Add Swiss UID and VAT numbers
    
    The Swiss VAT number (MWST, TVA, IVA, TPV) is the UID
    (Unternehmens-Identifikationsnummer) followed by one of the VAT
    abbreviations.

diff --git a/stdnum/ch/uid.py b/stdnum/ch/uid.py
new file mode 100644
index 0000000..6622f50
--- /dev/null
+++ b/stdnum/ch/uid.py
@@ -0,0 +1,90 @@
+# uid.py - functions for handling Swiss business identifiers
+# coding: utf-8
+#
+# Copyright (C) 2015 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
+# 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
+
+"""UID (Unternehmens-Identifikationsnummer, Swiss business identifier).
+
+The Swiss UID is used to uniquely identify businesses for taxation purposes.
+The number consists of a fixed "CHE" prefix, followed by 9 digits that are
+protected with a simple checksum.
+
+This module only supports the "new" format that was introduced in 2011 which
+completely replaced the "old" 6-digit format in 2014.
+
+More information is available at:
+  https://www.uid.admin.ch/
+  https://de.wikipedia.org/wiki/Unternehmens-Identifikationsnummer
+
+>>> validate('CHE-100.155.212')
+'CHE100155212'
+>>> validate('CHE-100.155.213')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> format('CHE100155212')
+'CHE-100.155.212'
+"""
+
+from stdnum.exceptions import *
+from stdnum.util import clean
+
+
+def compact(number):
+    """Convert the number to the minimal representation. This strips
+    surrounding whitespace and separators."""
+    return clean(number, ' -.').strip().upper()
+
+
+def calc_check_digit(number):
+    """Calculate the check digit for organisations. The number passed should
+    not have the check digit included."""
+    weights = (5, 4, 3, 2, 7, 6, 5, 4)
+    s = sum(w * int(n) for w, n in zip(weights, number))
+    return str((11 - s) % 11)
+
+
+def validate(number):
+    """Checks to see if the number provided is a valid number. This checks
+    the length, formatting and check digit."""
+    number = compact(number)
+    if len(number) != 12:
+        raise InvalidLength()
+    if not number.startswith('CHE'):
+        raise InvalidComponent()
+    if not number[3:].isdigit():
+        raise InvalidFormat()
+    if number[-1] != calc_check_digit(number[3:-1]):
+        raise InvalidChecksum()
+    return number
+
+
+def is_valid(number):
+    """Checks to see if the number provided is a valid number. This checks
+    the length, formatting and check digit."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
+
+
+def format(number):
+    """Reformat the passed number to the standard format."""
+    number = compact(number)
+    return number[:3] + '-' + '.'.join(
+        number[i:i + 3] for i in range(3, len(number), 3))
diff --git a/stdnum/ch/vat.py b/stdnum/ch/vat.py
new file mode 100644
index 0000000..a61c49e
--- /dev/null
+++ b/stdnum/ch/vat.py
@@ -0,0 +1,79 @@
+# vat.py - functions for handling Swiss VAT numbers
+# coding: utf-8
+#
+# Copyright (C) 2015 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
+# 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
+
+"""VAT, MWST, TVA, IVA, TPV (Mehrwertsteuernummer, the Swiss VAT number).
+
+The Swiss VAT number is based on the UID but is followed by either "MWST"
+(Mehrwertsteuer, the German abbreviation for VAT), "TVA" (Taxe sur la valeur
+ajoutée in French), "IVA" (Imposta sul valore aggiunto in Italian) or "TPV"
+(Taglia sin la plivalur in Romanian).
+
+This module only supports the "new" format that was introduced in 2011 which
+completely replaced the "old" 6-digit format in 2014.
+
+More information is available at:
+  
https://www.ch.ch/en/value-added-tax-number-und-business-identification-number/
+  https://www.uid.admin.ch/
+
+>>> validate('CHE-107.787.577 IVA')
+'CHE107787577IVA'
+>>> validate('CHE-107.787.578 IVA')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> format('CHE107787577IVA')
+'CHE-107.787.577 IVA'
+"""
+
+from stdnum.exceptions import *
+from stdnum.ch import uid
+
+
+def compact(number):
+    """Convert the number to the minimal representation. This strips
+    surrounding whitespace and separators."""
+    return uid.compact(number)
+
+
+def validate(number):
+    """Checks to see if the number provided is a valid number. This checks
+    the length, formatting and check digit."""
+    number = compact(number)
+    if len(number) not in (15, 16):
+        raise InvalidLength()
+    uid.validate(number[:12])
+    if number[12:] not in ('MWST', 'TVA', 'IVA', 'TPV'):
+        raise InvalidComponent()
+    return number
+
+
+def is_valid(number):
+    """Checks to see if the number provided is a valid number. This checks
+    the length, formatting and check digit."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
+
+
+def format(number):
+    """Reformat the passed number to the standard format."""
+    number = compact(number)
+    return uid.format(number[:12]) + ' ' + number[12:]
diff --git a/tests/test_ch_uid.doctest b/tests/test_ch_uid.doctest
new file mode 100644
index 0000000..04cd2a9
--- /dev/null
+++ b/tests/test_ch_uid.doctest
@@ -0,0 +1,183 @@
+test_ch_uid.doctest - more detailed doctests for the stdnum.ch.uid module
+
+Copyright (C) 2015 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
+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.ch.uid module.
+
+>>> from stdnum.ch import uid
+>>> from stdnum.exceptions import *
+
+
+Some more detailed tests.
+
+>>> uid.validate('ZZZ-107.787.577')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> uid.validate('CHE-10A.787.577')
+Traceback (most recent call last):
+    ...
+InvalidFormat: ...
+
+
+These have been found online and should all be valid numbers.
+
+>>> numbers = '''
+...
+... CHE 113.042.942.
+... CHE-101.415.551
+... CHE-105.067.880
+... CHE-105.616.108
+... CHE-105.838.471
+... CHE-106.222.918
+... CHE-108.902.220
+... CHE-112.786.448
+... CHE-113.606.230
+... CHE-113.606.253
+... CHE-113.614.519
+... CHE-113.617.417
+... CHE-113.638.690
+... CHE-113.690.319
+... CHE-113.706.877
+... CHE-113.840.903
+... CHE-114.165.895
+... CHE-114.332.288
+... CHE-114.365.477
+... CHE-114.557.166
+... CHE-114.587.210
+... CHE-114.764.713
+... CHE-114.921.562
+... CHE-115.117.491
+... CHE-115.188.717
+... CHE-115.257.146
+... CHE-115.401.147
+... CHE-115.681.283
+... CHE-115.702.784
+... CHE-115.901.131
+... CHE-116.018.087
+... CHE-116.022.172
+... CHE-116.024.389
+... CHE-116.066.413
+... CHE-116.066.436
+... CHE-116.066.459
+... CHE-116.066.465
+... CHE-116.066.471
+... CHE-116.066.488
+... CHE-116.068.168
+... CHE-116.068.180
+... CHE-116.068.257
+... CHE-116.068.369
+... CHE-116.068.375
+... CHE-116.068.398
+... CHE-116.068.435
+... CHE-116.068.470
+... CHE-116.068.524
+... CHE-116.068.582
+... CHE-131.608.474
+... CHE-132.071.565
+... CHE-133.192.355
+... CHE-145.202.776
+... CHE-146.680.598
+... CHE-154.748.703
+... CHE-154.936.162
+... CHE-157.957.462
+... CHE-164.589.300
+... CHE-165.355.615
+... CHE-170.094.053
+... CHE-172.763.936
+... CHE-187.271.257
+... CHE-188.858.471
+... CHE-190.214.202
+... CHE-193.052.812
+... CHE-199.027.184
+... CHE-199.213.611
+... CHE-200.143.304
+... CHE-200.474.557
+... CHE-201.091.609
+... CHE-208.913.684
+... CHE-211.403.691
+... CHE-221.032.573
+... CHE-221.432.665
+... CHE-222.251.936
+... CHE-222.259.895
+... CHE-226.253.064
+... CHE-226.598.037
+... CHE-247.670.953
+... CHE-254.168.819
+... CHE-255.108.719
+... CHE-255.286.924
+... CHE-261.860.174
+... CHE-263.297.189
+... CHE-264.708.255
+... CHE-265.476.805
+... CHE-268.880.226
+... CHE-276.015.555
+... CHE-276.258.224
+... CHE-279.426.498
+... CHE-288.910.965
+... CHE-304.459.014
+... CHE-313.282.453
+... CHE-316.510.171
+... CHE-317.089.412
+... CHE-319.639.393
+... CHE-320.640.339
+... CHE-322.193.357
+... CHE-325.352.422
+... CHE-327.285.558
+... CHE-335.670.007
+... CHE-360.001.499
+... CHE-363.192.993
+... CHE-367.908.992
+... CHE-378.338.277
+... CHE-379.051.878
+... CHE-383.713.530
+... CHE-392.445.860
+... CHE-397.984.845
+... CHE-400.352.783
+... CHE-402.703.876
+... CHE-403.244.345
+... CHE-404.107.716
+... CHE-405.509.388
+... CHE-415.481.515
+... CHE-420.485.329
+... CHE-422.892.792
+... CHE-424.195.422
+... CHE-430.271.592
+... CHE-433.064.977
+... CHE-443.047.638
+... CHE-444.796.174
+... CHE-444.901.873
+... CHE-445.737.990
+... CHE-446.609.550
+... CHE-447.518.447
+... CHE-447.564.660
+... CHE-449.312.098
+... CHE-450.220.178
+... CHE-460.147.005
+... CHE-467.023.568
+... CHE-468.593.911
+... CHE-475.427.548
+... CHE-478.406.525
+... CHE-488.502.886
+... CHE-488.972.766
+... CHE-489.713.641
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not uid.is_valid(x)]
+[]
diff --git a/tests/test_ch_vat.doctest b/tests/test_ch_vat.doctest
new file mode 100644
index 0000000..c13f8df
--- /dev/null
+++ b/tests/test_ch_vat.doctest
@@ -0,0 +1,68 @@
+test_ch_vat.doctest - more detailed doctests for the stdnum.ch.vat module
+
+Copyright (C) 2015 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
+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.ch.vat module.
+
+>>> from stdnum.ch import vat
+>>> from stdnum.exceptions import *
+
+
+Some more detailed tests.
+
+>>> vat.validate('CHE-107.787.577 ZZZ')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> vat.validate('ZZZ-107.787.577 MWST')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+
+
+These have been found online and should all be valid numbers.
+
+>>> numbers = '''
+...
+... CHE-1 76.814.97 5 MWST
+... CHE-100.155.212 MWST
+... CHE-105.048.256 MWST
+... CHE-105.838.471 MWST
+... CHE-105.969.179 MWST
+... CHE-106.222.918 MWST
+... CHE-107.787.577 IVA
+... CHE-108.113.335 MwST
+... CHE-108.446.096 MWST
+... CHE-108.703.181 MWST
+... CHE-109.578.122 MWST
+... CHE-110.576.236 IVA
+... CHE-110.576.236 TVA
+... CHE-112.142.015 TVA
+... CHE-112.487.804 MWST
+... CHE-113.330.424 MWST
+... CHE-115.606.778 MWST
+... CHE-116.046.681 TPV
+... CHE-116.274.213 MWST
+... CHE-116.320.362 MWST
+... CHE-164.589.300 MWST
+... CHE-400.352.783 MWST
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not vat.is_valid(x)]
+[]

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

Summary of changes:
 stdnum/{co/nit.py => ch/uid.py} |   59 +++++++------
 stdnum/{co/nit.py => ch/vat.py} |   60 ++++++-------
 tests/test_ch_uid.doctest       |  183 +++++++++++++++++++++++++++++++++++++++
 tests/test_ch_vat.doctest       |   68 +++++++++++++++
 4 files changed, 312 insertions(+), 58 deletions(-)
 copy stdnum/{co/nit.py => ch/uid.py} (53%)
 copy stdnum/{co/nit.py => ch/vat.py} (55%)
 create mode 100644 tests/test_ch_uid.doctest
 create mode 100644 tests/test_ch_vat.doctest


hooks/post-receive
-- 
python-stdnum
-- 
To unsubscribe send an email to
python-stdnum-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/python-stdnum-commits/