lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.8.1-16-g98d11a3

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

python-stdnum branch master updated. 1.8.1-16-g98d11a3



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  98d11a315938fbae9283075c5ca3c6779da4fd17 (commit)
      from  ab15e206abe8778eaf8109ddf209ab228c81c79d (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=98d11a315938fbae9283075c5ca3c6779da4fd17

commit 98d11a315938fbae9283075c5ca3c6779da4fd17
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Mar 18 19:43:35 2018 +0100

    Add Austrian Abgabenkontonummer
    
    Based on the implementation provided by Mohammed Salman of Holvi.
    
    Closes https://github.com/arthurdejong/python-stdnum/pull/50

diff --git a/stdnum/at/fa.dat b/stdnum/at/fa.dat
new file mode 100644
index 0000000..c632d49
--- /dev/null
+++ b/stdnum/at/fa.dat
@@ -0,0 +1,42 @@
+# List of Finanzamtsnummern was manually generated from
+# https://de.wikipedia.org/wiki/Abgabenkontonummer
+03 office="Wien 3/6/7/11/15 Schwechat Gerasdorf" region="Wien"
+04 office="Wien 4/5/10" region="Wien"
+06 office="Wien 8/16/17" region="Wien"
+07 office="Wien 9/18/19 Klosterneuburg" region="Wien"
+08 office="Wien 12/13/14 Purkersdorf" region="Wien"
+09 office="Wien 1/23" region="Wien"
+10 office="für Gebühren, Verkehrsteuern und Glücksspiel" region=""
+12 office="Wien 2/20/21/22" region="Wien"
+15 office="Amstetten Melk Scheibbs" region="Niederösterreich"
+16 office="Baden Mödling" region="Niederösterreich"
+18 office="Gänserndorf Mistelbach" region="Niederösterreich"
+22 office="Hollabrunn Korneuburg Tulln" region="Niederösterreich"
+23 office="Waldviertel" region="Niederösterreich"
+29 office="Lilienfeld St. Pölten" region="Niederösterreich"
+33 office="Neunkirchen Wr. Neustadt" region="Niederösterreich"
+38 office="Bruck Eisenstadt Oberwart" region="Burgenland, Niederösterreich"
+41 office="Braunau Ried Schärding" region="Oberösterreich"
+46 office="Linz" region="Oberösterreich"
+51 office="Kirchdorf Perg Steyr" region="Oberösterreich"
+52 office="Freistadt Rohrbach Urfahr" region="Oberösterreich"
+53 office="Gmunden Vöcklabruck" region="Oberösterreich"
+54 office="Grieskirchen Wels" region="Oberösterreich"
+57 office="Klagenfurt" region="Kärnten"
+59 office="St. Veit Wolfsberg" region="Kärnten"
+61 office="Spittal Villach" region="Kärnten"
+65 office="Bruck Leoben Mürzzuschlag" region="Steiermark"
+67 office="Oststeiermark" region="Steiermark"
+68 office="Graz-Stadt" region="Steiermark"
+69 office="Graz-Umgebung" region="Steiermark"
+71 office="Judenburg Liezen" region="Steiermark"
+72 office="Deutschlandsberg Leibnitz Voitsberg" region="Steiermark"
+81 office="Innsbruck" region="Tirol"
+82 office="Kitzbühel Lienz" region="Tirol"
+83 office="Kufstein Schwaz" region="Tirol"
+84 office="Landeck Reutte" region="Tirol"
+90 office="St. Johann Tamsweg Zell am See" region="Salzburg"
+91 office="Salzburg-Stadt" region="Salzburg"
+93 office="Salzburg-Land" region="Salzburg"
+97 office="Bregenz" region="Vorarlberg"
+98 office="Feldkirch" region="Vorarlberg"
diff --git a/stdnum/at/tin.py b/stdnum/at/tin.py
new file mode 100644
index 0000000..f79b0dc
--- /dev/null
+++ b/stdnum/at/tin.py
@@ -0,0 +1,113 @@
+# tin.py - functions for handling Austrian tax identification numbers
+# coding: utf-8
+#
+# Copyright (C) 2017 Holvi Payment Services Oy
+# Copyright (C) 2018 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
+
+r"""Abgabenkontonummer (Austrian tax identification number).
+
+The Austrian tax identification number (Abgabenkontonummer) consists of 2
+digits for the issuing tax office (Finanzamtsnummer) and 7 digits for the
+subject and a check digit (Steuernummer).
+
+More information:
+
+* https://de.wikipedia.org/wiki/Abgabenkontonummer
+* https://service.bmf.gv.at/Service/Anwend/Behoerden/show_mast.asp
+
+>>> validate('59-119/9013')
+'591199013'
+>>> validate('59-119/9013', office='St. Veit Wolfsberg')
+'591199013'
+>>> import json
+>>> print(json.dumps(info('59-119/9013'), indent=2, sort_keys=True))
+{
+  "office": "St. Veit Wolfsberg",
+  "region": "K\u00e4rnten"
+}
+>>> format('591199013')
+'59-119/9013'
+"""
+
+from stdnum.exceptions import *
+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."""
+    return clean(number, ' -./,').strip()
+
+
+def _min_fa(office):
+    """Convert the tax office name to something that we can use for
+    comparison without running into encoding issues."""
+    return ''.join(
+        x for x in office.lower()
+        if x in 'abcdefghijklmnopqrstvwxyz')
+
+
+def calc_check_digit(number):
+    """Calculate the check digit."""
+    number = compact(number)
+    s = sum(
+        int('0246813579'[int(n)]) if i % 2 else int(n)
+        for i, n in enumerate(number[:8]))
+    return str((10 - s) % 10)
+
+
+def info(number):
+    """Return a dictionary of data about the supplied number. This typically
+    returns the the tax office and region."""
+    number = compact(number)
+    from stdnum import numdb
+    return numdb.get('at/fa').info(number[:2])[0][1]
+
+
+def validate(number, office=None):
+    """Check if the number is a valid tax identification number. This checks
+    the length and formatting. The tax office can be supplied to check that
+    the number was issued in the specified tax office."""
+    number = compact(number)
+    if len(number) != 9:
+        raise InvalidLength()
+    if not number.isdigit():
+        raise InvalidFormat()
+    if calc_check_digit(number) != number[-1]:
+        raise InvalidChecksum()
+    i = info(number)
+    if not i:
+        raise InvalidComponent()
+    if office and _min_fa(i.get('office')) != _min_fa(office):
+        raise InvalidComponent()
+    return number
+
+
+def is_valid(number, office=None):
+    """Check if the number is a valid tax identification number. This checks
+    the length, formatting and check digit."""
+    try:
+        return bool(validate(number, office))
+    except ValidationError:
+        return False
+
+
+def format(number):
+    """Reformat the number to the standard presentation format."""
+    number = compact(number)
+    return '%s-%s/%s' % (number[:2], number[2:5], number[5:])
diff --git a/tests/test_at_tin.doctest b/tests/test_at_tin.doctest
new file mode 100644
index 0000000..3a2da53
--- /dev/null
+++ b/tests/test_at_tin.doctest
@@ -0,0 +1,195 @@
+test_at_tin.doctest - more detailed doctests for the stdnum.at.tin module
+
+Copyright (C) 2018 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.at.tin module. It
+tries to test more corner cases and detailed functionality that is not really
+useful as module documentation.
+
+>>> from stdnum import bic
+>>> from stdnum.at import tin
+
+
+Test more corner cases.
+
+>>> tin.validate('59-119/9013')
+'591199013'
+>>> tin.validate('59-119/9013', office='St. Veit Wolfsberg')
+'591199013'
+>>> tin.validate('59-119/9013', office='Spittal Villach')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> tin.validate('00XXXXXXX')
+Traceback (most recent call last):
+    ...
+InvalidFormat: ...
+>>> tin.validate('X12345678')
+Traceback (most recent call last):
+    ...
+InvalidFormat: ...
+>>> tin.validate('12345678')
+Traceback (most recent call last):
+    ...
+InvalidLength: ...
+>>> tin.validate('591199012')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> tin.validate('621199017')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+
+
+These should all be valid numbers.
+
+>>> numbers = '''
+... 98-123/4560
+... 90-123/4567
+... 12-987/6546
+... 46-376/5321
+... 03-826/1574
+... 54-267/9451
+...
+... 03 318/8822
+... 109999102
+... 12 035/4980
+... 12 504/1558
+... 12 528/1691
+... 22 283/3014
+... 29 122/4046
+... 38-999/9384
+... 41 248/1145
+... 46 1744591
+... 52-123/4567
+... 52-360/5855
+... 53 226/8059
+... 54 202/0565
+... 59 059/6383
+... 59 119/9013
+... 59 149/7540
+... 61 075/1679
+... 68 481/8826
+... 68 545 4266
+... 68 626/5406
+... 68 649/8114
+... 72 222/3526
+... 81 - 590/9908
+... 91 166/9307
+... 91 195/7272
+... 98 0100127
+... 98 0207336
+... 98 0300131
+... 98 0400378
+... 98 0500219
+... 98 0600092
+... 98 0700306
+... 98 0800130
+... 98 0900096
+... 98 1000284
+... 98 1100803
+... 98 1200363
+... 98 1300460
+... 98 1400534
+... 98 1500234
+... 98 1600042
+... 98 1700198
+... 98 1800212
+... 98 1900087
+... 98 2017196
+... 98 2102535
+... 98 2210643
+... 98 2300873
+... 98 2400038
+... 98 2500597
+... 98 2612509
+... 98 2700601
+... 98 2800047
+... 98 2900110
+... 98 3001314
+... 98 3100249
+... 98 3200445
+... 98 3300104
+... 98 3400326
+... 98 3500091
+... 98 3601303
+... 98 3700030
+... 98 3800194
+... 98 3900234
+... 98 4000257
+... 98 4100164
+... 98 4200287
+... 98 4300152
+... 98 4400010
+... 98 4500207
+... 98 4600254
+... 98 4700211
+... 98 4800318
+... 98 4900050
+... 98 5000157
+... 98 5100411
+... 98 5201573
+... 98 5300227
+... 98 5400027
+... 98 5500701
+... 98 5600360
+... 98 9300280
+... 98 9300363
+... 98 9300454
+... 98 9300579
+... 98 9300686
+... 98 9300736
+... 98 9300801
+... 98 9300819
+... 98 9300827
+... 98 9300850
+... 98 9300868
+... 98 9301015
+... 98 9301080
+... 98 9301155
+... 98 9301189
+... 98 9301247
+... 98 9301270
+... 98 9301304
+... 98 9301387
+... 98 9301528
+... 98 9301593
+... 98 9301676
+... 98 9301684
+... 98 9301841
+... 98 9301908
+... 98 9302021
+... 98 9302104
+... 98 9302161
+... 98 9302286
+... 98 9302310
+... 98 9302450
+... 98 9302500
+... 98 9302559
+... 98 9302690
+... 98 9302807
+... 98 9302831
+... 98 9302864
+... 98 9302914
+... 98 9302963
+... 98 9303086
+... '''
+>>> [x for x in numbers.splitlines() if x and not tin.is_valid(x)]
+[]

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

Summary of changes:
 stdnum/at/fa.dat          |  42 ++++++++++
 stdnum/at/tin.py          | 113 +++++++++++++++++++++++++++
 tests/test_at_tin.doctest | 195 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 350 insertions(+)
 create mode 100644 stdnum/at/fa.dat
 create mode 100644 stdnum/at/tin.py
 create mode 100644 tests/test_at_tin.doctest


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