Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-05-17 13:18:31 +0200
committerArthur de Jong <arthur@arthurdejong.org>2013-06-08 14:45:39 +0200
commit10710dcccf7ae453983d785e8fbcc5a53dfb485e (patch)
tree402fb1cb96f994cbbd42789b0d935a0880f93989
parent4753c09e81a0adb6b62d12ad60f5a5107d5033c2 (diff)
Implement validate() for United Kingdom numbers
-rw-r--r--stdnum/gb/vat.py57
-rw-r--r--tests/test_gb_vat.doctest52
2 files changed, 75 insertions, 34 deletions
diff --git a/stdnum/gb/vat.py b/stdnum/gb/vat.py
index 98b4a35..f502a5c 100644
--- a/stdnum/gb/vat.py
+++ b/stdnum/gb/vat.py
@@ -1,6 +1,6 @@
# vat.py - functions for handling United Kingdom VAT numbers
#
-# Copyright (C) 2012 Arthur de Jong
+# Copyright (C) 2012, 2013 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
@@ -25,17 +25,18 @@ government departments (first two digits are GD) or a 5-digit number for
health authorities (first two digits are HA). The 9-digit variants use a
weighted checksum.
->>> compact('GB 980 7806 84')
+>>> validate('GB 980 7806 84')
'980780684'
->>> is_valid('980780684')
-True
->>> is_valid('802311781') # invalid check digit
-False
+>>> validate('802311781') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
>>> format('980780684')
'980 7806 84'
"""
from stdnum.util import clean
+from stdnum.exceptions import *
def compact(number):
@@ -54,26 +55,40 @@ def checksum(number):
return sum(weights[i] * int(n) for i, n in enumerate(number)) % 97
+def validate(number):
+ """Checks to see if the number provided is a valid VAT number. This
+ checks the length, formatting and check digit."""
+ number = compact(number)
+ if len(number) == 5:
+ if not number[2:].isdigit():
+ raise InvalidFormat()
+ if number.startswith('GD') and int(number[2:]) < 500:
+ # government department
+ pass
+ elif number.startswith('HA') and int(number[2:]) >= 500:
+ # health authority
+ pass
+ else:
+ raise InvalidComponent()
+ elif len(number) in (9, 12):
+ if not number.isdigit():
+ raise InvalidFormat()
+ # standard number: nnn nnnn nn
+ # branch trader: nnn nnnn nn nnn (ignore the last thee digits)
+ if checksum(number[:9]) not in (0, 42):
+ raise InvalidChecksum()
+ else:
+ raise InvalidLength()
+ return number
+
+
def is_valid(number):
"""Checks to see if the number provided is a valid VAT number. This
checks the length, formatting and check digit."""
try:
- number = compact(number)
- except:
+ return bool(validate(number))
+ except ValidationError:
return False
- if len(number) == 5 and number.startswith('GD') and number[2:].isdigit():
- # government department
- return int(number[2:]) < 500
- if len(number) == 5 and number.startswith('HA') and number[2:].isdigit():
- # health authority
- return int(number[2:]) >= 500
- if len(number) == 12 and number.isdigit():
- # branch trader: nnn nnnn nn nnn (ignore the last thee digits)
- return checksum(number[:-3]) in (0, 42)
- if len(number) == 9 and number.isdigit():
- # standard number: nnn nnnn nn
- return checksum(number) in (0, 42)
- return False
def format(number):
diff --git a/tests/test_gb_vat.doctest b/tests/test_gb_vat.doctest
index 1537a5d..cdcfe36 100644
--- a/tests/test_gb_vat.doctest
+++ b/tests/test_gb_vat.doctest
@@ -1,6 +1,6 @@
test_gb_vat.doctest - more detailed doctests for stdnum.gb.vat module
-Copyright (C) 2012 Arthur de Jong
+Copyright (C) 2012, 2013 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
@@ -27,20 +27,46 @@ really useful as module documentation.
Normal values that should just work.
->>> vat.is_valid('980780684') # standard number
-True
->>> vat.is_valid('242338087388') # branch trader
-True
->>> vat.is_valid('GD100') # government department
-True
->>> vat.is_valid('HA501') # health authority
-True
-
+>>> vat.validate('980780684') # standard number
+'980780684'
+>>> vat.validate('242338087388') # branch trader
+'242338087388'
+>>> vat.validate('GD100') # government department
+'GD100'
+>>> vat.validate('HA501') # health authority
+'HA501'
-Invalid checksum:
->>> vat.is_valid('802311781') # invalid check digit
-False
+Invalid long numbers:
+
+>>> vat.validate('802311781') # invalid check digit
+Traceback (most recent call last):
+ ...
+InvalidChecksum: ...
+>>> vat.validate('9807806842') # too long for standard number
+Traceback (most recent call last):
+ ...
+InvalidLength: ...
+>>> vat.validate('9807806B4') # invalid digit
+Traceback (most recent call last):
+ ...
+InvalidFormat: ...
+
+
+Some variations on the short format:
+
+>>> vat.validate('ZZ100') # unknown code
+Traceback (most recent call last):
+ ...
+InvalidComponent: ...
+>>> vat.validate('GD600') # government department with high number
+Traceback (most recent call last):
+ ...
+InvalidComponent: ...
+>>> vat.validate('HA201') # health authority with low number
+Traceback (most recent call last):
+ ...
+InvalidComponent: ...
Formatting tests: