DNI functions

Hi everyone!

I want to share four functions with you. I hope that you can use it at some time.

DNI: the initials of the type of national identity document, is composed of different series of numbers and letters. That proves the identity and personal data of the holder, as well as the Spanish nationality. Example: 94494452X

NIE:  The NIE or foreigner identity number is a code for foreigners in Spain.


In this page you can generate examples of DNI or NIE https://generadordni.es/

The first function calculates the letter of  a DNI number.

/// Calculate letter of DNI
/// <br><b>pDni</b> format: con 8 numbers
ClassMethod GetLetterDni(pDni As %String) As %String
{
    set correspondence = $LISTBUILD("T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E")
    
    set letter = ""
    
    if (pDni '= "") & ($GET(pDni)?8N){
        set num = (pDni # 23)+1
        set letter = $LISTGET(correspondence,num)
    }
    
    quit letter
}

The second function calculates a  letter of NIE using the first function.

/// Calculate letter of NIE
/// <br><b>pNie</b> format: 1 letter, 7 numbers
ClassMethod GetLetterNie(pNie As %String) As %String
{
    set letter = ""
    //Get the first value
    set letter1 = $ZCONVERT($EXTRACT(pNie,1,1),"U")
    //Cogemos el resto del Nie para su posterior uso
    set num = $EXTRACT(pNie,2,8)
    
    if (pNie '= "") & ($GET(pNie)?1U7N){
        
        //If NIE starts with X, the X is replaced by the 0
        if (letter1 = "X") { set dni = 0_num }
        
        //If NIE starts with Y, the Y is replaced by the 1
        elseif(letter1 = "Y") { set dni = 1_num }
        
        //If NIE starts with Z, the Z is replaced by the 2
        elseif (letter1 = "Z"){ set dni = 2_num }
        
        //Calculates the letter
        set letter = ..GetLetterDni(dni)
    }
    
    quit letter
}

The third function validates a DNI using the first function.

/// <br><b>pDni</b> format: 8 numbers, 1 letter
/// <br><b>0</b> Dni OK
/// <br><b>-1</b> Dni error
ClassMethod ValidateDni(pDni As %String) As %Integer
{
    set response = -1
    
    if (pDni '= "") & ($GET(pDni)?8N1U){
        //Get the numbers
        set auxNum = $EXTRACT(pDni,1,8)
        
        //Get the letter
        set auxLetter = $EXTRACT(pDni,9,9)
        
        //Calculates letter of dni
        set calculatedLetter = ..GetLetterDni(auxNum)
        
        //If both letters are the same the DNI is valid
        if (auxLetter = calculatedLetter) { set response = 0 }        
    }
    
    quit response
}

The last function validates a NIE using the second function.

/// <br><b>pNie</b> NIE format: 1 letter, 7 numbers, 1 letter
/// <br><b>0</b> NIE OK
/// <br><b>-1</b> NIE error
ClassMethod ValidateNie(pNie As %String) As %Integer
{
    set response = -1
    
    if (pNie '= "") & ($GET(pNie)?1U7N1U){
        //Get the "numbers"
        set auxNum = $EXTRACT(pNie,1,8)
        
        //Get the first letter
        set auxLetter = $EXTRACT(pNie,9,9)
        
        set calculatedLetter = ..GetLetterNie(auxNum)
        
        //Si ambas letras son iguales el DNI es valido
        if (auxLetter = calculatedLetter) { set response = 0 }        
    }
    
    quit response
}

Any comments to improve will be welcome!!!

Regards  ;)

Comments

Pilar, could you please extend your post with a bit details about DNI, looks like it is used only in Spain.
And it would be better, to translate comments to English.

Hi,

I tried to explain a bit that is the DNI  updating the post. 

Thank you Pili !!

Yes, we only use DNI (our national identifier) in Spain but your method still being useful for a lot of DC users... I hope more and more :-D

I think that in GetLetter the condition should be if $get(pDni)?8n to validate that pDni contain 8 exactly 8 digits

And in ValidateDni the condition should be if $get(pDni)?8n1u to validate that pDni contains exactly 8 digits followd by an uppercase letter.

Also in ValidateDni instead of ##class(DKI.Common.Utils.Utilitades).GetLetter(auxNumber) you should do ..GetLetter(auxNumber) in this way when you put both methods in the same class the class name doesn't have to be DKI.Common.Utils.Utilitades

More about pattern matching can be found here:

https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY...

And about arithmetic&logic precedence:

http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?...

Thanks!!

Instead of using $LENGTH(pDni) '= 8  I can use  $GET(pDni)?8N

$GET(pDni)?8N in the GetLetter method where your input is 8 digits and the output is the corresponding letter.

In ValidateDni your input is 8 digits and one uppercase letter so there you should use $GET(pDni)?8N1U

So now the code will be something like this:

ClassMethod GetLetter(pDni As %String) As %String
{
    set correspondence = $LISTBUILD("T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E")
    
    set letter = ""
    
    if ($get(pDni)?8N){
        set number = (pDni # 23)+1
        set letter = $LISTGET(correspondence,number)
    }
    
    quit letter
}
/// <br><b>0</b> Dni OK
/// <br><b>-1</b> Dni error

ClassMethod ValidateDni(pDni As %String) As %Integer
{

    set response = -1
    
    if ($get(pDni)?8N1U){
        //Get the numbers of Dni
        set auxNumber = $EXTRACT(pDni,1,8)
        
        //Get the letter of Dni
        set auxLetter = $EXTRACT(pDni,9,9)
        
        //Calculate the letter of the dni
        set calculatedLetter = ..GetLetter(auxNumber)
        
        if (auxLetter = calculatedLetter){
            set response = 0
        }        
    }
    
    quit response
}