#### Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Options

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

Member Posts: 9
edited 2024-03-25
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);
```