Skip to content

Instantly share code, notes, and snippets.

@sergio-toro
Forked from afgomez/validate_spanish_id.js
Last active January 16, 2023 16:12
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save sergio-toro/9929129 to your computer and use it in GitHub Desktop.
Save sergio-toro/9929129 to your computer and use it in GitHub Desktop.
AngularJS service to validate spanish document id DNI / NIE / NIF
/**
* AngularJS service to validate spanish document id.
* Returns the type of document and checks its validity.
*
* Usage:
* angular
* .module('myApp', [ 'validate-spanish-id' ])
* .controller('myController', function(ValidateSpanishID){
* ValidateSpanishID.validate( str );
* })
*
*
* > ValidateSpanishID.validate( '12345678Z' );
* // { type: 'dni', valid: true }
*
* > ValidateSpanishID.validate( 'B83375575' );
* // { type: 'cif', valid: false }
*
* The algorithm is adapted from other solutions found at:
* - https://gist.github.com/afgomez/5691823
* - http://www.compartecodigo.com/javascript/validar-nif-cif-nie-segun-ley-vigente-31.html
* - http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
*/
(function() {
'use strict';
angular
.module('validate-spanish-id')
.service('ValidateSpanishID', [ function() {
this.DNI_REGEX = /^(\d{8})([A-Z])$/;
this.CIF_REGEX = /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/;
this.NIE_REGEX = /^[XYZ]\d{7,8}[A-Z]$/;
this.validate = function( str ) {
// If no valid value passed
if (!str) {
str = '';
}
// Ensure upcase and remove whitespace
str = str.toUpperCase().replace(/\s/, '');
var valid = false;
var type = this.idType( str );
switch (type) {
case 'dni':
valid = this.validateDNI( str );
break;
case 'nie':
valid = this.validateNIE( str );
break;
case 'cif':
valid = this.validateCIF( str );
break;
}
return {
type: type,
valid: valid
};
};
this.idType = function( str ) {
if ( str.match( this.DNI_REGEX ) ) {
return 'dni';
}
else if ( str.match( this.CIF_REGEX ) ) {
return 'cif';
}
else if ( str.match( this.NIE_REGEX ) ) {
return 'nie';
}
else {
return '';
}
};
this.validateDNI = function( dni ) {
var dni_letters = "TRWAGMYFPDXBNJZSQVHLCKE";
var letter = dni_letters.charAt( parseInt( dni, 10 ) % 23 );
return letter == dni.charAt(8);
};
this.validateNIE = function( nie ) {
// Change the initial letter for the corresponding number and validate as DNI
var nie_prefix = nie.charAt( 0 );
switch (nie_prefix) {
case 'X':
nie_prefix = 0;
break;
case 'Y':
nie_prefix = 1;
break;
case 'Z':
nie_prefix = 2;
break;
}
return this.validateDNI( nie_prefix + nie.substr(1) );
};
this.validateCIF = function( cif ) {
var match = cif.match( this.CIF_REGEX );
var letter = match[1],
number = match[2],
control = match[3];
var even_sum = 0;
var odd_sum = 0;
var n;
for ( var i = 0; i < number.length; i++) {
n = parseInt( number[i], 10 );
// Odd positions (Even index equals to odd position. i=0 equals first position)
if ( i % 2 === 0 ) {
// Odd positions are multiplied first.
n *= 2;
// If the multiplication is bigger than 10 we need to adjust
odd_sum += n < 10 ? n : n - 9;
// Even positions
// Just sum them
} else {
even_sum += n;
}
}
var control_digit = (10 - (even_sum + odd_sum).toString().substr(-1) );
var control_letter = 'JABCDEFGHI'.substr( control_digit, 1 );
// Control must be a digit
if ( letter.match( /[ABEH]/ ) ) {
return control == control_digit;
// Control must be a letter
} else if ( letter.match( /[KPQS]/ ) ) {
return control == control_letter;
// Can be either
} else {
return control == control_digit || control == control_letter;
}
};
}])
;
})();
@SilverSeva
Copy link

Hi, thank you for sharing the code.

But there is some errors in it:

  1. "(even_sum + odd_sum).toString().substr(-1);" if this is 0 this just fails: 'JABCDEFGHI'.substr( control_digit, 1 );
  2. Try this valid CIF: Q58584673

Regards,
Alex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment