diff --git a/README b/README index 60ef4de9..0d8c0879 100644 --- a/README +++ b/README @@ -132,6 +132,7 @@ Currently this package supports the following formats: * Onderwijsnummer (the Dutch student identification number) * Postcode (the Dutch postal code) * Norwegian IBAN (International Bank Account Number) + * Norwegian eleven-digit birth number (fødselsnummer) * Konto nr. (Norwegian bank account number) * MVA (Merverdiavgift, Norwegian VAT number) * Orgnr (Organisasjonsnummer, Norwegian organisation number) @@ -145,6 +146,7 @@ Currently this package supports the following formats: * ИНН (Идентификационный номер налогоплательщика, Russian tax identifier) * Orgnr (Organisationsnummer, Swedish company number) * VAT (Moms, Mervärdesskatt, Swedish VAT number) + * Swedish Personal identity number * ID za DDV (Davčna številka, Slovenian VAT number) * IČ DPH (IČ pre daň z pridanej hodnoty, Slovak VAT number) * RČ (Rodné číslo, the Slovak birth number) diff --git a/stdnum/cn/ric.py b/stdnum/cn/ric.py index e5289109..fbf832e0 100644 --- a/stdnum/cn/ric.py +++ b/stdnum/cn/ric.py @@ -75,7 +75,7 @@ def calc_check_digit(number): return 'X' if checksum == 10 else str(checksum) -def validate(number): +def validate(number, validate_region=False): """Check if the number is a valid RIC number. This checks the length, formatting and birth date and place.""" number = compact(number) @@ -88,11 +88,12 @@ def validate(number): if number[-1] != calc_check_digit(number): raise InvalidChecksum() get_birth_date(number) - get_birth_place(number) + if validate_region: + get_birth_place(number) return number -def is_valid(number): +def is_valid(number, validate_region=False): """Check if the number is a valid RIC number.""" try: return bool(validate(number)) diff --git a/tests/cn_ssn_test.py b/tests/cn_ssn_test.py new file mode 100644 index 00000000..155d6a5f --- /dev/null +++ b/tests/cn_ssn_test.py @@ -0,0 +1,39 @@ +# flake8: noqa +import unittest + +from stdnum.cn import ric +from stdnum.exceptions import ValidationError + + +VALID_SSN = ['486268198802140611', '354133198209290022', '338720197801060214', + '387908198001010226', '341617198002120424', '38064219921117061X', + '45883019880120031X'] + + +class TestChinaRic(unittest.TestCase): + def test_non_digit(self): + try: + ric.validate('It is a bad SSN') + self.assertTrue(False, 'Should throw ValidationError') + except ValidationError: + self.assertTrue(True, 'Should throw ValidationError') + + def test_valid(self): + for number in VALID_SSN: + ric.validate(number) + self.assertTrue(ric.is_valid(number)) + + def test_invalid_checksum(self): + for num in VALID_SSN: + checksum = num[-1:] + + for n in range(0, 10): + if str(n) == checksum: + continue + number = num[:-1] + str(n) + self.assertFalse(ric.is_valid(number)) + try: + ric.validate(number) + self.assertTrue(False, 'Should throw ValidationError') + except ValidationError: + self.assertTrue(True, 'Should throw ValidationError') diff --git a/tests/no_ssn_test.py b/tests/no_ssn_test.py new file mode 100644 index 00000000..e304b29c --- /dev/null +++ b/tests/no_ssn_test.py @@ -0,0 +1,81 @@ +# flake8: noqa +import unittest + +from stdnum.no import personalid as ssn +from stdnum.exceptions import ValidationError + + +VALID_SSN = ( + ('42957044500', 1), + ('11027794191', 1), + ('31042639152', 1), + ('71946503120', 1), + ('95700625908', 1), + ('68413152112', 1), + ('56653047547', 1), + ('70624830529', 1), + ('75442702381', 1), + ('34831582121', 1), + ('27389446152', 1), + ('96517753502', 1), + ('46929323343', 1), + ('92782833709', 1), + ('40070897972', 1), + ('56403643756', 1), + ('24396859900', 1), + ('89829529360', 1), + ('30383131118', 1), + ('30777674125', 1), + ('71494457037', 0), + ('83814827871', 0), + ('40673759612', 0), + ('44207789809', 0), + ('70341666064', 0), + ('11051996811', 0), + ('39043009846', 0), + ('27213364885', 0), + ('70031073454', 0), + ('42115114470', 0), + ('19575770838', 0), + ('50067834221', 0), + ('63282310041', 0), + ('42485176432', 0), + ('98576936818', 0), + ('79318270827', 0), + ('21918484865', 0), + ('79189404641', 0), + ('82938389280', 0), + ('45014054018', 0), +) + + +class TestNorwaySSN(unittest.TestCase): + def test_non_digit(self): + try: + ssn.validate('It is a bad SSN') + self.assertTrue(False, 'Should throw ValidationError') + except ValidationError: + self.assertTrue(True, 'Should throw ValidationError') + + def test_valid(self): + for number, _ in VALID_SSN: + ssn.validate(number) + self.assertTrue(ssn.is_valid(number)) + + def test_valid_gender(self): + # 1 - Male, 0 - Female + for number, gender in VALID_SSN: + self.assertTrue(ssn.get_gender(number) == 'M' if gender else 'F') + + def test_invalid_checksum(self): + def check_number(number): + self.assertFalse(ssn.is_valid(number)) + + for num, gender in VALID_SSN: + checksum = int(num[-2:]) + + for n in range(0, 100): + if n == checksum: + continue + number = num[:-2] + '%02d' % n + check_number(number) diff --git a/tests/se_ssn_test.py b/tests/se_ssn_test.py new file mode 100644 index 00000000..8df4f227 --- /dev/null +++ b/tests/se_ssn_test.py @@ -0,0 +1,45 @@ +# flake8: noqa +""" +Test for Swedish Personal identity number +""" + +import unittest + +from stdnum.se import personalid as ssn +from stdnum.exceptions import ValidationError + + +VALID_SSN = ['880320-0016', '880320-0057', '8803200073', '8803200099', '8803200420', + '8803200115', '8803200131', '8803200156', '8803200172', '8803200198'] + + +class TestSwedenSSN(unittest.TestCase): + """ + Test for Swedish Personal identity number + """ + def test_non_digit(self): + try: + ssn.validate('a' * 10) + self.assertTrue(False, 'Should throw ValidationError') + except ValidationError: + self.assertTrue(True, 'Should throw ValidationError') + + def test_valid(self): + for number in VALID_SSN: + ssn.validate(number) + self.assertTrue(ssn.is_valid(number)) + + def test_invalid_checksum(self): + for num in VALID_SSN: + checksum = int(num[-1:]) + + for n in range(0, 10): + if n == checksum: + continue + number = num[:-1] + str(n) + self.assertFalse(ssn.is_valid(number)) + try: + ssn.validate(number) + self.assertTrue(False, 'Should throw ValidationError') + except ValidationError: + self.assertTrue(True, 'Should throw ValidationError') diff --git a/tests/test_cn_ric.doctest b/tests/test_cn_ric.doctest index 5b219481..ce0a2e7d 100644 --- a/tests/test_cn_ric.doctest +++ b/tests/test_cn_ric.doctest @@ -84,7 +84,7 @@ InvalidChecksum: ... Invalid location: ->>> ric.validate('990426199112010074') # unknown birth place code +>>> ric.validate('990426199112010074', validate_region=True) # unknown birth place code Traceback (most recent call last): ... InvalidComponent: ...