module.exports = function(tin, country) { if (tin == null || country == null) return true; if (typeof tin != 'string' || typeof country != 'string') return false; tin = tin.toUpperCase(); country = country.toLowerCase(); let len = tin.length; let validators = { es: { regExp: /^[A-Z0-9]\d{7}[A-Z0-9]$/, validate: () => { let isCif = /[A-W]/.test(tin.charAt(0)); let lastDigit = tin.charAt(len - 1); let computedDigit; if (isCif) { let numbers = tin.substring(1, 8) .split('') .map(x => parseInt(x)); let pairSum = numbers .filter((_, i) => i % 2 != 0) .reduce((a, x) => a + x); let oddSum = numbers .filter((_, i) => i % 2 == 0) .map(x => x * 2) .join('') .split('') .map(x => parseInt(x)) .reduce((a, x) => a + x); let sum = (pairSum + oddSum).toString(); let units = parseInt(sum.charAt(sum.length - 1)); let control = units == 0 ? 0 : 10 - units; let isLetter = /^[A-Z]$/.test(lastDigit); computedDigit = isLetter ? 'JABCDEFGHI'.charAt(control) : control.toString(); } else { // Foreign NIF let index = 'XYZ'.indexOf(tin.charAt(0)); let nif = index == -1 ? tin : index.toString() + tin.substring(1); let rest = parseInt(nif.substring(0, 8)) % 23; computedDigit = 'TRWAGMYFPDXBNJZSQVHLCKE'.charAt(rest); } return computedDigit == lastDigit; } }, it: { regExp: /^(\d{11}|[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z])$/ }, pt: { regExp: /^\d{9}$/ } }; let validator = validators[country]; if (!validator) return true; return validator.regExp.test(tin) && (!validator.validate || validator.validate()); };