diff --git a/schwifty/checksum/__init__.py b/schwifty/checksum/__init__.py index 8c88029..29f4be9 100644 --- a/schwifty/checksum/__init__.py +++ b/schwifty/checksum/__init__.py @@ -37,3 +37,4 @@ def register(algorithm_cls: Type[Algorithm], prefix: Optional[str] = None) -> Ty from schwifty.checksum import germany # noqa from schwifty.checksum import italy # noqa +from schwifty.checksum import belgium # noqa diff --git a/schwifty/checksum/belgium.py b/schwifty/checksum/belgium.py new file mode 100644 index 0000000..5adcc6d --- /dev/null +++ b/schwifty/checksum/belgium.py @@ -0,0 +1,18 @@ +import functools + +from schwifty import checksum + + +register = functools.partial(checksum.register, prefix="BE") + + +@register +class DefaultAlgorithm(checksum.Algorithm): + name = "default" + accepts = checksum.InputType.BBAN + + def compute(self, bban: str) -> str: + return str(int(bban[:-2]) % 97) + + def validate(self, bban: str) -> bool: + return bban[-2:] == self.compute(bban) diff --git a/schwifty/iban.py b/schwifty/iban.py index eb014b2..e6eceae 100644 --- a/schwifty/iban.py +++ b/schwifty/iban.py @@ -43,6 +43,20 @@ def add_bban_checksum(country_code: str, bban: str) -> str: if country_code == "IT": checksum = algorithms["IT:default"].compute(bban[1:]) bban = checksum + bban[1:] + elif country_code == "BE": + """ + The Belgian account format is XXX-YYYYYYY-ZZ where: + - XXX: bank code + - YYYYYYY: account number + - ZZ: mod 97 remainder of XXYYYYYYY + """ + # The BBAN as passed in does not have the checksum yet + bank_code, account_number = bban[:3], bban[3:] + # Remove extra zeroes and fill up to 7 spaces again + account_number = account_number.lstrip("0").zfill(7) + # Concatenate again, leave space for the checksum digits + checksum = algorithms["BE:default"].compute(f"{bank_code}{account_number}??") + bban = f"{bank_code}{account_number}{checksum}" return bban diff --git a/tests/test_checksum.py b/tests/test_checksum.py index 06c2e13..82539a9 100644 --- a/tests/test_checksum.py +++ b/tests/test_checksum.py @@ -89,3 +89,11 @@ def test_german_checksum_success(account_code, algorithm_name): ) def test_german_checksum_failure(account_code, algorithm_name): assert algorithms[algorithm_name].validate(account_code) is False + + +def test_belgium_checksum(): + assert algorithms["BE:default"].validate("539007547034") is True + + +def test_belgium_checksum_failure(): + assert algorithms["BE:default"].validate("050000123456") is False diff --git a/tests/test_iban.py b/tests/test_iban.py index d0a6a1b..8484235 100644 --- a/tests/test_iban.py +++ b/tests/test_iban.py @@ -1,6 +1,5 @@ import pytest from pycountry import countries - from schwifty import IBAN from schwifty.exceptions import SchwiftyException @@ -152,6 +151,9 @@ def test_iban_properties(): (("GB", "NWBK", "31926819", "601613"), "GB29NWBK60161331926819"), (("GB", "NWBK", "31926819"), "GB66NWBK00000031926819"), (("GB", "NWBK601613", "31926819"), "GB29NWBK60161331926819"), + (("BE", "050", "123"), "BE66050000012343"), + (("BE", "050", "123456"), "BE45050012345689"), + (("BE", "539", "0075470"), "BE68539007547034"), ], ) def test_generate_iban(components, compact): @@ -206,3 +208,8 @@ def test_bic_from_iban(iban, bic): def test_unknown_bic_from_iban(): assert IBAN("SI72000001234567892").bic is None + + +def test_be_generated_iban_valid(): + iban = IBAN.generate("BE", bank_code="050", account_code="123456") + assert iban.validate(validate_bban=True)