UFN_VALIDATE_ACCOUNTNUMBER

Return

Return Type
bit

Parameters

Parameter Parameter Type Mode Description
@FINANCIALINSTITUTIONID uniqueidentifier IN
@ACCOUNTNUMBER nvarchar(50) IN

Definition

Copy


create function dbo.UFN_VALIDATE_ACCOUNTNUMBER
(
    @FINANCIALINSTITUTIONID uniqueidentifier,
    @ACCOUNTNUMBER nvarchar(50)
)
returns bit
with execute as caller
as 
begin
    /* IBAN validation algorithm
      1)Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid
      2)Move the four initial characters to the end of the string
      3)Replace each letter in the string with two digits, thereby expanding the string, where A = 10, B = 11, ..., Z = 35
      4)Interpret the string as a decimal integer and compute the remainder of that number on division by 97
    */
    declare @CONDITIONSETTINGNAME nvarchar(25);
    select
        @CONDITIONSETTINGNAME = BANKINGSYSTEM.CONDITIONSETTINGNAME
    from
        dbo.BANKINGSYSTEM
        inner join dbo.FINANCIALINSTITUTION on FINANCIALINSTITUTION.BANKINGSYSTEMID = BANKINGSYSTEM.ID
    where
        FINANCIALINSTITUTION.ID = @FINANCIALINSTITUTIONID;

    --ACCOUNTNUMBER is IBAN, do IBAN validation

    --Other (non-SEPA) banking systems don't have validation for ACCOUNTNUMBER

    if @CONDITIONSETTINGNAME = 'BankingSystem-SEPA'
    begin
        declare @COUNTRYCODELENGTH int = 2;
        declare @COUNTRYCODEANDCHECKDIGITSLENGTH int = 4;
        declare @MAXLENGTH int = 34;

        if len(@ACCOUNTNUMBER) <= @COUNTRYCODEANDCHECKDIGITSLENGTH or len(@ACCOUNTNUMBER) >= @MAXLENGTH
            --invalid length

            return 0;

        -- move first 4 characters to end per IBAN validation algorithms

        declare @IBAN nvarchar(50) = substring(@ACCOUNTNUMBER, @COUNTRYCODEANDCHECKDIGITSLENGTH + 1, len(@ACCOUNTNUMBER)) + substring(@ACCOUNTNUMBER, 1, @COUNTRYCODEANDCHECKDIGITSLENGTH);
        declare @INDEX int = 1;
        declare @NEWIBAN nvarchar(20) = '';
        declare @CHAR nvarchar(1);

        --replace letters with 2 numbers

        while @INDEX <= len(@IBAN)
        begin
            set @CHAR = substring(@IBAN, @INDEX, 1);
            if @CHAR like '[0-9]'
            begin
                set @NEWIBAN = @NEWIBAN + @CHAR;
            end
            else if @CHAR like '[a-z]' or @CHAR like '[A-Z]'
            begin
                set @NEWIBAN = @NEWIBAN + convert(nvarchar, ascii(upper(@CHAR))-55);
            end
            else
            begin
                --invalid character

                return 0;
            end
            if len(@NEWIBAN) > 16
            begin
                set @NEWIBAN = convert(nvarchar(20), convert(bigint, @NEWIBAN) % 97);
            end
            set @index = @index + 1;
        end

        if (convert(bigint, @NEWIBAN) % 97) != 1
            --invalid digits

            return 0;

        declare @COUNTRYCODE nvarchar(2) = substring(@ACCOUNTNUMBER, 1, @COUNTRYCODELENGTH);
        declare @IBANSTRUCTURE nvarchar(50) = '';

        select
            @IBANSTRUCTURE = substring(IBANREGISTRY.IBANSTRUCTURE, @COUNTRYCODELENGTH + 1, len(IBANREGISTRY.IBANSTRUCTURE))
        from
            dbo.IBANREGISTRY
        where
            IBANREGISTRY.COUNTRYISO3166 = @COUNTRYCODE;

        if @IBANSTRUCTURE = ''
            --invalid country code

            return 0;

        set @IBAN = substring(@ACCOUNTNUMBER, @COUNTRYCODELENGTH + 1, len(@ACCOUNTNUMBER));

        declare @CURRENTINDEXMAX int;
        declare @CURRENTTYPE nvarchar(1);

        --use IBAN structure in database to validate

        while len(@IBANSTRUCTURE) > 0
        begin
                if substring(@IBANSTRUCTURE, 2, 1) = '!'
                begin
                    set @CURRENTINDEXMAX = convert(int, substring(@IBANSTRUCTURE, 1, 1)) + 1;
                    set @CURRENTTYPE = substring(@IBANSTRUCTURE, 3, 1);
                    set @IBANSTRUCTURE = substring(@IBANSTRUCTURE, 4, len(@IBANSTRUCTURE));
                end
                else if substring(@IBANSTRUCTURE, 3, 1) = '!'
                begin
                    set @CURRENTINDEXMAX = convert(int, substring(@IBANSTRUCTURE, 1, 2)) + 1;
                    set @CURRENTTYPE = substring(@IBANSTRUCTURE, 4, 1);
                    set @IBANSTRUCTURE = substring(@IBANSTRUCTURE, 5, len(@IBANSTRUCTURE));
                end
                else
                begin
                    --invalid ibanstructure

                    return 0;
                end
          if @CURRENTTYPE = 'a'
            begin
                      while @INDEX < @CURRENTINDEXMAX
                      begin
                          if substring(@IBAN, @INDEX, 1) not like '[A-Z]'
                          begin
                              --iban doesn't match structure

                              return 0;
                          end
                          set @INDEX = @INDEX + 1;
                      end
                  end
                else if @CURRENTTYPE = 'n'
                begin
                    while @INDEX < @CURRENTINDEXMAX
                    begin
                        if substring(@IBAN, @INDEX, 1) not like '[0-9]'
                        begin
                            --iban doesn't match structure

                            return 0;
                        end
                        set @INDEX = @INDEX + 1;
                    end
                end
                else if @CURRENTTYPE = 'c'
                begin
                    while @INDEX < @CURRENTINDEXMAX
                    begin
                        if substring(@IBAN, @INDEX, 1) not like '[0-9]' and substring(@IBAN, @INDEX, 1) not like '[A-Z]'  and substring(@IBAN, @INDEX, 1) not like '[a-z]' 
                        begin
                            --iban doesn't match structure

                            return 0;
                        end
                        set @INDEX = @INDEX + 1;
                    end
                end
                else
                begin
                    --invalid ibanstructure

                    return 0;
                end
              set @IBAN = substring(@IBAN, @CURRENTINDEXMAX, len(@IBAN));
              set @INDEX = 1;
        end

        if LEN(@IBAN) > 0
            --iban doesn't match structure

            return 0;
    end

    return 1;

end