Comparing version 0.6.1 to 0.9.0
{ | ||
"name": "jsvat", | ||
"version": "0.6.1", | ||
"version": "0.9.0", | ||
"description": "Check the validity of the format of an EU VAT number", | ||
@@ -17,4 +17,7 @@ "main": "./dist/jsvat.js", | ||
}, | ||
"ignore": { | ||
}, | ||
"ignore": [ | ||
".bithoundrc", | ||
".log", | ||
".travis.yml" | ||
], | ||
"keywords": [ | ||
@@ -21,0 +24,0 @@ "jsvat", |
1735
dist/jsvat.js
@@ -1,176 +0,7 @@ | ||
var jsvat = (function () { | ||
var jsvat = (function() { | ||
'use strict'; | ||
var CONDITIONS = { | ||
austria: { | ||
multipliers: [1, 2, 1, 2, 1, 2, 1], | ||
regex: /^(AT)U(\d{8})$/ | ||
}, | ||
belgium: { | ||
regex: /^(BE)(0?\d{9})$/ | ||
}, | ||
bulgaria: { | ||
multipliers: { | ||
physical: [2, 4, 8, 5, 10, 9, 7, 3, 6], | ||
foreigner: [21, 19, 17, 13, 11, 9, 7, 3, 1], | ||
miscellaneous: [4, 3, 2, 7, 6, 5, 4, 3, 2] | ||
}, | ||
regex: /^(BG)(\d{9,10})$/ | ||
}, | ||
switzerland: { | ||
multipliers: [5, 4, 3, 2, 7, 6, 5, 4], | ||
regex: /^(CHE)(\d{9})(MWST)?$/ | ||
}, | ||
cyprus: { | ||
regex: /^(CY)([0-59]\d{7}[A-Z])$/ | ||
}, | ||
czech_republic: { | ||
multipliers: [8, 7, 6, 5, 4, 3, 2], | ||
lookup: [8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10], | ||
regex: /^(CZ)(\d{8,10})(\d{3})?$/, | ||
additional: [ | ||
/^\d{8}$/, | ||
/^[0-5][0-9][0|1|5|6]\d[0-3]\d\d{3}$/, | ||
/^6\d{8}$/, | ||
/^\d{2}[0-3|5-8]\d[0-3]\d\d{4}$/ | ||
] | ||
}, | ||
germany: { | ||
regex: /^(DE)([1-9]\d{8})$/ | ||
}, | ||
denmark: { | ||
multipliers: [2, 7, 6, 5, 4, 3, 2, 1], | ||
regex: /^(DK)(\d{8})$/ | ||
}, | ||
estonia: { | ||
multipliers: [3, 7, 1, 3, 7, 1, 3, 7], | ||
regex: /^(EE)(10\d{7})$/ | ||
}, | ||
greece: { | ||
multipliers: [256, 128, 64, 32, 16, 8, 4, 2], | ||
regex: /^(EL)(\d{9})$/ | ||
}, | ||
spain: { | ||
multipliers: [2, 1, 2, 1, 2, 1, 2], | ||
regex: [ | ||
/^(ES)([A-Z]\d{8})$/, | ||
/^(ES)([A-HN-SW]\d{7}[A-J])$/, | ||
/^(ES)([0-9YZ]\d{7}[A-Z])$/, | ||
/^(ES)([KLMX]\d{7}[A-Z])$/ | ||
], | ||
additional: [ | ||
/^[A-H|J|U|V]\d{8}$/, | ||
/^[A-H|N-S|W]\d{7}[A-J]$/, | ||
/^[0-9|Y|Z]\d{7}[A-Z]$/, | ||
/^[K|L|M|X]\d{7}[A-Z]$/ | ||
] | ||
}, | ||
europe: { | ||
regex: /^(EU)(\d{9})$/ | ||
}, | ||
finland: { | ||
multipliers: [7, 9, 10, 5, 8, 4, 2], | ||
regex: /^(FI)(\d{8})$/ | ||
}, | ||
france: { | ||
regex: [ | ||
/^(FR)(\d{11})$/, | ||
/^(FR)([A-HJ-NP-Z]\d{10})$/, | ||
/^(FR)(\d[A-HJ-NP-Z]\d{9})$/, | ||
/^(FR)([A-HJ-NP-Z]{2}\d{9})$/ | ||
] | ||
var COUNTRIES = {}; | ||
}, | ||
united_kingdom: { | ||
multipliers: [8, 7, 6, 5, 4, 3, 2], | ||
regex: [ | ||
/^(GB)?(\d{9})$/, | ||
/^(GB)?(\d{12})$/, | ||
/^(GB)?(GD\d{3})$/, | ||
/^(GB)?(HA\d{3})$/ | ||
] | ||
}, | ||
croatia: { | ||
regex: /^(HR)(\d{11})$/ | ||
}, | ||
hungary: { | ||
multipliers: [9, 7, 3, 1, 9, 7, 3], | ||
regex: /^(HU)(\d{8})$/ | ||
}, | ||
ireland: { | ||
multipliers: [8, 7, 6, 5, 4, 3, 2], | ||
regex: [ | ||
/^(IE)(\d{7}[A-W])$/, | ||
/^(IE)([7-9][A-Z\*\+)]\d{5}[A-W])$/, | ||
/^(IE)(\d{7}[A-W][AH])$/ | ||
] | ||
}, | ||
italy: { | ||
multipliers: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2], | ||
regex: /^(IT)(\d{11})$/ | ||
}, | ||
latvia: { | ||
multipliers: [9, 1, 4, 8, 3, 10, 2, 5, 7, 6], | ||
regex: /^(LV)(\d{11})$/ | ||
}, | ||
lithunia: { | ||
multipliers: { | ||
short: [3, 4, 5, 6, 7, 8, 9, 1], | ||
med: [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2], | ||
alt: [3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] | ||
}, | ||
regex: /^(LT)(\d{9}|\d{12})$/ | ||
}, | ||
luxembourg: { | ||
regex: /^(LU)(\d{8})$/ | ||
}, | ||
malta: { | ||
multipliers: [3, 4, 6, 7, 8, 9], | ||
regex: /^(MT)([1-9]\d{7})$/ | ||
}, | ||
netherlands: { | ||
multipliers: [9, 8, 7, 6, 5, 4, 3, 2], | ||
regex: /^(NL)(\d{9})B\d{2}$/ | ||
}, | ||
norway: { | ||
multipliers: [3, 2, 7, 6, 5, 4, 3, 2], | ||
regex: /^(NO)(\d{9})$/ | ||
}, | ||
poland: { | ||
multipliers: [6, 5, 7, 2, 3, 4, 5, 6, 7], | ||
regex: /^(PL)(\d{10})$/ | ||
}, | ||
portugal: { | ||
multipliers: [9, 8, 7, 6, 5, 4, 3, 2], | ||
regex: /^(PT)(\d{9})$/ | ||
}, | ||
romania: { | ||
multipliers: [7, 5, 3, 2, 1, 7, 5, 3, 2], | ||
regex: /^(RO)([1-9]\d{1,9})$/ | ||
}, | ||
russia: { | ||
multipliers: { | ||
m_1: [2, 4, 10, 3, 5, 9, 4, 6, 8, 0], | ||
m_2: [7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0], | ||
m_3: [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0] | ||
}, | ||
regex: /^(RU)(\d{10}|\d{12})$/ | ||
}, | ||
serbia: { | ||
regex: /^(RS)(\d{9})$/ | ||
}, | ||
slovenia: { | ||
multipliers: [8, 7, 6, 5, 4, 3, 2], | ||
regex: /^(SI)([1-9]\d{7})$/ | ||
}, | ||
slovakia_republic: { | ||
regex: /^(SK)([1-9]\d[2346-9]\d{7})$/ | ||
}, | ||
sweden: { | ||
regex: /^(SE)(\d{10}01)$/ | ||
} | ||
}; | ||
function _validateRegex(vat, regex) { | ||
@@ -182,8 +13,5 @@ return regex.test(vat); | ||
var parsedNum = regex.exec(vat); | ||
var vatNum = parsedNum[2]; | ||
//var code = parsedNum[1]; | ||
var number = parsedNum[2]; | ||
//if (!code || code.length === 0) code = 'GB'; | ||
return _checks[countryName](number, countryName); | ||
return COUNTRIES[countryName].calcs(vatNum); | ||
} | ||
@@ -199,34 +27,83 @@ | ||
function getClearVAT(vat) { | ||
return vat.toString().toUpperCase().replace(/(\s|-|\.)+/g, ''); | ||
} | ||
function _makeArr(regex) { | ||
//TODO (S.Panfilov) this is not cross-browser check | ||
if (!Array.isArray(regex)) { | ||
return [regex]; | ||
} | ||
return regex; | ||
} | ||
function isCountryBlocked(config, countryName) { | ||
if (!config || Object.keys(config).length === 0) return false; //TODO (S.Panfilov) Object.keys didn't supports by old browsers | ||
var country = config[countryName]; | ||
return (country === null || country === undefined) ? true : !country; | ||
} | ||
var exports = { | ||
checkVAT: function (vat) { | ||
config: {}, | ||
checkVAT: function(vat, isDetailed) { | ||
if (!vat) return false; | ||
vat = vat.toString().toUpperCase().replace(/(\s|-|\.)+/g, ''); | ||
for (var countryName in CONDITIONS) { | ||
if (CONDITIONS.hasOwnProperty(countryName)) { | ||
var regex = CONDITIONS[countryName].regex; | ||
vat = getClearVAT(vat); | ||
//TODO (S.Panfilov) this is not cross-browser check | ||
if (Array.isArray(regex)) { | ||
for (var i = 0; i < regex.length; i++) { | ||
if (_validate(vat, regex[i], countryName)) return true; | ||
var result = { | ||
isValid: false, | ||
countries: [] | ||
}; | ||
for (var countryName in COUNTRIES) { | ||
if (COUNTRIES.hasOwnProperty(countryName)) { | ||
//Make sure country check not skipped in config | ||
if (!isCountryBlocked(exports.config, countryName)) { | ||
var regexArr = _makeArr(COUNTRIES[countryName].rules.regex); | ||
for (var i = 0; i < regexArr.length; i++) { | ||
//If once become a true, shouldn't be a false any more | ||
result.isValid = (_validate(vat, regexArr[i], countryName)) ? true : result.isValid; | ||
if (!isDetailed && result.isValid) return result.isValid; | ||
var isValidForCurrCountry = _validate(vat, regexArr[i], countryName); | ||
if (isValidForCurrCountry) { | ||
result.countries.push(countryName); | ||
} | ||
// if (result.isValid) { | ||
// //If not detailed just return bool and exit | ||
// if (!isDetailed) { | ||
// return result.isValid | ||
// } | ||
// else { | ||
// //if detailed, should fill array of countries | ||
// result.push(countryName); | ||
// } | ||
} | ||
} else { | ||
if (_validate(vat, regex, countryName)) return true; | ||
} | ||
} | ||
} | ||
return false; | ||
return isDetailed ? result : result.isValid; | ||
} | ||
}; | ||
COUNTRIES.austria = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var temp; | ||
var expect; | ||
var expect; | ||
var temp; | ||
var _checks = { | ||
austria: function (vat, countryName) { | ||
var total = 0; | ||
for (var i = 0; i < 7; i++) { | ||
temp = vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
temp = vat.charAt(i) * this.rules.multipliers[i]; | ||
if (temp > 9) | ||
@@ -245,3 +122,19 @@ total += Math.floor(temp / 10) + temp % 10; | ||
}, | ||
belgium: function (vat) { | ||
rules: { | ||
multipliers: [ | ||
1, | ||
2, | ||
1, | ||
2, | ||
1, | ||
2, | ||
1 | ||
], | ||
regex: /^(AT)U(\d{8})$/ | ||
} | ||
}; | ||
COUNTRIES.belgium = { | ||
calcs: function(vat) { | ||
var expect; | ||
if (vat.length === 9) { | ||
@@ -257,96 +150,78 @@ vat = '0' + vat; | ||
}, | ||
bulgaria: function (vat, countryName) { | ||
var checkNineLengthVat = function () { | ||
var total =0; | ||
temp = 0; | ||
for (var i = 0; i < 8; i++) { | ||
temp += +vat.charAt(i) * (i + 1); | ||
} | ||
rules: { | ||
regex: /^(BE)(0?\d{9})$/ | ||
} | ||
}; | ||
COUNTRIES.bulgaria = (function() { | ||
total = temp % 11; | ||
if (total !== 10) { | ||
expect = +vat.slice(8); | ||
return total === expect; | ||
} | ||
function _checkNineLengthVat(vat) { | ||
var total; | ||
var temp = 0; | ||
var expect; | ||
temp = 0; | ||
for (var j = 0; j < 8; j++) { | ||
temp += +vat.charAt(j) * (j + 3); | ||
} | ||
for (var i = 0; i < 8; i++) { | ||
temp += +vat.charAt(i) * (i + 1); | ||
} | ||
total = temp % 11; | ||
if (total === 10) total = 0; | ||
total = temp % 11; | ||
if (total !== 10) { | ||
expect = +vat.slice(8); | ||
return total === expect; | ||
}; | ||
} | ||
var isPhysicalPerson = function () { | ||
var total = 0; | ||
// 10 digit VAT code - see if it relates to a standard physical person | ||
if ((/^\d\d[0-5]\d[0-3]\d\d{4}$/).test(vat)) { | ||
// Check month | ||
var month = +vat.slice(2, 4); | ||
if ((month > 0 && month < 13) || (month > 20 && month < 33) || (month > 40 && month < 53)) { | ||
temp = 0; | ||
for (var j = 0; j < 8; j++) { | ||
temp += +vat.charAt(j) * (j + 3); | ||
} | ||
total = 0; | ||
for (var k = 0; k < 9; k++) { | ||
total += +vat.charAt(k) * CONDITIONS[countryName].multipliers.physical[k]; | ||
} | ||
// Establish check digit. | ||
total = total % 11; | ||
if (total === 10) total = 0; | ||
total = temp % 11; | ||
if (total === 10) total = 0; | ||
expect = +vat.slice(8); | ||
// Check to see if the check digit given is correct, If not, try next type of person | ||
if (total === +vat.substr(9, 1)) return true; | ||
} | ||
} | ||
return total === expect; | ||
} | ||
return false; | ||
function _isPhysicalPerson(vat, rules) { | ||
var total = 0; | ||
// 10 digit VAT code - see if it relates to a standard physical person | ||
if ((/^\d\d[0-5]\d[0-3]\d\d{4}$/).test(vat)) { | ||
// Check month | ||
var month = +vat.slice(2, 4); | ||
if ((month > 0 && month < 13) || (month > 20 && month < 33) || (month > 40 && month < 53)) { | ||
}; | ||
total = 0; | ||
for (var i = 0; i < 9; i++) { | ||
total += +vat.charAt(i) * rules.multipliers.physical[i]; | ||
} | ||
// Establish check digit. | ||
total = total % 11; | ||
if (total === 10) total = 0; | ||
// It doesn't relate to a standard physical person - see if it relates to a foreigner. | ||
var isForeigner = function () { | ||
var total = 0; | ||
// Extract the next digit and multiply by the counter. | ||
for (var l = 0; l < 9; l++) { | ||
total += +vat.charAt(l) * CONDITIONS[countryName].multipliers.foreigner[l]; | ||
// Check to see if the check digit given is correct, If not, try next type of person | ||
if (total === +vat.substr(9, 1)) return true; | ||
} | ||
} | ||
// Check to see if the check digit given is correct, If not, try next type of person | ||
if (total % 10 === +vat.substr(9, 1)) { | ||
return true; | ||
} | ||
}; | ||
return false; | ||
} | ||
var miscellaneousVAT = function () { | ||
var total = 0; | ||
// Finally, if not yet identified, see if it conforms to a miscellaneous VAT number | ||
function _isForeigner(vat, rules) { | ||
var total = 0; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 9; i++) { | ||
total += +vat.charAt(i) * rules.multipliers.foreigner[i]; | ||
} | ||
for (var m = 0; m < 9; m++) { | ||
total += +vat.charAt(m) * CONDITIONS[countryName].multipliers.miscellaneous[m]; | ||
} | ||
// Establish check digit. | ||
total = 11 - total % 11; | ||
if (total === 10) return false; | ||
if (total === 11) total = 0; | ||
// Check to see if the check digit given is correct, If not, we have an error with the VAT number | ||
expect = +vat.substr(9, 1); | ||
return total === expect; | ||
}; | ||
if (vat.length === 9) { | ||
return checkNineLengthVat(); | ||
} else { | ||
return isPhysicalPerson() || isForeigner() || miscellaneousVAT(); | ||
// Check to see if the check digit given is correct, If not, try next type of person | ||
if (total % 10 === +vat.substr(9, 1)) { | ||
return true; | ||
} | ||
} | ||
}, | ||
switzerland: function (vat, countryName) { | ||
function _miscellaneousVAT(vat, rules) { | ||
var total = 0; | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
// Finally, if not yet identified, see if it conforms to a miscellaneous VAT number | ||
for (var i = 0; i < 9; i++) { | ||
total += +vat.charAt(i) * rules.multipliers.miscellaneous[i]; | ||
} | ||
@@ -360,7 +235,88 @@ | ||
// Check to see if the check digit given is correct, If not, we have an error with the VAT number | ||
expect = +vat.substr(8, 1); | ||
var expect = +vat.substr(9, 1); | ||
return total === expect; | ||
} | ||
return { | ||
calcs: function(vat) { | ||
if (vat.length === 9) { | ||
return _checkNineLengthVat(vat); | ||
} else { | ||
return _isPhysicalPerson(vat, this.rules) || _isForeigner(vat, this.rules) || _miscellaneousVAT(vat, this.rules); | ||
} | ||
}, | ||
rules: { | ||
multipliers: { | ||
physical: [ | ||
2, | ||
4, | ||
8, | ||
5, | ||
10, | ||
9, | ||
7, | ||
3, | ||
6 | ||
], | ||
foreigner: [ | ||
21, | ||
19, | ||
17, | ||
13, | ||
11, | ||
9, | ||
7, | ||
3, | ||
1 | ||
], | ||
miscellaneous: [ | ||
4, | ||
3, | ||
2, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
] | ||
}, | ||
regex: /^(BG)(\d{9,10})$/ | ||
} | ||
}; | ||
})(); | ||
COUNTRIES.croatia = { | ||
calcs: function(vat) { | ||
var expect; | ||
// Checks the check digits of a Croatian VAT number using ISO 7064, MOD 11-10 for check digit. | ||
var product = 10; | ||
var sum = 0; | ||
for (var i = 0; i < 10; i++) { | ||
// Extract the next digit and implement the algorithm | ||
sum = (+vat.charAt(i) + product) % 10; | ||
if (sum === 0) { | ||
sum = 10; | ||
} | ||
product = (2 * sum) % 11; | ||
} | ||
// Now check that we have the right check digit | ||
expect = +vat.slice(10, 11); | ||
return (product + expect) % 10 === 1; | ||
}, | ||
cyprus: function (vat) { | ||
rules: { | ||
regex: /^(HR)(\d{11})$/ | ||
} | ||
}; | ||
COUNTRIES.cyprus = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Not allowed to start with '12' | ||
@@ -405,11 +361,15 @@ if (+vat.slice(0, 2) === 12) return false; | ||
}, | ||
czech_republic: function (vat, countryName) { | ||
rules: { | ||
regex: /^(CY)([0-59]\d{7}[A-Z])$/ | ||
} | ||
}; | ||
COUNTRIES.czech_republic = (function() { | ||
function _isLegalEntities(vat, rules) { | ||
var total = 0; | ||
// Legal entities | ||
if (CONDITIONS[countryName].additional[0].test(vat)) { | ||
if (rules.additional[0].test(vat)) { | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 7; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * rules.multipliers[i]; | ||
} | ||
@@ -423,12 +383,17 @@ | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(7, 8); | ||
var expect = +vat.slice(7, 8); | ||
return total === expect; | ||
} | ||
// Individuals type 2 | ||
else if (CONDITIONS[countryName].additional[2].test(vat)) { | ||
return false; | ||
} | ||
function _isIndividualType2(vat, rules) { | ||
var total = 0; | ||
if (rules.additional[2].test(vat)) { | ||
// Extract the next digit and multiply by the counter. | ||
for (var j = 0; j < 7; j++) { | ||
total += +vat.charAt(j + 1) * CONDITIONS[countryName].multipliers[j]; | ||
total += +vat.charAt(j + 1) * rules.multipliers[j]; | ||
} | ||
@@ -442,50 +407,67 @@ | ||
// Convert calculated check digit according to a lookup table; | ||
expect = +vat.slice(8, 9); | ||
return CONDITIONS[countryName].lookup[total - 1] === expect; | ||
var expect = +vat.slice(8, 9); | ||
return rules.lookup[total - 1] === expect; | ||
} | ||
// Individuals type 3 | ||
else if (CONDITIONS[countryName].additional[3].test(vat)) { | ||
return false; | ||
} | ||
function _isIndividualType3(vat, rules) { | ||
if (rules.additional[3].test(vat)) { | ||
var temp = +vat.slice(0, 2) + vat.slice(2, 4) + vat.slice(4, 6) + vat.slice(6, 8) + vat.slice(8); | ||
expect = +vat % 11 === 0; | ||
var expect = +vat % 11 === 0; | ||
return !!(temp % 11 === 0 && expect); | ||
} | ||
// else error | ||
return false; | ||
}, | ||
germany: function (vat) { | ||
} | ||
return { | ||
calcs: function(vat) { | ||
// Checks the check digits of a German VAT number. | ||
if (_isLegalEntities(vat, this.rules)) return true; | ||
if (_isIndividualType2(vat, this.rules)) return true; | ||
if (_isIndividualType3(vat, this.rules)) return true; | ||
var product = 10; | ||
var sum = 0; | ||
var checkDigit = 0; | ||
for (var i = 0; i < 8; i++) { | ||
// Extract the next digit and implement peculiar algorithm!. | ||
sum = (+vat.charAt(i) + product) % 10; | ||
if (sum === 0) { | ||
sum = 10; | ||
} | ||
product = (2 * sum) % 11; | ||
return false; | ||
}, | ||
rules: { | ||
multipliers: [ | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
"lookup": [ | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2, | ||
1, | ||
0, | ||
9, | ||
10 | ||
], | ||
regex: /^(CZ)(\d{8,10})(\d{3})?$/, | ||
additional: [ | ||
/^\d{8}$/, | ||
/^[0-5][0-9][0|1|5|6]\d[0-3]\d\d{3}$/, | ||
/^6\d{8}$/, | ||
/^\d{2}[0-3|5-8]\d[0-3]\d\d{4}$/ | ||
] | ||
} | ||
} | ||
})(); | ||
COUNTRIES.denmark = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
// Establish check digit. | ||
if (11 - product === 10) { | ||
checkDigit = 0; | ||
} else { | ||
checkDigit = 11 - product; | ||
} | ||
// Compare it with the last two characters of the VAT number. If the same, then it is a valid | ||
// check digit. | ||
expect = +vat.slice(8, 9); | ||
return checkDigit === expect; | ||
}, | ||
denmark: function (vat, countryName) { | ||
var total = 0; | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -495,7 +477,24 @@ | ||
}, | ||
estonia: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
2, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2, | ||
1 | ||
], | ||
regex: /^(DK)(\d{8})$/ | ||
} | ||
}; | ||
COUNTRIES.estonia = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -511,90 +510,18 @@ | ||
}, | ||
greece: function (vat, countryName) { | ||
var total = 0; | ||
//eight character numbers should be prefixed with an 0. | ||
if (vat.length === 8) { | ||
vat = '0' + vat; | ||
} | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
} | ||
// Establish check digit. | ||
total = total % 11; | ||
if (total > 9) { | ||
total = 0; | ||
} | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(8, 9); | ||
return total === expect; | ||
}, | ||
spain: function (vat, countryName) { | ||
var i = 0; | ||
var total = 0; | ||
// National juridical entities | ||
if (CONDITIONS[countryName].additional[0].test(vat)) { | ||
// Extract the next digit and multiply by the counter. | ||
for (i = 0; i < 7; i++) { | ||
temp = vat.charAt(i + 1) * CONDITIONS[countryName].multipliers[i]; | ||
if (temp > 9) | ||
total += Math.floor(temp / 10) + temp % 10; | ||
else | ||
total += temp; | ||
} | ||
// Now calculate the check digit itself. | ||
total = 10 - total % 10; | ||
if (total === 10) { | ||
total = 0; | ||
} | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(8, 9); | ||
return total === expect; | ||
} | ||
// Juridical entities other than national ones | ||
else if (CONDITIONS[countryName].additional[1].test(vat)) { | ||
// Extract the next digit and multiply by the counter. | ||
for (i = 0; i < 7; i++) { | ||
temp = vat.charAt(i + 1) * CONDITIONS[countryName].multipliers[i]; | ||
if (temp > 9) | ||
total += Math.floor(temp / 10) + temp % 10; | ||
else | ||
total += temp; | ||
} | ||
// Now calculate the check digit itself. | ||
total = 10 - total % 10; | ||
total = String.fromCharCode(total + 64); | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = vat.slice(8, 9); | ||
return total === expect; | ||
} | ||
// Personal number (NIF) (starting with numeric of Y or Z) | ||
else if (CONDITIONS[countryName].additional[2].test(vat)) { | ||
var tempnumber = vat; | ||
if (tempnumber.substring(0, 1) === 'Y') tempnumber = tempnumber.replace(/Y/, '1'); | ||
if (tempnumber.substring(0, 1) === 'Z') tempnumber = tempnumber.replace(/Z/, '2'); | ||
expect = 'TRWAGMYFPDXBNJZSQVHLCKE'.charAt(+tempnumber.substring(0, 8) % 23); | ||
return tempnumber.charAt(8) === expect; | ||
} | ||
// Personal number (NIF) (starting with K, L, M, or X) | ||
else if (CONDITIONS[countryName].additional[3].test(vat)) { | ||
expect = 'TRWAGMYFPDXBNJZSQVHLCKE'.charAt(+vat.substring(1, 8) % 23); | ||
return vat.charAt(8) === expect; | ||
} | ||
else return false; | ||
}, | ||
europe: function () { | ||
//TODO (S.Panfilov) wtf? | ||
rules: { | ||
multipliers: [ | ||
3, | ||
7, | ||
1, | ||
3, | ||
7, | ||
1, | ||
3, | ||
7 | ||
], | ||
regex: /^(EE)(10\d{7})$/ | ||
} | ||
}; | ||
COUNTRIES.europe = { | ||
calcs: function(vat) { | ||
// We know little about EU numbers apart from the fact that the first 3 digits represent the | ||
@@ -604,6 +531,13 @@ // country, and that there are nine digits in total. | ||
}, | ||
finland: function (vat, countryName) { | ||
rules: { | ||
regex: /^(EU)(\d{9})$/ | ||
} | ||
}; | ||
COUNTRIES.finland = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 7; i++) total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
for (var i = 0; i < 7; i++) total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
@@ -620,4 +554,20 @@ // Establish check digit. | ||
}, | ||
france: function (vat) { | ||
rules: { | ||
multipliers: [ | ||
7, | ||
9, | ||
10, | ||
5, | ||
8, | ||
4, | ||
2 | ||
], | ||
regex: /^(FI)(\d{8})$/ | ||
} | ||
}; | ||
COUNTRIES.france = { | ||
calcs: function(vat) { | ||
var total; | ||
var expect; | ||
// Checks the check digits of a French VAT number. | ||
@@ -638,81 +588,92 @@ if (!(/^\d{11}$/).test(vat)) { | ||
}, | ||
united_kingdom: function (vat, countryName) { | ||
var total = 0; | ||
// Government departments | ||
if (vat.substr(0, 2) === 'GD') { | ||
expect = 500; | ||
return vat.substr(2, 3) < expect; | ||
} | ||
rules: { | ||
regex: [ | ||
/^(FR)(\d{11})$/, | ||
/^(FR)([A-HJ-NP-Z]\d{10})$/, | ||
/^(FR)(\d[A-HJ-NP-Z]\d{9})$/, | ||
/^(FR)([A-HJ-NP-Z]{2}\d{9})$/ | ||
] | ||
} | ||
}; | ||
COUNTRIES.germany = { | ||
calcs: function(vat) { | ||
// Checks the check digits of a German VAT number. | ||
var product = 10; | ||
var sum = 0; | ||
var checkDigit = 0; | ||
var expect; | ||
// Health authorities | ||
if (vat.substr(0, 2) === 'HA') { | ||
expect = 499; | ||
return vat.substr(2, 3) > expect; | ||
} | ||
for (var i = 0; i < 8; i++) { | ||
// Standard and commercial numbers | ||
// 0 VAT numbers disallowed! | ||
if (+vat.slice(0) === 0) return false; | ||
// Check range is OK for modulus 97 calculation | ||
var no = +vat.slice(0, 7); | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 7; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
// Extract the next digit and implement peculiar algorithm!. | ||
sum = (+vat.charAt(i) + product) % 10; | ||
if (sum === 0) { | ||
sum = 10; | ||
} | ||
product = (2 * sum) % 11; | ||
} | ||
// Old numbers use a simple 97 modulus, but new numbers use an adaptation of that (less 55). Our | ||
// VAT number could use either system, so we check it against both. | ||
// Establish check digits by subtracting 97 from total until negative. | ||
var checkDigit = total; | ||
while (checkDigit > 0) { | ||
checkDigit = checkDigit - 97; | ||
// Establish check digit. | ||
if (11 - product === 10) { | ||
checkDigit = 0; | ||
} else { | ||
checkDigit = 11 - product; | ||
} | ||
// Get the absolute value and compare it with the last two characters of the VAT number. If the | ||
// same, then it is a valid traditional check digit. However, even then the number must fit within | ||
// certain specified ranges. | ||
checkDigit = Math.abs(checkDigit); | ||
if (checkDigit === +vat.slice(7, 9) && no < 9990001 && (no < 100000 || no > 999999) && (no < 9490001 || no > 9700000)) return true; | ||
// Now try the new method by subtracting 55 from the check digit if we can - else add 42 | ||
if (checkDigit >= 55) | ||
checkDigit = checkDigit - 55; | ||
else | ||
checkDigit = checkDigit + 42; | ||
expect = +vat.slice(7, 9); | ||
return !!(checkDigit === expect && no > 1000000); | ||
// Compare it with the last two characters of the VAT number. If the same, then it is a valid | ||
// check digit. | ||
expect = +vat.slice(8, 9); | ||
return checkDigit === expect; | ||
}, | ||
croatia: function (vat) { | ||
rules: { | ||
regex: /^(DE)([1-9]\d{8})$/ | ||
} | ||
}; | ||
COUNTRIES.greece = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
//eight character numbers should be prefixed with an 0. | ||
if (vat.length === 8) { | ||
vat = '0' + vat; | ||
} | ||
// Checks the check digits of a Croatian VAT number using ISO 7064, MOD 11-10 for check digit. | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
var product = 10; | ||
var sum = 0; | ||
for (var i = 0; i < 10; i++) { | ||
// Extract the next digit and implement the algorithm | ||
sum = (+vat.charAt(i) + product) % 10; | ||
if (sum === 0) { | ||
sum = 10; | ||
} | ||
product = (2 * sum) % 11; | ||
// Establish check digit. | ||
total = total % 11; | ||
if (total > 9) { | ||
total = 0; | ||
} | ||
// Now check that we have the right check digit | ||
expect = +vat.slice(10, 11); | ||
return (product + expect) % 10 === 1; | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(8, 9); | ||
return total === expect; | ||
}, | ||
hungary: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
256, | ||
128, | ||
64, | ||
32, | ||
16, | ||
8, | ||
4, | ||
2 | ||
], | ||
regex: /^(EL)(\d{9})$/ | ||
} | ||
}; | ||
COUNTRIES.hungary = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 7; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -728,6 +689,22 @@ | ||
}, | ||
ireland: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
9, | ||
7, | ||
3, | ||
1, | ||
9, | ||
7, | ||
3 | ||
], | ||
regex: /^(HU)(\d{8})$/ | ||
} | ||
}; | ||
COUNTRIES.ireland = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// If the code is type 1 format, we need to convert it to the new before performing the validation. | ||
if (/^\d[A-Z\*\+]/.test(vat)) { | ||
if (this.rules.typeFormats.first.test(vat)) { | ||
vat = '0' + vat.substring(2, 7) + vat.substring(0, 1) + vat.substring(7, 8); | ||
@@ -738,7 +715,7 @@ } | ||
for (var i = 0; i < 7; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
// If the number is type 3 then we need to include the trailing A or H in the calculation | ||
if (/^\d{7}[A-Z][AH]$/.test(vat)) { | ||
if (this.rules.typeFormats.third.test(vat)) { | ||
// Add in a multiplier for the character A (1*9=9) or H (8*9=72) | ||
@@ -764,4 +741,29 @@ if (vat.charAt(8) === 'H') { | ||
}, | ||
italy: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
typeFormats: { | ||
first: /^\d[A-Z\*\+]/, | ||
third: /^\d{7}[A-Z][AH]$/ | ||
}, | ||
regex: [ | ||
/^(IE)(\d{7}[A-W])$/, | ||
/^(IE)([7-9][A-Z\*\+)]\d{5}[A-W])$/, | ||
/^(IE)(\d{7}[A-W][AH])$/ | ||
] | ||
} | ||
}; | ||
COUNTRIES.italy = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var temp; | ||
var expect; | ||
// The last three digits are the issuing office, and cannot exceed more 201, unless 999 or 888 | ||
@@ -779,3 +781,3 @@ if (+vat.slice(0, 7) === 0) { | ||
for (var i = 0; i < 10; i++) { | ||
temp = +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
temp = +vat.charAt(i) * this.rules.multipliers[i]; | ||
if (temp > 9) | ||
@@ -797,5 +799,103 @@ total += Math.floor(temp / 10) + temp % 10; | ||
}, | ||
lithunia: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
1, | ||
2, | ||
1, | ||
2, | ||
1, | ||
2, | ||
1, | ||
2, | ||
1, | ||
2 | ||
], | ||
regex: /^(IT)(\d{11})$/ | ||
} | ||
}; | ||
COUNTRIES.latvia = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Differentiate between legal entities and natural bodies. For the latter we simply check that | ||
// the first six digits correspond to valid DDMMYY dates. | ||
if ((/^[0-3]/).test(vat)) { | ||
return !!(/^[0-3][0-9][0-1][0-9]/).test(vat); | ||
} else { | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 10; i++) { | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
// Establish check digits by getting modulus 11. | ||
if (total % 11 === 4 && vat[0] === 9) total = total - 45; | ||
if (total % 11 === 4) { | ||
total = 4 - total % 11; | ||
} else if (total % 11 > 4) { | ||
total = 14 - total % 11; | ||
} else if (total % 11 < 4) { | ||
total = 3 - total % 11; | ||
} | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(10, 11); | ||
return total === expect; | ||
} | ||
}, | ||
rules: { | ||
multipliers: [ | ||
9, | ||
1, | ||
4, | ||
8, | ||
3, | ||
10, | ||
2, | ||
5, | ||
7, | ||
6 | ||
], | ||
regex: /^(LV)(\d{11})$/ | ||
} | ||
}; | ||
COUNTRIES.lithunia = (function() { | ||
function _extractDigit(vat, multiplier, key) { | ||
return +vat.charAt(key) * multiplier[key]; | ||
} | ||
function _doubleCheckCalculation(vat, total, rules) { | ||
if (total % 11 === 10) { | ||
total = 0; | ||
for (var i = 0; i < 8; i++) { | ||
total += _extractDigit(vat, rules.multipliers.short, i) | ||
} | ||
} | ||
return total; | ||
} | ||
function extractDigit(vat, total) { | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * (i + 1); | ||
} | ||
return total; | ||
} | ||
function checkDigit(total) { | ||
total = total % 11; | ||
if (total === 10) { | ||
total = 0; | ||
} | ||
return total; | ||
} | ||
function _check9DigitVat(vat, rules) { | ||
// 9 character VAT numbers are for legal persons | ||
var total = 0; | ||
if (vat.length === 9) { | ||
@@ -807,58 +907,111 @@ | ||
// Extract the next digit and multiply by the counter+1. | ||
total = 0; | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * (i + 1); | ||
} | ||
total = extractDigit(vat, total); | ||
// Can have a double check digit calculation! | ||
if (total % 11 === 10) { | ||
total = 0; | ||
for (var j = 0; j < 8; j++) { | ||
total += +vat.charAt(j) * CONDITIONS[countryName].multipliers.short[j]; | ||
} | ||
} | ||
total = _doubleCheckCalculation(vat, total, rules); | ||
// Establish check digit. | ||
total = total % 11; | ||
if (total === 10) { | ||
total = 0; | ||
} | ||
total = checkDigit(total); | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(8, 9); | ||
var expect = +vat.slice(8, 9); | ||
return total === expect; | ||
} | ||
return false; | ||
} | ||
function extractDigit12(vat, total, rules) { | ||
for (var k = 0; k < 11; k++) { | ||
total += _extractDigit(vat, rules.multipliers.med, k) | ||
} | ||
return total; | ||
} | ||
function _doubleCheckCalculation12(vat, total, rules) { | ||
if (total % 11 === 10) { | ||
total = 0; | ||
for (var l = 0; l < 11; l++) { | ||
total += _extractDigit(vat, rules.multipliers.alt, l) | ||
} | ||
} | ||
return total; | ||
} | ||
function _check12DigitVat(vat, rules) { | ||
var total = 0; | ||
// 12 character VAT numbers are for temporarily registered taxpayers | ||
else { | ||
if (vat.length === 12) { | ||
// 11th character must be one | ||
if (!(/^\d{10}1/).test(vat)) return false; | ||
if (!(rules.check).test(vat)) return false; | ||
// Extract the next digit and multiply by the counter+1. | ||
total = 0; | ||
for (var k = 0; k < 11; k++) { | ||
total += +vat.charAt(k) * CONDITIONS[countryName].multipliers.med[k]; | ||
} | ||
total = extractDigit12(vat, total, rules); | ||
// Can have a double check digit calculation! | ||
if (total % 11 === 10) { | ||
total = 0; | ||
for (var l = 0; l < 11; l++) { | ||
total += +vat.charAt(l) * CONDITIONS[countryName].multipliers.alt[l]; | ||
} | ||
} | ||
total = _doubleCheckCalculation12(vat, total, rules); | ||
// Establish check digit. | ||
total = total % 11; | ||
if (total === 10) { | ||
total = 0; | ||
} | ||
total = checkDigit(total); | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(11, 12); | ||
var expect = +vat.slice(11, 12); | ||
return total === expect; | ||
} | ||
}, | ||
luxembourg: function (vat) { | ||
return false; | ||
} | ||
return { | ||
calcs: function(vat) { | ||
return _check9DigitVat(vat, this.rules) || _check12DigitVat(vat, this.rules); | ||
}, | ||
rules: { | ||
multipliers: { | ||
"short": [ | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
1 | ||
], | ||
"med": [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
1, | ||
2 | ||
], | ||
"alt": [ | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
1, | ||
2, | ||
3, | ||
4 | ||
] | ||
}, | ||
check: /^\d{10}1/, | ||
regex: /^(LT)(\d{9}|\d{12})$/ | ||
} | ||
}; | ||
})(); | ||
COUNTRIES.luxembourg = { | ||
calcs: function(vat) { | ||
var expect = +vat.slice(6, 8); | ||
@@ -870,35 +1023,14 @@ var checkDigit = +vat.slice(0, 6) % 89; | ||
}, | ||
latvia: function (vat, countryName) { | ||
rules: { | ||
regex: /^(LU)(\d{8})$/ | ||
} | ||
}; | ||
COUNTRIES.malta = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Differentiate between legal entities and natural bodies. For the latter we simply check that | ||
// the first six digits correspond to valid DDMMYY dates. | ||
if ((/^[0-3]/).test(vat)) { | ||
return !!(/^[0-3][0-9][0-1][0-9]/).test(vat); | ||
} else { | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 10; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
} | ||
// Establish check digits by getting modulus 11. | ||
if (total % 11 === 4 && vat[0] === 9) total = total - 45; | ||
if (total % 11 === 4) | ||
total = 4 - total % 11; | ||
else if (total % 11 > 4) | ||
total = 14 - total % 11; | ||
else if (total % 11 < 4) | ||
total = 3 - total % 11; | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(10, 11); | ||
return total === expect; | ||
} | ||
}, | ||
malta: function (vat, countryName) { | ||
var total = 0; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 6; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -913,7 +1045,22 @@ | ||
}, | ||
netherlands: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
3, | ||
4, | ||
6, | ||
7, | ||
8, | ||
9 | ||
], | ||
regex: /^(MT)([1-9]\d{7})$/ | ||
} | ||
}; | ||
COUNTRIES.netherlands = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -931,4 +1078,20 @@ | ||
}, | ||
norway: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
9, | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
regex: /^(NL)(\d{9})B\d{2}$/ | ||
} | ||
}; | ||
COUNTRIES.norway = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// See http://www.brreg.no/english/coordination/number.html | ||
@@ -938,3 +1101,3 @@ | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -944,7 +1107,8 @@ | ||
total = 11 - total % 11; | ||
if (total === 11) { | ||
total = 0; | ||
} | ||
if (total < 10) { | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
@@ -955,7 +1119,24 @@ expect = +vat.slice(8, 9); | ||
}, | ||
poland: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
3, | ||
2, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
regex: /^(NO)(\d{9})$/ | ||
} | ||
}; | ||
COUNTRIES.poland = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 9; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -973,7 +1154,25 @@ | ||
}, | ||
portugal: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
6, | ||
5, | ||
7, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7 | ||
], | ||
regex: /^(PL)(\d{10})$/ | ||
} | ||
}; | ||
COUNTRIES.portugal = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
@@ -991,7 +1190,24 @@ | ||
}, | ||
romania: function (vat, countryName) { | ||
rules: { | ||
multipliers: [ | ||
9, | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
regex: /^(PT)(\d{9})$/ | ||
} | ||
}; | ||
COUNTRIES.romania = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
var vatLength = vat.length; | ||
var multipliers = CONDITIONS[countryName].multipliers.slice(10 - vatLength); | ||
var multipliers = this.rules.multipliers.slice(10 - vatLength); | ||
@@ -1010,36 +1226,26 @@ for (var i = 0; i < vat.length - 1; i++) { | ||
}, | ||
serbia: function (vat) { | ||
// Checks the check digits of a Serbian VAT number using ISO 7064, MOD 11-10 for check digit. | ||
rules: { | ||
multipliers: [ | ||
7, | ||
5, | ||
3, | ||
2, | ||
1, | ||
7, | ||
5, | ||
3, | ||
2 | ||
], | ||
regex: /^(RO)([1-9]\d{1,9})$/ | ||
} | ||
}; | ||
COUNTRIES.russia = (function() { | ||
var product = 10; | ||
var sum = 0; | ||
var checkDigit; | ||
for (var i = 0; i < 8; i++) { | ||
// Extract the next digit and implement the algorithm | ||
sum = (+vat.charAt(i) + product) % 10; | ||
if (sum === 0) { | ||
sum = 10; | ||
} | ||
product = (2 * sum) % 11; | ||
} | ||
// Now check that we have the right check digit | ||
expect = 1; | ||
checkDigit = (product + (+vat.slice(8, 9))) % 10; | ||
return checkDigit === expect; | ||
}, | ||
russia: function (vat, countryName) { | ||
function _check10DigitINN(vat, rules) { | ||
var total = 0; | ||
var expect2; | ||
// Checks the check digits of a Russian INN number | ||
// See http://russianpartner.biz/test_inn.html for algorithm | ||
// 10 digit INN numbers | ||
if (vat.length === 10) { | ||
for (var i = 0; i < 10; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers.m_1[i]; | ||
total += +vat.charAt(i) * rules.multipliers.m_1[i]; | ||
} | ||
@@ -1053,15 +1259,21 @@ | ||
// Compare it with the last character of the VAT number. If it is the same, then it's valid | ||
expect = +vat.slice(9, 10); | ||
var expect = +vat.slice(9, 10); | ||
return total === expect; | ||
} | ||
// 12 digit INN numbers | ||
} else if (vat.length === 12) { | ||
var total1 = 0; | ||
var total2 = 0; | ||
return false; | ||
} | ||
function _check12DigitINN(vat, rules) { | ||
var total1 = 0; | ||
var total2 = 0; | ||
if (vat.length === 12) { | ||
for (var j = 0; j < 11; j++) { | ||
total1 += +vat.charAt(j) * CONDITIONS[countryName].multipliers.m_2[j]; | ||
total1 += +vat.charAt(j) * rules.multipliers.m_2[j]; | ||
} | ||
total1 = total1 % 11; | ||
if (total1 > 9) { | ||
@@ -1072,3 +1284,3 @@ total1 = total1 % 10; | ||
for (var k = 0; k < 11; k++) { | ||
total2 += +vat.charAt(k) * CONDITIONS[countryName].multipliers.m_3[k]; | ||
total2 += +vat.charAt(k) * rules.multipliers.m_3[k]; | ||
} | ||
@@ -1083,10 +1295,226 @@ | ||
// character of the VAT number. If they're both the same, then it's valid | ||
//expect = +vat.slice(10, 11); | ||
expect = (total1 === +vat.slice(10, 11)); | ||
//expect2 = +vat.slice(11, 12); | ||
expect2 = (total2 === +vat.slice(11, 12)); | ||
var expect = (total1 === +vat.slice(10, 11)); | ||
var expect2 = (total2 === +vat.slice(11, 12)); | ||
return (expect) && (expect2); | ||
} | ||
return false; | ||
} | ||
return { | ||
calcs: function(vat) { | ||
// See http://russianpartner.biz/test_inn.html for algorithm | ||
return _check10DigitINN(vat, this.rules) || _check12DigitINN(vat, this.rules); | ||
}, | ||
rules: { | ||
multipliers: { | ||
"m_1": [ | ||
2, | ||
4, | ||
10, | ||
3, | ||
5, | ||
9, | ||
4, | ||
6, | ||
8, | ||
0 | ||
], | ||
"m_2": [ | ||
7, | ||
2, | ||
4, | ||
10, | ||
3, | ||
5, | ||
9, | ||
4, | ||
6, | ||
8, | ||
0 | ||
], | ||
"m_3": [ | ||
3, | ||
7, | ||
2, | ||
4, | ||
10, | ||
3, | ||
5, | ||
9, | ||
4, | ||
6, | ||
8, | ||
0 | ||
] | ||
}, | ||
regex: /^(RU)(\d{10}|\d{12})$/ | ||
} | ||
}; | ||
})(); | ||
COUNTRIES.serbia = { | ||
calcs: function(vat) { | ||
// Checks the check digits of a Serbian VAT number using ISO 7064, MOD 11-10 for check digit. | ||
var product = 10; | ||
var sum = 0; | ||
var checkDigit; | ||
for (var i = 0; i < 8; i++) { | ||
// Extract the next digit and implement the algorithm | ||
sum = (+vat.charAt(i) + product) % 10; | ||
if (sum === 0) { | ||
sum = 10; | ||
} | ||
product = (2 * sum) % 11; | ||
} | ||
// Now check that we have the right check digit | ||
var expect = 1; | ||
checkDigit = (product + (+vat.slice(8, 9))) % 10; | ||
return checkDigit === expect; | ||
}, | ||
sweden: function (vat) { | ||
rules: { | ||
regex: /^(RS)(\d{9})$/ | ||
} | ||
}; | ||
COUNTRIES.slovakia_republic = { | ||
calcs: function(vat) { | ||
var expect = 0; | ||
var checkDigit = (vat % 11); | ||
return checkDigit === expect; | ||
}, | ||
rules: { | ||
regex: /^(SK)([1-9]\d[2346-9]\d{7})$/ | ||
} | ||
}; | ||
COUNTRIES.slovenia = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 7; i++) { | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
// Establish check digits using modulus 11 | ||
total = 11 - total % 11; | ||
if (total === 10) { | ||
total = 0; | ||
} | ||
// Compare the number with the last character of the VAT number. If it is the | ||
// same, then it's a valid check digit. | ||
expect = +vat.slice(7, 8); | ||
return !!(total !== 11 && total === expect); | ||
}, | ||
rules: { | ||
multipliers: [ | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
regex: /^(SI)([1-9]\d{7})$/ | ||
} | ||
}; | ||
COUNTRIES.spain = { | ||
calcs: function(vat) { | ||
var i = 0; | ||
var total = 0; | ||
var temp; | ||
var expect; | ||
// National juridical entities | ||
if (this.rules.additional[0].test(vat)) { | ||
// Extract the next digit and multiply by the counter. | ||
for (i = 0; i < 7; i++) { | ||
temp = vat.charAt(i + 1) * this.rules.multipliers[i]; | ||
if (temp > 9) | ||
total += Math.floor(temp / 10) + temp % 10; | ||
else | ||
total += temp; | ||
} | ||
// Now calculate the check digit itself. | ||
total = 10 - total % 10; | ||
if (total === 10) { | ||
total = 0; | ||
} | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = +vat.slice(8, 9); | ||
return total === expect; | ||
} | ||
// Juridical entities other than national ones | ||
else if (this.rules.additional[1].test(vat)) { | ||
// Extract the next digit and multiply by the counter. | ||
for (i = 0; i < 7; i++) { | ||
temp = vat.charAt(i + 1) * this.rules.multipliers[i]; | ||
if (temp > 9) | ||
total += Math.floor(temp / 10) + temp % 10; | ||
else | ||
total += temp; | ||
} | ||
// Now calculate the check digit itself. | ||
total = 10 - total % 10; | ||
total = String.fromCharCode(total + 64); | ||
// Compare it with the last character of the VAT number. If it's the same, then it's valid. | ||
expect = vat.slice(8, 9); | ||
return total === expect; | ||
} | ||
// Personal number (NIF) (starting with numeric of Y or Z) | ||
else if (this.rules.additional[2].test(vat)) { | ||
var tempnumber = vat; | ||
if (tempnumber.substring(0, 1) === 'Y') tempnumber = tempnumber.replace(/Y/, '1'); | ||
if (tempnumber.substring(0, 1) === 'Z') tempnumber = tempnumber.replace(/Z/, '2'); | ||
expect = 'TRWAGMYFPDXBNJZSQVHLCKE'.charAt(+tempnumber.substring(0, 8) % 23); | ||
return tempnumber.charAt(8) === expect; | ||
} | ||
// Personal number (NIF) (starting with K, L, M, or X) | ||
else if (this.rules.additional[3].test(vat)) { | ||
expect = 'TRWAGMYFPDXBNJZSQVHLCKE'.charAt(+vat.substring(1, 8) % 23); | ||
return vat.charAt(8) === expect; | ||
} else return false; | ||
}, | ||
rules: { | ||
multipliers: [ | ||
2, | ||
1, | ||
2, | ||
1, | ||
2, | ||
1, | ||
2 | ||
], | ||
regex: [ | ||
/^(ES)([A-Z]\d{8})$/, | ||
/^(ES)([A-HN-SW]\d{7}[A-J])$/, | ||
/^(ES)([0-9YZ]\d{7}[A-Z])$/, | ||
/^(ES)([KLMX]\d{7}[A-Z])$/ | ||
], | ||
additional: [ | ||
/^[A-H|J|U|V]\d{8}$/, | ||
/^[A-H|N-S|W]\d{7}[A-J]$/, | ||
/^[0-9|Y|Z]\d{7}[A-Z]$/, | ||
/^[K|L|M|X]\d{7}[A-Z]$/ | ||
] | ||
} | ||
}; | ||
COUNTRIES.sweden = { | ||
calcs: function(vat) { | ||
var expect; | ||
// Calculate R where R = R1 + R3 + R5 + R7 + R9, and Ri = INT(Ci/5) + (Ci*2) modulo 10 | ||
@@ -1113,32 +1541,115 @@ var R = 0; | ||
}, | ||
slovenia: function (vat, countryName) { | ||
rules: { | ||
regex: /^(SE)(\d{10}01)$/ | ||
} | ||
}; | ||
COUNTRIES.switzerland = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
for (var i = 0; i < 8; i++) { | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
// Establish check digit. | ||
total = 11 - total % 11; | ||
if (total === 10) return false; | ||
if (total === 11) total = 0; | ||
// Check to see if the check digit given is correct, If not, we have an error with the VAT number | ||
var expect = +vat.substr(8, 1); | ||
return total === expect; | ||
}, | ||
rules: { | ||
multipliers: [ | ||
5, | ||
4, | ||
3, | ||
2, | ||
7, | ||
6, | ||
5, | ||
4 | ||
], | ||
regex: /^(CHE)(\d{9})(MWST)?$/ | ||
} | ||
}; | ||
COUNTRIES.united_kingdom = { | ||
calcs: function(vat) { | ||
var total = 0; | ||
var expect; | ||
// Government departments | ||
if (vat.substr(0, 2) === 'GD') { | ||
expect = 500; | ||
return vat.substr(2, 3) < expect; | ||
} | ||
// Health authorities | ||
if (vat.substr(0, 2) === 'HA') { | ||
expect = 499; | ||
return vat.substr(2, 3) > expect; | ||
} | ||
// Standard and commercial numbers | ||
// 0 VAT numbers disallowed! | ||
if (+vat.slice(0) === 0) return false; | ||
// Check range is OK for modulus 97 calculation | ||
var no = +vat.slice(0, 7); | ||
// Extract the next digit and multiply by the counter. | ||
for (var i = 0; i < 7; i++) { | ||
total += +vat.charAt(i) * CONDITIONS[countryName].multipliers[i]; | ||
total += +vat.charAt(i) * this.rules.multipliers[i]; | ||
} | ||
// Establish check digits using modulus 11 | ||
total = 11 - total % 11; | ||
if (total === 10) { | ||
total = 0; | ||
// Old numbers use a simple 97 modulus, but new numbers use an adaptation of that (less 55). Our | ||
// VAT number could use either system, so we check it against both. | ||
// Establish check digits by subtracting 97 from total until negative. | ||
var checkDigit = total; | ||
while (checkDigit > 0) { | ||
checkDigit = checkDigit - 97; | ||
} | ||
// Compare the number with the last character of the VAT number. If it is the | ||
// same, then it's a valid check digit. | ||
expect = +vat.slice(7, 8); | ||
return !!(total !== 11 && total === expect); | ||
// Get the absolute value and compare it with the last two characters of the VAT number. If the | ||
// same, then it is a valid traditional check digit. However, even then the number must fit within | ||
// certain specified ranges. | ||
checkDigit = Math.abs(checkDigit); | ||
if (checkDigit === +vat.slice(7, 9) && no < 9990001 && (no < 100000 || no > 999999) && (no < 9490001 || no > 9700000)) return true; | ||
// Now try the new method by subtracting 55 from the check digit if we can - else add 42 | ||
if (checkDigit >= 55) | ||
checkDigit = checkDigit - 55; | ||
else | ||
checkDigit = checkDigit + 42; | ||
expect = +vat.slice(7, 9); | ||
return !!(checkDigit === expect && no > 1000000); | ||
}, | ||
slovakia_republic: function (vat) { | ||
var expect = 0; | ||
var checkDigit = (vat % 11); | ||
// Checks the check digits of a Slovakian VAT number. | ||
// Check that the modulus of the whole VAT number is 0 - else error | ||
return checkDigit === expect; | ||
rules: { | ||
multipliers: [ | ||
8, | ||
7, | ||
6, | ||
5, | ||
4, | ||
3, | ||
2 | ||
], | ||
regex: [ | ||
/^(GB)?(\d{9})$/, | ||
/^(GB)?(\d{12})$/, | ||
/^(GB)?(GD\d{3})$/, | ||
/^(GB)?(HA\d{3})$/ | ||
] | ||
} | ||
}; | ||
//Support of node.js | ||
if (typeof module === 'object' && module.exports) module.exports = exports; | ||
return exports; | ||
})(); |
@@ -1,2 +0,2 @@ | ||
var jsvat=function(){"use strict";function r(r,e){return e.test(r)}function e(r,e,t){var i=e.exec(r),l=i[2];return u[t](l,t)}function t(t,i,l){var a=!1;return r(t,i)&&(a=e(t,i,l)),a}var i,l,a={austria:{multipliers:[1,2,1,2,1,2,1],regex:/^(AT)U(\d{8})$/},belgium:{regex:/^(BE)(0?\d{9})$/},bulgaria:{multipliers:{physical:[2,4,8,5,10,9,7,3,6],foreigner:[21,19,17,13,11,9,7,3,1],miscellaneous:[4,3,2,7,6,5,4,3,2]},regex:/^(BG)(\d{9,10})$/},switzerland:{multipliers:[5,4,3,2,7,6,5,4],regex:/^(CHE)(\d{9})(MWST)?$/},cyprus:{regex:/^(CY)([0-59]\d{7}[A-Z])$/},czech_republic:{multipliers:[8,7,6,5,4,3,2],lookup:[8,7,6,5,4,3,2,1,0,9,10],regex:/^(CZ)(\d{8,10})(\d{3})?$/,additional:[/^\d{8}$/,/^[0-5][0-9][0|1|5|6]\d[0-3]\d\d{3}$/,/^6\d{8}$/,/^\d{2}[0-3|5-8]\d[0-3]\d\d{4}$/]},germany:{regex:/^(DE)([1-9]\d{8})$/},denmark:{multipliers:[2,7,6,5,4,3,2,1],regex:/^(DK)(\d{8})$/},estonia:{multipliers:[3,7,1,3,7,1,3,7],regex:/^(EE)(10\d{7})$/},greece:{multipliers:[256,128,64,32,16,8,4,2],regex:/^(EL)(\d{9})$/},spain:{multipliers:[2,1,2,1,2,1,2],regex:[/^(ES)([A-Z]\d{8})$/,/^(ES)([A-HN-SW]\d{7}[A-J])$/,/^(ES)([0-9YZ]\d{7}[A-Z])$/,/^(ES)([KLMX]\d{7}[A-Z])$/],additional:[/^[A-H|J|U|V]\d{8}$/,/^[A-H|N-S|W]\d{7}[A-J]$/,/^[0-9|Y|Z]\d{7}[A-Z]$/,/^[K|L|M|X]\d{7}[A-Z]$/]},europe:{regex:/^(EU)(\d{9})$/},finland:{multipliers:[7,9,10,5,8,4,2],regex:/^(FI)(\d{8})$/},france:{regex:[/^(FR)(\d{11})$/,/^(FR)([A-HJ-NP-Z]\d{10})$/,/^(FR)(\d[A-HJ-NP-Z]\d{9})$/,/^(FR)([A-HJ-NP-Z]{2}\d{9})$/]},united_kingdom:{multipliers:[8,7,6,5,4,3,2],regex:[/^(GB)?(\d{9})$/,/^(GB)?(\d{12})$/,/^(GB)?(GD\d{3})$/,/^(GB)?(HA\d{3})$/]},croatia:{regex:/^(HR)(\d{11})$/},hungary:{multipliers:[9,7,3,1,9,7,3],regex:/^(HU)(\d{8})$/},ireland:{multipliers:[8,7,6,5,4,3,2],regex:[/^(IE)(\d{7}[A-W])$/,/^(IE)([7-9][A-Z\*\+)]\d{5}[A-W])$/,/^(IE)(\d{7}[A-W][AH])$/]},italy:{multipliers:[1,2,1,2,1,2,1,2,1,2],regex:/^(IT)(\d{11})$/},latvia:{multipliers:[9,1,4,8,3,10,2,5,7,6],regex:/^(LV)(\d{11})$/},lithunia:{multipliers:{"short":[3,4,5,6,7,8,9,1],med:[1,2,3,4,5,6,7,8,9,1,2],alt:[3,4,5,6,7,8,9,1,2,3,4]},regex:/^(LT)(\d{9}|\d{12})$/},luxembourg:{regex:/^(LU)(\d{8})$/},malta:{multipliers:[3,4,6,7,8,9],regex:/^(MT)([1-9]\d{7})$/},netherlands:{multipliers:[9,8,7,6,5,4,3,2],regex:/^(NL)(\d{9})B\d{2}$/},norway:{multipliers:[3,2,7,6,5,4,3,2],regex:/^(NO)(\d{9})$/},poland:{multipliers:[6,5,7,2,3,4,5,6,7],regex:/^(PL)(\d{10})$/},portugal:{multipliers:[9,8,7,6,5,4,3,2],regex:/^(PT)(\d{9})$/},romania:{multipliers:[7,5,3,2,1,7,5,3,2],regex:/^(RO)([1-9]\d{1,9})$/},russia:{multipliers:{m_1:[2,4,10,3,5,9,4,6,8,0],m_2:[7,2,4,10,3,5,9,4,6,8,0],m_3:[3,7,2,4,10,3,5,9,4,6,8,0]},regex:/^(RU)(\d{10}|\d{12})$/},serbia:{regex:/^(RS)(\d{9})$/},slovenia:{multipliers:[8,7,6,5,4,3,2],regex:/^(SI)([1-9]\d{7})$/},slovakia_republic:{regex:/^(SK)([1-9]\d[2346-9]\d{7})$/},sweden:{regex:/^(SE)(\d{10}01)$/}},n={checkVAT:function(r){if(!r)return!1;r=r.toString().toUpperCase().replace(/(\s|-|\.)+/g,"");for(var e in a)if(a.hasOwnProperty(e)){var i=a[e].regex;if(Array.isArray(i)){for(var l=0;l<i.length;l++)if(t(r,i[l],e))return!0}else if(t(r,i,e))return!0}return!1}},u={austria:function(r,e){for(var t=0,n=0;7>n;n++)l=r.charAt(n)*a[e].multipliers[n],t+=l>9?Math.floor(l/10)+l%10:l;return t=10-(t+4)%10,10===t&&(t=0),i=+r.slice(7,8),t===i},belgium:function(r){if(9===r.length&&(r="0"+r),0===+r.slice(1,2))return!1;var e=97-+r.slice(0,8)%97;return i=+r.slice(8,10),e===i},bulgaria:function(r,e){var t=function(){var e=0;l=0;for(var t=0;8>t;t++)l+=+r.charAt(t)*(t+1);if(e=l%11,10!==e)return i=+r.slice(8),e===i;l=0;for(var a=0;8>a;a++)l+=+r.charAt(a)*(a+3);return e=l%11,10===e&&(e=0),i=+r.slice(8),e===i},n=function(){var t=0;if(/^\d\d[0-5]\d[0-3]\d\d{4}$/.test(r)){var i=+r.slice(2,4);if(i>0&&13>i||i>20&&33>i||i>40&&53>i){t=0;for(var l=0;9>l;l++)t+=+r.charAt(l)*a[e].multipliers.physical[l];if(t%=11,10===t&&(t=0),t===+r.substr(9,1))return!0}}return!1},u=function(){for(var t=0,i=0;9>i;i++)t+=+r.charAt(i)*a[e].multipliers.foreigner[i];return t%10===+r.substr(9,1)?!0:void 0},s=function(){for(var t=0,l=0;9>l;l++)t+=+r.charAt(l)*a[e].multipliers.miscellaneous[l];return t=11-t%11,10===t?!1:(11===t&&(t=0),i=+r.substr(9,1),t===i)};return 9===r.length?t():n()||u()||s()},switzerland:function(r,e){for(var t=0,l=0;8>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=11-t%11,10===t?!1:(11===t&&(t=0),i=+r.substr(8,1),t===i)},cyprus:function(r){var e=0;if(12===+r.slice(0,2))return!1;for(var t=0;8>t;t++){var l=+r.charAt(t);if(t%2===0)switch(l){case 0:l=1;break;case 1:l=0;break;case 2:l=5;break;case 3:l=7;break;case 4:l=9;break;default:l=2*l+3}e+=l}return e%=26,e=String.fromCharCode(e+65),i=r.substr(8,1),e===i},czech_republic:function(r,e){var t=0;if(a[e].additional[0].test(r)){for(var l=0;7>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=11-t%11,10===t&&(t=0),11===t&&(t=1),i=+r.slice(7,8),t===i}if(a[e].additional[2].test(r)){for(var n=0;7>n;n++)t+=+r.charAt(n+1)*a[e].multipliers[n];return t=11-t%11,10===t&&(t=0),11===t&&(t=1),i=+r.slice(8,9),a[e].lookup[t-1]===i}if(a[e].additional[3].test(r)){var u=+r.slice(0,2)+r.slice(2,4)+r.slice(4,6)+r.slice(6,8)+r.slice(8);return i=+r%11===0,!(u%11!==0||!i)}return!1},germany:function(r){for(var e=10,t=0,l=0,a=0;8>a;a++)t=(+r.charAt(a)+e)%10,0===t&&(t=10),e=2*t%11;return l=11-e===10?0:11-e,i=+r.slice(8,9),l===i},denmark:function(r,e){for(var t=0,i=0;8>i;i++)t+=+r.charAt(i)*a[e].multipliers[i];return t%11===0},estonia:function(r,e){for(var t=0,l=0;8>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=10-t%10,10===t&&(t=0),i=+r.slice(8,9),t===i},greece:function(r,e){var t=0;8===r.length&&(r="0"+r);for(var l=0;8>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t%=11,t>9&&(t=0),i=+r.slice(8,9),t===i},spain:function(r,e){var t=0,n=0;if(a[e].additional[0].test(r)){for(t=0;7>t;t++)l=r.charAt(t+1)*a[e].multipliers[t],n+=l>9?Math.floor(l/10)+l%10:l;return n=10-n%10,10===n&&(n=0),i=+r.slice(8,9),n===i}if(a[e].additional[1].test(r)){for(t=0;7>t;t++)l=r.charAt(t+1)*a[e].multipliers[t],n+=l>9?Math.floor(l/10)+l%10:l;return n=10-n%10,n=String.fromCharCode(n+64),i=r.slice(8,9),n===i}if(a[e].additional[2].test(r)){var u=r;return"Y"===u.substring(0,1)&&(u=u.replace(/Y/,"1")),"Z"===u.substring(0,1)&&(u=u.replace(/Z/,"2")),i="TRWAGMYFPDXBNJZSQVHLCKE".charAt(+u.substring(0,8)%23),u.charAt(8)===i}return a[e].additional[3].test(r)?(i="TRWAGMYFPDXBNJZSQVHLCKE".charAt(+r.substring(1,8)%23),r.charAt(8)===i):!1},europe:function(){return!0},finland:function(r,e){for(var t=0,l=0;7>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=11-t%11,t>9&&(t=0),i=+r.slice(7,8),t===i},france:function(r){var e;return/^\d{11}$/.test(r)?(e=+r.substring(2),e=(100*e+12)%97,i=+r.slice(0,2),e===i):!0},united_kingdom:function(r,e){var t=0;if("GD"===r.substr(0,2))return i=500,r.substr(2,3)<i;if("HA"===r.substr(0,2))return i=499,r.substr(2,3)>i;if(0===+r.slice(0))return!1;for(var l=+r.slice(0,7),n=0;7>n;n++)t+=+r.charAt(n)*a[e].multipliers[n];for(var u=t;u>0;)u-=97;return u=Math.abs(u),u===+r.slice(7,9)&&9990001>l&&(1e5>l||l>999999)&&(9490001>l||l>97e5)?!0:(u>=55?u-=55:u+=42,i=+r.slice(7,9),!!(u===i&&l>1e6))},croatia:function(r){for(var e=10,t=0,l=0;10>l;l++)t=(+r.charAt(l)+e)%10,0===t&&(t=10),e=2*t%11;return i=+r.slice(10,11),(e+i)%10===1},hungary:function(r,e){for(var t=0,l=0;7>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=10-t%10,10===t&&(t=0),i=+r.slice(7,8),t===i},ireland:function(r,e){var t=0;/^\d[A-Z\*\+]/.test(r)&&(r="0"+r.substring(2,7)+r.substring(0,1)+r.substring(7,8));for(var l=0;7>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return/^\d{7}[A-Z][AH]$/.test(r)&&(t+="H"===r.charAt(8)?72:9),t%=23,t=0===t?"W":String.fromCharCode(t+64),i=r.slice(7,8),t===i},italy:function(r,e){var t=0;if(0===+r.slice(0,7))return!1;if(l=+r.slice(7,10),1>l||l>201&&999!==l&&888!==l)return!1;for(var n=0;10>n;n++)l=+r.charAt(n)*a[e].multipliers[n],t+=l>9?Math.floor(l/10)+l%10:l;return t=10-t%10,t>9&&(t=0),i=+r.slice(10,11),t===i},lithunia:function(r,e){var t=0;if(9===r.length){if(!/^\d{7}1/.test(r))return!1;t=0;for(var l=0;8>l;l++)t+=+r.charAt(l)*(l+1);if(t%11===10){t=0;for(var n=0;8>n;n++)t+=+r.charAt(n)*a[e].multipliers["short"][n]}return t%=11,10===t&&(t=0),i=+r.slice(8,9),t===i}if(!/^\d{10}1/.test(r))return!1;t=0;for(var u=0;11>u;u++)t+=+r.charAt(u)*a[e].multipliers.med[u];if(t%11===10){t=0;for(var s=0;11>s;s++)t+=+r.charAt(s)*a[e].multipliers.alt[s]}return t%=11,10===t&&(t=0),i=+r.slice(11,12),t===i},luxembourg:function(r){var e=+r.slice(6,8),t=+r.slice(0,6)%89;return t===e},latvia:function(r,e){var t=0;if(/^[0-3]/.test(r))return!!/^[0-3][0-9][0-1][0-9]/.test(r);for(var l=0;10>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t%11===4&&9===r[0]&&(t-=45),t%11===4?t=4-t%11:t%11>4?t=14-t%11:4>t%11&&(t=3-t%11),i=+r.slice(10,11),t===i},malta:function(r,e){for(var t=0,l=0;6>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=37-t%37,i=+r.slice(6,8),t===i},netherlands:function(r,e){for(var t=0,l=0;8>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t%=11,t>9&&(t=0),i=+r.slice(8,9),t===i},norway:function(r,e){for(var t=0,l=0;8>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=11-t%11,11===t&&(t=0),10>t?(i=+r.slice(8,9),t===i):void 0},poland:function(r,e){for(var t=0,l=0;9>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t%=11,t>9&&(t=0),i=+r.slice(9,10),t===i},portugal:function(r,e){for(var t=0,l=0;8>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=11-t%11,t>9&&(t=0),i=+r.slice(8,9),t===i},romania:function(r,e){for(var t=0,l=r.length,n=a[e].multipliers.slice(10-l),u=0;u<r.length-1;u++)t+=+r.charAt(u)*n[u];return t=10*t%11,10===t&&(t=0),i=+r.slice(r.length-1,r.length),t===i},serbia:function(r){for(var e,t=10,l=0,a=0;8>a;a++)l=(+r.charAt(a)+t)%10,0===l&&(l=10),t=2*l%11;return i=1,e=(t+ +r.slice(8,9))%10,e===i},russia:function(r,e){var t,l=0;if(10===r.length){for(var n=0;10>n;n++)l+=+r.charAt(n)*a[e].multipliers.m_1[n];return l%=11,l>9&&(l%=10),i=+r.slice(9,10),l===i}if(12===r.length){for(var u=0,s=0,c=0;11>c;c++)u+=+r.charAt(c)*a[e].multipliers.m_2[c];u%=11,u>9&&(u%=10);for(var o=0;11>o;o++)s+=+r.charAt(o)*a[e].multipliers.m_3[o];return s%=11,s>9&&(s%=10),i=u===+r.slice(10,11),t=s===+r.slice(11,12),i&&t}},sweden:function(r){for(var e,t=0,l=0;9>l;l+=2)e=+r.charAt(l),t+=Math.floor(e/5)+2*e%10;for(var a=0,n=1;9>n;n+=2)a+=+r.charAt(n);var u=(10-(t+a)%10)%10;return i=+r.slice(9,10),u===i},slovenia:function(r,e){for(var t=0,l=0;7>l;l++)t+=+r.charAt(l)*a[e].multipliers[l];return t=11-t%11,10===t&&(t=0),i=+r.slice(7,8),!(11===t||t!==i)},slovakia_republic:function(r){var e=0,t=r%11;return t===e}};return"object"==typeof module&&module.exports&&(module.exports=n),n}(); | ||
var jsvat=function(){"use strict";function r(r,e){return e.test(r)}function e(r,e,t){var i=e.exec(r),s=i[2];return u[t].calcs(s)}function t(t,i,s){var l=!1;return r(t,i)&&(l=e(t,i,s)),l}function i(r){return r.toString().toUpperCase().replace(/(\s|-|\.)+/g,"")}function s(r){return Array.isArray(r)?r:[r]}function l(r,e){if(!r||0===Object.keys(r).length)return!1;var t=r[e];return null===t||void 0===t?!0:!t}var u={},n={config:{},checkVAT:function(r,e){if(!r)return!1;r=i(r);var c={isValid:!1,countries:[]};for(var a in u)if(u.hasOwnProperty(a)&&!l(n.config,a))for(var o=s(u[a].rules.regex),f=0;f<o.length;f++){if(c.isValid=t(r,o[f],a)?!0:c.isValid,!e&&c.isValid)return c.isValid;var d=t(r,o[f],a);d&&c.countries.push(a)}return e?c:c.isValid}};return u.austria={calcs:function(r){for(var e,t,i=0,s=0;7>s;s++)e=r.charAt(s)*this.rules.multipliers[s],i+=e>9?Math.floor(e/10)+e%10:e;return i=10-(i+4)%10,10===i&&(i=0),t=+r.slice(7,8),i===t},rules:{multipliers:[1,2,1,2,1,2,1],regex:/^(AT)U(\d{8})$/}},u.belgium={calcs:function(r){var e;if(9===r.length&&(r="0"+r),0===+r.slice(1,2))return!1;var t=97-+r.slice(0,8)%97;return e=+r.slice(8,10),t===e},rules:{regex:/^(BE)(0?\d{9})$/}},u.bulgaria=function(){function r(r){for(var e,t,i=0,s=0;8>s;s++)i+=+r.charAt(s)*(s+1);if(e=i%11,10!==e)return t=+r.slice(8),e===t;i=0;for(var l=0;8>l;l++)i+=+r.charAt(l)*(l+3);return e=i%11,10===e&&(e=0),t=+r.slice(8),e===t}function e(r,e){var t=0;if(/^\d\d[0-5]\d[0-3]\d\d{4}$/.test(r)){var i=+r.slice(2,4);if(i>0&&13>i||i>20&&33>i||i>40&&53>i){t=0;for(var s=0;9>s;s++)t+=+r.charAt(s)*e.multipliers.physical[s];if(t%=11,10===t&&(t=0),t===+r.substr(9,1))return!0}}return!1}function t(r,e){for(var t=0,i=0;9>i;i++)t+=+r.charAt(i)*e.multipliers.foreigner[i];return t%10===+r.substr(9,1)?!0:void 0}function i(r,e){for(var t=0,i=0;9>i;i++)t+=+r.charAt(i)*e.multipliers.miscellaneous[i];if(t=11-t%11,10===t)return!1;11===t&&(t=0);var s=+r.substr(9,1);return t===s}return{calcs:function(s){return 9===s.length?r(s):e(s,this.rules)||t(s,this.rules)||i(s,this.rules)},rules:{multipliers:{physical:[2,4,8,5,10,9,7,3,6],foreigner:[21,19,17,13,11,9,7,3,1],miscellaneous:[4,3,2,7,6,5,4,3,2]},regex:/^(BG)(\d{9,10})$/}}}(),u.croatia={calcs:function(r){for(var e,t=10,i=0,s=0;10>s;s++)i=(+r.charAt(s)+t)%10,0===i&&(i=10),t=2*i%11;return e=+r.slice(10,11),(t+e)%10===1},rules:{regex:/^(HR)(\d{11})$/}},u.cyprus={calcs:function(r){var e,t=0;if(12===+r.slice(0,2))return!1;for(var i=0;8>i;i++){var s=+r.charAt(i);if(i%2===0)switch(s){case 0:s=1;break;case 1:s=0;break;case 2:s=5;break;case 3:s=7;break;case 4:s=9;break;default:s=2*s+3}t+=s}return t%=26,t=String.fromCharCode(t+65),e=r.substr(8,1),t===e},rules:{regex:/^(CY)([0-59]\d{7}[A-Z])$/}},u.czech_republic=function(){function r(r,e){var t=0;if(e.additional[0].test(r)){for(var i=0;7>i;i++)t+=+r.charAt(i)*e.multipliers[i];t=11-t%11,10===t&&(t=0),11===t&&(t=1);var s=+r.slice(7,8);return t===s}return!1}function e(r,e){var t=0;if(e.additional[2].test(r)){for(var i=0;7>i;i++)t+=+r.charAt(i+1)*e.multipliers[i];t=11-t%11,10===t&&(t=0),11===t&&(t=1);var s=+r.slice(8,9);return e.lookup[t-1]===s}return!1}function t(r,e){if(e.additional[3].test(r)){var t=+r.slice(0,2)+r.slice(2,4)+r.slice(4,6)+r.slice(6,8)+r.slice(8),i=+r%11===0;return!(t%11!==0||!i)}return!1}return{calcs:function(i){return r(i,this.rules)?!0:e(i,this.rules)?!0:!!t(i,this.rules)},rules:{multipliers:[8,7,6,5,4,3,2],lookup:[8,7,6,5,4,3,2,1,0,9,10],regex:/^(CZ)(\d{8,10})(\d{3})?$/,additional:[/^\d{8}$/,/^[0-5][0-9][0|1|5|6]\d[0-3]\d\d{3}$/,/^6\d{8}$/,/^\d{2}[0-3|5-8]\d[0-3]\d\d{4}$/]}}}(),u.denmark={calcs:function(r){for(var e=0,t=0;8>t;t++)e+=+r.charAt(t)*this.rules.multipliers[t];return e%11===0},rules:{multipliers:[2,7,6,5,4,3,2,1],regex:/^(DK)(\d{8})$/}},u.estonia={calcs:function(r){for(var e,t=0,i=0;8>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=10-t%10,10===t&&(t=0),e=+r.slice(8,9),t===e},rules:{multipliers:[3,7,1,3,7,1,3,7],regex:/^(EE)(10\d{7})$/}},u.europe={calcs:function(r){return!0},rules:{regex:/^(EU)(\d{9})$/}},u.finland={calcs:function(r){for(var e,t=0,i=0;7>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=11-t%11,t>9&&(t=0),e=+r.slice(7,8),t===e},rules:{multipliers:[7,9,10,5,8,4,2],regex:/^(FI)(\d{8})$/}},u.france={calcs:function(r){var e,t;return/^\d{11}$/.test(r)?(e=+r.substring(2),e=(100*e+12)%97,t=+r.slice(0,2),e===t):!0},rules:{regex:[/^(FR)(\d{11})$/,/^(FR)([A-HJ-NP-Z]\d{10})$/,/^(FR)(\d[A-HJ-NP-Z]\d{9})$/,/^(FR)([A-HJ-NP-Z]{2}\d{9})$/]}},u.germany={calcs:function(r){for(var e,t=10,i=0,s=0,l=0;8>l;l++)i=(+r.charAt(l)+t)%10,0===i&&(i=10),t=2*i%11;return s=11-t===10?0:11-t,e=+r.slice(8,9),s===e},rules:{regex:/^(DE)([1-9]\d{8})$/}},u.greece={calcs:function(r){var e,t=0;8===r.length&&(r="0"+r);for(var i=0;8>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t%=11,t>9&&(t=0),e=+r.slice(8,9),t===e},rules:{multipliers:[256,128,64,32,16,8,4,2],regex:/^(EL)(\d{9})$/}},u.hungary={calcs:function(r){for(var e,t=0,i=0;7>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=10-t%10,10===t&&(t=0),e=+r.slice(7,8),t===e},rules:{multipliers:[9,7,3,1,9,7,3],regex:/^(HU)(\d{8})$/}},u.ireland={calcs:function(r){var e,t=0;this.rules.typeFormats.first.test(r)&&(r="0"+r.substring(2,7)+r.substring(0,1)+r.substring(7,8));for(var i=0;7>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return this.rules.typeFormats.third.test(r)&&(t+="H"===r.charAt(8)?72:9),t%=23,t=0===t?"W":String.fromCharCode(t+64),e=r.slice(7,8),t===e},rules:{multipliers:[8,7,6,5,4,3,2],typeFormats:{first:/^\d[A-Z\*\+]/,third:/^\d{7}[A-Z][AH]$/},regex:[/^(IE)(\d{7}[A-W])$/,/^(IE)([7-9][A-Z\*\+)]\d{5}[A-W])$/,/^(IE)(\d{7}[A-W][AH])$/]}},u.italy={calcs:function(r){var e,t,i=0;if(0===+r.slice(0,7))return!1;if(e=+r.slice(7,10),1>e||e>201&&999!==e&&888!==e)return!1;for(var s=0;10>s;s++)e=+r.charAt(s)*this.rules.multipliers[s],i+=e>9?Math.floor(e/10)+e%10:e;return i=10-i%10,i>9&&(i=0),t=+r.slice(10,11),i===t},rules:{multipliers:[1,2,1,2,1,2,1,2,1,2],regex:/^(IT)(\d{11})$/}},u.latvia={calcs:function(r){var e,t=0;if(/^[0-3]/.test(r))return!!/^[0-3][0-9][0-1][0-9]/.test(r);for(var i=0;10>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t%11===4&&9===r[0]&&(t-=45),t%11===4?t=4-t%11:t%11>4?t=14-t%11:4>t%11&&(t=3-t%11),e=+r.slice(10,11),t===e},rules:{multipliers:[9,1,4,8,3,10,2,5,7,6],regex:/^(LV)(\d{11})$/}},u.lithunia=function(){function r(r,e,t){return+r.charAt(t)*e[t]}function e(e,t,i){if(t%11===10){t=0;for(var s=0;8>s;s++)t+=r(e,i.multipliers["short"],s)}return t}function t(r,e){for(var t=0;8>t;t++)e+=+r.charAt(t)*(t+1);return e}function i(r){return r%=11,10===r&&(r=0),r}function s(r,s){var l=0;if(9===r.length){if(!/^\d{7}1/.test(r))return!1;l=t(r,l),l=e(r,l,s),l=i(l);var u=+r.slice(8,9);return l===u}return!1}function l(e,t,i){for(var s=0;11>s;s++)t+=r(e,i.multipliers.med,s);return t}function u(e,t,i){if(t%11===10){t=0;for(var s=0;11>s;s++)t+=r(e,i.multipliers.alt,s)}return t}function n(r,e){var t=0;if(12===r.length){if(!e.check.test(r))return!1;t=l(r,t,e),t=u(r,t,e),t=i(t);var s=+r.slice(11,12);return t===s}return!1}return{calcs:function(r){return s(r,this.rules)||n(r,this.rules)},rules:{multipliers:{"short":[3,4,5,6,7,8,9,1],med:[1,2,3,4,5,6,7,8,9,1,2],alt:[3,4,5,6,7,8,9,1,2,3,4]},check:/^\d{10}1/,regex:/^(LT)(\d{9}|\d{12})$/}}}(),u.luxembourg={calcs:function(r){var e=+r.slice(6,8),t=+r.slice(0,6)%89;return t===e},rules:{regex:/^(LU)(\d{8})$/}},u.malta={calcs:function(r){for(var e,t=0,i=0;6>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=37-t%37,e=+r.slice(6,8),t===e},rules:{multipliers:[3,4,6,7,8,9],regex:/^(MT)([1-9]\d{7})$/}},u.netherlands={calcs:function(r){for(var e,t=0,i=0;8>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t%=11,t>9&&(t=0),e=+r.slice(8,9),t===e},rules:{multipliers:[9,8,7,6,5,4,3,2],regex:/^(NL)(\d{9})B\d{2}$/}},u.norway={calcs:function(r){for(var e,t=0,i=0;8>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=11-t%11,11===t&&(t=0),10>t?(e=+r.slice(8,9),t===e):void 0},rules:{multipliers:[3,2,7,6,5,4,3,2],regex:/^(NO)(\d{9})$/}},u.poland={calcs:function(r){for(var e,t=0,i=0;9>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t%=11,t>9&&(t=0),e=+r.slice(9,10),t===e},rules:{multipliers:[6,5,7,2,3,4,5,6,7],regex:/^(PL)(\d{10})$/}},u.portugal={calcs:function(r){for(var e,t=0,i=0;8>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=11-t%11,t>9&&(t=0),e=+r.slice(8,9),t===e},rules:{multipliers:[9,8,7,6,5,4,3,2],regex:/^(PT)(\d{9})$/}},u.romania={calcs:function(r){for(var e,t=0,i=r.length,s=this.rules.multipliers.slice(10-i),l=0;l<r.length-1;l++)t+=+r.charAt(l)*s[l];return t=10*t%11,10===t&&(t=0),e=+r.slice(r.length-1,r.length),t===e},rules:{multipliers:[7,5,3,2,1,7,5,3,2],regex:/^(RO)([1-9]\d{1,9})$/}},u.russia=function(){function r(r,e){var t=0;if(10===r.length){for(var i=0;10>i;i++)t+=+r.charAt(i)*e.multipliers.m_1[i];t%=11,t>9&&(t%=10);var s=+r.slice(9,10);return t===s}return!1}function e(r,e){var t=0,i=0;if(12===r.length){for(var s=0;11>s;s++)t+=+r.charAt(s)*e.multipliers.m_2[s];t%=11,t>9&&(t%=10);for(var l=0;11>l;l++)i+=+r.charAt(l)*e.multipliers.m_3[l];i%=11,i>9&&(i%=10);var u=t===+r.slice(10,11),n=i===+r.slice(11,12);return u&&n}return!1}return{calcs:function(t){return r(t,this.rules)||e(t,this.rules)},rules:{multipliers:{m_1:[2,4,10,3,5,9,4,6,8,0],m_2:[7,2,4,10,3,5,9,4,6,8,0],m_3:[3,7,2,4,10,3,5,9,4,6,8,0]},regex:/^(RU)(\d{10}|\d{12})$/}}}(),u.serbia={calcs:function(r){for(var e,t=10,i=0,s=0;8>s;s++)i=(+r.charAt(s)+t)%10,0===i&&(i=10),t=2*i%11;var l=1;return e=(t+ +r.slice(8,9))%10,e===l},rules:{regex:/^(RS)(\d{9})$/}},u.slovakia_republic={calcs:function(r){var e=0,t=r%11;return t===e},rules:{regex:/^(SK)([1-9]\d[2346-9]\d{7})$/}},u.slovenia={calcs:function(r){for(var e,t=0,i=0;7>i;i++)t+=+r.charAt(i)*this.rules.multipliers[i];return t=11-t%11,10===t&&(t=0),e=+r.slice(7,8),!(11===t||t!==e)},rules:{multipliers:[8,7,6,5,4,3,2],regex:/^(SI)([1-9]\d{7})$/}},u.spain={calcs:function(r){var e,t,i=0,s=0;if(this.rules.additional[0].test(r)){for(i=0;7>i;i++)e=r.charAt(i+1)*this.rules.multipliers[i],s+=e>9?Math.floor(e/10)+e%10:e;return s=10-s%10,10===s&&(s=0),t=+r.slice(8,9),s===t}if(this.rules.additional[1].test(r)){for(i=0;7>i;i++)e=r.charAt(i+1)*this.rules.multipliers[i],s+=e>9?Math.floor(e/10)+e%10:e;return s=10-s%10,s=String.fromCharCode(s+64),t=r.slice(8,9),s===t}if(this.rules.additional[2].test(r)){var l=r;return"Y"===l.substring(0,1)&&(l=l.replace(/Y/,"1")),"Z"===l.substring(0,1)&&(l=l.replace(/Z/,"2")),t="TRWAGMYFPDXBNJZSQVHLCKE".charAt(+l.substring(0,8)%23),l.charAt(8)===t}return this.rules.additional[3].test(r)?(t="TRWAGMYFPDXBNJZSQVHLCKE".charAt(+r.substring(1,8)%23),r.charAt(8)===t):!1},rules:{multipliers:[2,1,2,1,2,1,2],regex:[/^(ES)([A-Z]\d{8})$/,/^(ES)([A-HN-SW]\d{7}[A-J])$/,/^(ES)([0-9YZ]\d{7}[A-Z])$/,/^(ES)([KLMX]\d{7}[A-Z])$/],additional:[/^[A-H|J|U|V]\d{8}$/,/^[A-H|N-S|W]\d{7}[A-J]$/,/^[0-9|Y|Z]\d{7}[A-Z]$/,/^[K|L|M|X]\d{7}[A-Z]$/]}},u.sweden={calcs:function(r){for(var e,t,i=0,s=0;9>s;s+=2)t=+r.charAt(s),i+=Math.floor(t/5)+2*t%10;for(var l=0,u=1;9>u;u+=2)l+=+r.charAt(u);var n=(10-(i+l)%10)%10;return e=+r.slice(9,10),n===e},rules:{regex:/^(SE)(\d{10}01)$/}},u.switzerland={calcs:function(r){for(var e=0,t=0;8>t;t++)e+=+r.charAt(t)*this.rules.multipliers[t];if(e=11-e%11,10===e)return!1;11===e&&(e=0);var i=+r.substr(8,1);return e===i},rules:{multipliers:[5,4,3,2,7,6,5,4],regex:/^(CHE)(\d{9})(MWST)?$/}},u.united_kingdom={calcs:function(r){var e,t=0;if("GD"===r.substr(0,2))return e=500,r.substr(2,3)<e;if("HA"===r.substr(0,2))return e=499,r.substr(2,3)>e;if(0===+r.slice(0))return!1;for(var i=+r.slice(0,7),s=0;7>s;s++)t+=+r.charAt(s)*this.rules.multipliers[s];for(var l=t;l>0;)l-=97;return l=Math.abs(l),l===+r.slice(7,9)&&9990001>i&&(1e5>i||i>999999)&&(9490001>i||i>97e5)?!0:(l>=55?l-=55:l+=42,e=+r.slice(7,9),!!(l===e&&i>1e6))},rules:{multipliers:[8,7,6,5,4,3,2],regex:[/^(GB)?(\d{9})$/,/^(GB)?(\d{12})$/,/^(GB)?(GD\d{3})$/,/^(GB)?(HA\d{3})$/]}},"object"==typeof module&&module.exports&&(module.exports=n),n}(); | ||
//# sourceMappingURL=jsvat.min.js.map |
'use strict'; | ||
var gulp = require('gulp'), rename, uglify, sourcemaps, jshint, size, buddyjs, todo; | ||
var gulp = require('gulp'); | ||
var config = require('./build/config.js'); | ||
var requireDir = require('require-dir'); | ||
requireDir('./build', { recurse: true }); | ||
var src = { | ||
jsDir: [ | ||
'src/**/*.js' | ||
] | ||
}; | ||
var dest = { | ||
dist: 'dist' | ||
}; | ||
gulp.task('lint', function () { | ||
jshint = jshint || require('gulp-jshint'); | ||
return gulp.src(src.jsDir) | ||
.pipe(jshint({ | ||
globalstrict: true, | ||
strict: false, | ||
globals: { | ||
angular: true, | ||
localStorage: true, | ||
console: true | ||
} | ||
})) | ||
.pipe(jshint.reporter('jshint-stylish')); | ||
gulp.task('default', function () { | ||
gulp.start('make'); | ||
gulp.start('watch'); | ||
}); | ||
gulp.task('webstandards', function () { | ||
var webstandards = require('gulp-webstandards'); | ||
return gulp.src(src.jsDir) | ||
.pipe(webstandards()); | ||
}); | ||
gulp.task('magic_numbers', function () { | ||
buddyjs = buddyjs || require('gulp-buddy.js'); | ||
return gulp.src(src.jsDir) | ||
.pipe(buddyjs({ | ||
ignore: [0, 1, 2], | ||
reporter: 'detailed' | ||
})); | ||
}); | ||
gulp.task('sizes', function () { | ||
size = size || require('gulp-size'); | ||
return gulp.src([ | ||
'dist/**/*.js', | ||
'dist/**/*.css', | ||
'dist/**/*.gz' | ||
]).pipe(size({showFiles: true, showTotal: true})); | ||
}); | ||
gulp.task('js', function () { | ||
sourcemaps = sourcemaps || require('gulp-sourcemaps'); | ||
uglify = uglify || require('gulp-uglify'); | ||
rename = rename || require('gulp-rename'); | ||
return gulp.src(src.jsDir) | ||
.pipe(gulp.dest(dest.dist)) | ||
.pipe(sourcemaps.init()) | ||
.pipe(uglify()) | ||
.pipe(rename({basename: 'jsvat.min'})) | ||
.pipe(sourcemaps.write('.')) | ||
.pipe(gulp.dest(dest.dist)) | ||
; | ||
}); | ||
gulp.task('todo', function () { | ||
todo = require('gulp-todo'); | ||
gulp.src('src/**/*.*') | ||
.pipe(todo()) | ||
.pipe(gulp.dest('./')); | ||
}); | ||
gulp.task('watch', function () { | ||
var watch = require('gulp-watch'); | ||
gulp.watch(src.jsDir, ['js', 'todo']); | ||
}); | ||
gulp.task('build', function () { | ||
gulp.start('js'); | ||
gulp.start('todo'); | ||
}); | ||
gulp.task('default', function () { | ||
gulp.start('build'); | ||
gulp.start('watch'); | ||
}); | ||
gulp.watch(config.js.src, ['js', 'todo']); | ||
}); |
{ | ||
"name": "jsvat", | ||
"version": "0.6.1", | ||
"version": "0.9.0", | ||
"description": "Check the validity of the format of an EU VAT number", | ||
"main": "./dist/jsvat.js", | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "mocha \"test/acceptance/test_cases.js\"" | ||
}, | ||
@@ -41,4 +41,9 @@ "license": "MIT", | ||
"chai": "^3.5.0", | ||
"gulp-beautify": "^2.0.0", | ||
"gulp-buddy.js": "^1.0.0", | ||
"gulp-concat": "^2.6.0", | ||
"gulp-gzip": "^1.2.0", | ||
"gulp-jshint": "^2.0.0", | ||
"gulp-notify": "^2.2.0", | ||
"gulp-plumber": "^1.1.0", | ||
"gulp-rename": "^1.2.2", | ||
@@ -54,4 +59,6 @@ "gulp-size": "^2.1.0", | ||
"jshint-stylish": "^2.1.0", | ||
"mocha": "^2.4.5" | ||
"mocha": "^2.4.5", | ||
"require-dir": "^0.3.0", | ||
"run-sequence": "^1.1.5" | ||
} | ||
} |
### TODOs | ||
| Filename | line # | TODO | ||
|:------|:------:|:------ | ||
| jsvat.js | 207 | (S.Panfilov) this is not cross-browser check | ||
| jsvat.js | 589 | (S.Panfilov) wtf? | ||
| main.js | 27 | (S.Panfilov) this is not cross-browser check |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 2 instances in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
98
5565
303382
21
3