Options

Luhn Algorithm (Modulus 10) in Dynamics NAV C/AL & Business Central code - Creating a check Digit

Ephraim_07Ephraim_07 Member Posts: 9
Hello people,

So a client required Luhn algorithm (also known as modulus 10 or mod 10) to be used on their database to create a check digit for a given number and a valid OCR reference for payments. I saw some solutions on this website that did not work so I decided to post a good solution below:

For Luhn algorithm, you need a Payload (the original number) to generate a check digit. The check digit will be added to the code to make a valid number.

To read More on the Luhn Algorithm, see here >> https://simplycalc.com/luhn-calculate.php

1. Create a Codeunit with the following data types in your C/AL Locals:

Name DataType Subtype Length
i Integer
LengthOfDigit Integer
Digits Code 250
Product BigInteger
SumProduct BigInteger
CurrentNumber BigInteger
CurrentStringPosition BigInteger
ReversePosition BigInteger

And the following Parameters:

Var Name DataType Subtype Length
No OrigNumber BigInteger

2. View the code below:

LOCAL GenerateCheckDigit(OrigNumber : Code[249]) CheckDigitNumber : Code[1]      

IF COPYSTR(OrigNumber,1,1) = '-' THEN
  ERROR('The number to evaluate must be a positive number. Number provided is %1',OrigNumber);
 
LengthOfDigit := STRLEN(OrigNumber);                     //Get the length of the string because this will allow to define how long the loop below will be.

FOR i := LengthOfDigit DOWNTO 1 DO BEGIN
  CLEAR(ReversePosition); CLEAR(Product);
  ReversePosition := (LengthOfDigit + 1) - i;              //this will get the REVERSE position of the digit because Luhn Algorithm starts from right to left.
                                                                             // This means the last digit in the number is processed first.

  Digits[i] := COPYSTR(OrigNumber,ReversePosition,1);           // Get the individual digit in that position with an array. The digit must be converted to a Code variable because only Text and Code variable can be seperated into their individual parts in NAV.
                                                                                              // e.g.  231123 = [2,3,1,1,2,3]

  CheckLettersInNumber(Digits[i]);

 
  //Check if the *Position* of the digit is an odd number. All odd numbers will always be [ i MOD 2 = 1 ]
  // If Odd position, then multiply by 2, else multiply by 1. This is how the Algorithm works
  //--------------------------------------------------------------
  IF i MOD 2 <> 0 THEN BEGIN                                
    EVALUATE(Product,Digits[i]);                 //Convert the code back to integer/number for multiplication
    Product :=  Product * 2;
  END ELSE BEGIN
    EVALUATE(Product,Digits[i]);
    Product := Product * 1;
  END;

  //-----If the product computed above is greater than 9, get the sum of the individual digits (digit sum) e.g. 12 will be 1 + 2 = 3
  CASE Product OF
    10:
      Product := 1 + 0;
    11:
      Product := 1 + 1;
    12:
      Product := 1 + 2;
    13:
      Product := 1 + 3;
    14:
      Product := 1 + 4;
    15:
      Product := 1 + 5;
    16:
      Product := 1 + 6;
    17:
      Product := 1 + 7;
    18:
      Product := 1 + 8;
    19:
      Product := 1 + 9;
   END;

   SumProduct := SumProduct + Product;

//Get the Modulus of the sum of figures
  IF SumProduct MOD 10 <> 0 THEN
    CheckDigitNumber := FORMAT(10 - (SumProduct MOD 10))
  ELSE
    CheckDigitNumber := FORMAT(0);             //If SumProduct MOD 10 is =10 then answer should be 0 and NOT = 10- 0

END;

  MESSAGE('the Check digit is %1',CheckDigitNumber);
EXIT(CheckDigitNumber);                        //Return the result as an Integer. 

3. After you have generated the code I recommend you convert it to text/Code so that you can combine it into a new number that is OCR compliant, e.g.
NewNumber := NumberToValidate + '' + FORMAT(CheckDigit);
MESSAGE('The new number is %1',NewNumber);

Comments

Sign In or Register to comment.