isTaxID.js 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399
  1. "use strict";
  2. function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.default = isTaxID;
  7. var _assertString = _interopRequireDefault(require("./util/assertString"));
  8. var algorithms = _interopRequireWildcard(require("./util/algorithms"));
  9. var _isDate = _interopRequireDefault(require("./isDate"));
  10. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  11. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  12. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  13. function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
  14. function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  15. function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  16. function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
  17. function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
  18. function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
  19. /**
  20. * TIN Validation
  21. * Validates Tax Identification Numbers (TINs) from the US, EU member states and the United Kingdom.
  22. *
  23. * EU-UK:
  24. * National TIN validity is calculated using public algorithms as made available by DG TAXUD.
  25. *
  26. * See `https://ec.europa.eu/taxation_customs/tin/specs/FS-TIN%20Algorithms-Public.docx` for more information.
  27. *
  28. * US:
  29. * An Employer Identification Number (EIN), also known as a Federal Tax Identification Number,
  30. * is used to identify a business entity.
  31. *
  32. * NOTES:
  33. * - Prefix 47 is being reserved for future use
  34. * - Prefixes 26, 27, 45, 46 and 47 were previously assigned by the Philadelphia campus.
  35. *
  36. * See `http://www.irs.gov/Businesses/Small-Businesses-&-Self-Employed/How-EINs-are-Assigned-and-Valid-EIN-Prefixes`
  37. * for more information.
  38. */
  39. // Locale functions
  40. /*
  41. * bg-BG validation function
  42. * (Edinen graždanski nomer (EGN/ЕГН), persons only)
  43. * Checks if birth date (first six digits) is valid and calculates check (last) digit
  44. */
  45. function bgBgCheck(tin) {
  46. // Extract full year, normalize month and check birth date validity
  47. var century_year = tin.slice(0, 2);
  48. var month = parseInt(tin.slice(2, 4), 10);
  49. if (month > 40) {
  50. month -= 40;
  51. century_year = "20".concat(century_year);
  52. } else if (month > 20) {
  53. month -= 20;
  54. century_year = "18".concat(century_year);
  55. } else {
  56. century_year = "19".concat(century_year);
  57. }
  58. if (month < 10) {
  59. month = "0".concat(month);
  60. }
  61. var date = "".concat(century_year, "/").concat(month, "/").concat(tin.slice(4, 6));
  62. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  63. return false;
  64. }
  65. // split digits into an array for further processing
  66. var digits = tin.split('').map(function (a) {
  67. return parseInt(a, 10);
  68. });
  69. // Calculate checksum by multiplying digits with fixed values
  70. var multip_lookup = [2, 4, 8, 5, 10, 9, 7, 3, 6];
  71. var checksum = 0;
  72. for (var i = 0; i < multip_lookup.length; i++) {
  73. checksum += digits[i] * multip_lookup[i];
  74. }
  75. checksum = checksum % 11 === 10 ? 0 : checksum % 11;
  76. return checksum === digits[9];
  77. }
  78. /**
  79. * Check if an input is a valid Canadian SIN (Social Insurance Number)
  80. *
  81. * The Social Insurance Number (SIN) is a 9 digit number that
  82. * you need to work in Canada or to have access to government programs and benefits.
  83. *
  84. * https://en.wikipedia.org/wiki/Social_Insurance_Number
  85. * https://www.canada.ca/en/employment-social-development/services/sin.html
  86. * https://www.codercrunch.com/challenge/819302488/sin-validator
  87. *
  88. * @param {string} input
  89. * @return {boolean}
  90. */
  91. function isCanadianSIN(input) {
  92. var digitsArray = input.split('');
  93. var even = digitsArray.filter(function (_, idx) {
  94. return idx % 2;
  95. }).map(function (i) {
  96. return Number(i) * 2;
  97. }).join('').split('');
  98. var total = digitsArray.filter(function (_, idx) {
  99. return !(idx % 2);
  100. }).concat(even).map(function (i) {
  101. return Number(i);
  102. }).reduce(function (acc, cur) {
  103. return acc + cur;
  104. });
  105. return total % 10 === 0;
  106. }
  107. /*
  108. * cs-CZ validation function
  109. * (Rodné číslo (RČ), persons only)
  110. * Checks if birth date (first six digits) is valid and divisibility by 11
  111. * Material not in DG TAXUD document sourced from:
  112. * -`https://lorenc.info/3MA381/overeni-spravnosti-rodneho-cisla.htm`
  113. * -`https://www.mvcr.cz/clanek/rady-a-sluzby-dokumenty-rodne-cislo.aspx`
  114. */
  115. function csCzCheck(tin) {
  116. tin = tin.replace(/\W/, '');
  117. // Extract full year from TIN length
  118. var full_year = parseInt(tin.slice(0, 2), 10);
  119. if (tin.length === 10) {
  120. if (full_year < 54) {
  121. full_year = "20".concat(full_year);
  122. } else {
  123. full_year = "19".concat(full_year);
  124. }
  125. } else {
  126. if (tin.slice(6) === '000') {
  127. return false;
  128. } // Three-zero serial not assigned before 1954
  129. if (full_year < 54) {
  130. full_year = "19".concat(full_year);
  131. } else {
  132. return false; // No 18XX years seen in any of the resources
  133. }
  134. }
  135. // Add missing zero if needed
  136. if (full_year.length === 3) {
  137. full_year = [full_year.slice(0, 2), '0', full_year.slice(2)].join('');
  138. }
  139. // Extract month from TIN and normalize
  140. var month = parseInt(tin.slice(2, 4), 10);
  141. if (month > 50) {
  142. month -= 50;
  143. }
  144. if (month > 20) {
  145. // Month-plus-twenty was only introduced in 2004
  146. if (parseInt(full_year, 10) < 2004) {
  147. return false;
  148. }
  149. month -= 20;
  150. }
  151. if (month < 10) {
  152. month = "0".concat(month);
  153. }
  154. // Check date validity
  155. var date = "".concat(full_year, "/").concat(month, "/").concat(tin.slice(4, 6));
  156. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  157. return false;
  158. }
  159. // Verify divisibility by 11
  160. if (tin.length === 10) {
  161. if (parseInt(tin, 10) % 11 !== 0) {
  162. // Some numbers up to and including 1985 are still valid if
  163. // check (last) digit equals 0 and modulo of first 9 digits equals 10
  164. var checkdigit = parseInt(tin.slice(0, 9), 10) % 11;
  165. if (parseInt(full_year, 10) < 1986 && checkdigit === 10) {
  166. if (parseInt(tin.slice(9), 10) !== 0) {
  167. return false;
  168. }
  169. } else {
  170. return false;
  171. }
  172. }
  173. }
  174. return true;
  175. }
  176. /*
  177. * de-AT validation function
  178. * (Abgabenkontonummer, persons/entities)
  179. * Verify TIN validity by calling luhnCheck()
  180. */
  181. function deAtCheck(tin) {
  182. return algorithms.luhnCheck(tin);
  183. }
  184. /*
  185. * de-DE validation function
  186. * (Steueridentifikationsnummer (Steuer-IdNr.), persons only)
  187. * Tests for single duplicate/triplicate value, then calculates ISO 7064 check (last) digit
  188. * Partial implementation of spec (same result with both algorithms always)
  189. */
  190. function deDeCheck(tin) {
  191. // Split digits into an array for further processing
  192. var digits = tin.split('').map(function (a) {
  193. return parseInt(a, 10);
  194. });
  195. // Fill array with strings of number positions
  196. var occurences = [];
  197. for (var i = 0; i < digits.length - 1; i++) {
  198. occurences.push('');
  199. for (var j = 0; j < digits.length - 1; j++) {
  200. if (digits[i] === digits[j]) {
  201. occurences[i] += j;
  202. }
  203. }
  204. }
  205. // Remove digits with one occurence and test for only one duplicate/triplicate
  206. occurences = occurences.filter(function (a) {
  207. return a.length > 1;
  208. });
  209. if (occurences.length !== 2 && occurences.length !== 3) {
  210. return false;
  211. }
  212. // In case of triplicate value only two digits are allowed next to each other
  213. if (occurences[0].length === 3) {
  214. var trip_locations = occurences[0].split('').map(function (a) {
  215. return parseInt(a, 10);
  216. });
  217. var recurrent = 0; // Amount of neighbour occurences
  218. for (var _i = 0; _i < trip_locations.length - 1; _i++) {
  219. if (trip_locations[_i] + 1 === trip_locations[_i + 1]) {
  220. recurrent += 1;
  221. }
  222. }
  223. if (recurrent === 2) {
  224. return false;
  225. }
  226. }
  227. return algorithms.iso7064Check(tin);
  228. }
  229. /*
  230. * dk-DK validation function
  231. * (CPR-nummer (personnummer), persons only)
  232. * Checks if birth date (first six digits) is valid and assigned to century (seventh) digit,
  233. * and calculates check (last) digit
  234. */
  235. function dkDkCheck(tin) {
  236. tin = tin.replace(/\W/, '');
  237. // Extract year, check if valid for given century digit and add century
  238. var year = parseInt(tin.slice(4, 6), 10);
  239. var century_digit = tin.slice(6, 7);
  240. switch (century_digit) {
  241. case '0':
  242. case '1':
  243. case '2':
  244. case '3':
  245. year = "19".concat(year);
  246. break;
  247. case '4':
  248. case '9':
  249. if (year < 37) {
  250. year = "20".concat(year);
  251. } else {
  252. year = "19".concat(year);
  253. }
  254. break;
  255. default:
  256. if (year < 37) {
  257. year = "20".concat(year);
  258. } else if (year > 58) {
  259. year = "18".concat(year);
  260. } else {
  261. return false;
  262. }
  263. break;
  264. }
  265. // Add missing zero if needed
  266. if (year.length === 3) {
  267. year = [year.slice(0, 2), '0', year.slice(2)].join('');
  268. }
  269. // Check date validity
  270. var date = "".concat(year, "/").concat(tin.slice(2, 4), "/").concat(tin.slice(0, 2));
  271. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  272. return false;
  273. }
  274. // Split digits into an array for further processing
  275. var digits = tin.split('').map(function (a) {
  276. return parseInt(a, 10);
  277. });
  278. var checksum = 0;
  279. var weight = 4;
  280. // Multiply by weight and add to checksum
  281. for (var i = 0; i < 9; i++) {
  282. checksum += digits[i] * weight;
  283. weight -= 1;
  284. if (weight === 1) {
  285. weight = 7;
  286. }
  287. }
  288. checksum %= 11;
  289. if (checksum === 1) {
  290. return false;
  291. }
  292. return checksum === 0 ? digits[9] === 0 : digits[9] === 11 - checksum;
  293. }
  294. /*
  295. * el-CY validation function
  296. * (Arithmos Forologikou Mitroou (AFM/ΑΦΜ), persons only)
  297. * Verify TIN validity by calculating ASCII value of check (last) character
  298. */
  299. function elCyCheck(tin) {
  300. // split digits into an array for further processing
  301. var digits = tin.slice(0, 8).split('').map(function (a) {
  302. return parseInt(a, 10);
  303. });
  304. var checksum = 0;
  305. // add digits in even places
  306. for (var i = 1; i < digits.length; i += 2) {
  307. checksum += digits[i];
  308. }
  309. // add digits in odd places
  310. for (var _i2 = 0; _i2 < digits.length; _i2 += 2) {
  311. if (digits[_i2] < 2) {
  312. checksum += 1 - digits[_i2];
  313. } else {
  314. checksum += 2 * (digits[_i2] - 2) + 5;
  315. if (digits[_i2] > 4) {
  316. checksum += 2;
  317. }
  318. }
  319. }
  320. return String.fromCharCode(checksum % 26 + 65) === tin.charAt(8);
  321. }
  322. /*
  323. * el-GR validation function
  324. * (Arithmos Forologikou Mitroou (AFM/ΑΦΜ), persons/entities)
  325. * Verify TIN validity by calculating check (last) digit
  326. * Algorithm not in DG TAXUD document- sourced from:
  327. * - `http://epixeirisi.gr/%CE%9A%CE%A1%CE%99%CE%A3%CE%99%CE%9C%CE%91-%CE%98%CE%95%CE%9C%CE%91%CE%A4%CE%91-%CE%A6%CE%9F%CE%A1%CE%9F%CE%9B%CE%9F%CE%93%CE%99%CE%91%CE%A3-%CE%9A%CE%91%CE%99-%CE%9B%CE%9F%CE%93%CE%99%CE%A3%CE%A4%CE%99%CE%9A%CE%97%CE%A3/23791/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8C%CF%82-%CE%A6%CE%BF%CF%81%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CE%BA%CE%BF%CF%8D-%CE%9C%CE%B7%CF%84%CF%81%CF%8E%CE%BF%CF%85`
  328. */
  329. function elGrCheck(tin) {
  330. // split digits into an array for further processing
  331. var digits = tin.split('').map(function (a) {
  332. return parseInt(a, 10);
  333. });
  334. var checksum = 0;
  335. for (var i = 0; i < 8; i++) {
  336. checksum += digits[i] * Math.pow(2, 8 - i);
  337. }
  338. return checksum % 11 % 10 === digits[8];
  339. }
  340. /*
  341. * en-GB validation function (should go here if needed)
  342. * (National Insurance Number (NINO) or Unique Taxpayer Reference (UTR),
  343. * persons/entities respectively)
  344. */
  345. /*
  346. * en-IE validation function
  347. * (Personal Public Service Number (PPS No), persons only)
  348. * Verify TIN validity by calculating check (second to last) character
  349. */
  350. function enIeCheck(tin) {
  351. var checksum = algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 7).map(function (a) {
  352. return parseInt(a, 10);
  353. }), 8);
  354. if (tin.length === 9 && tin[8] !== 'W') {
  355. checksum += (tin[8].charCodeAt(0) - 64) * 9;
  356. }
  357. checksum %= 23;
  358. if (checksum === 0) {
  359. return tin[7].toUpperCase() === 'W';
  360. }
  361. return tin[7].toUpperCase() === String.fromCharCode(64 + checksum);
  362. }
  363. // Valid US IRS campus prefixes
  364. var enUsCampusPrefix = {
  365. andover: ['10', '12'],
  366. atlanta: ['60', '67'],
  367. austin: ['50', '53'],
  368. brookhaven: ['01', '02', '03', '04', '05', '06', '11', '13', '14', '16', '21', '22', '23', '25', '34', '51', '52', '54', '55', '56', '57', '58', '59', '65'],
  369. cincinnati: ['30', '32', '35', '36', '37', '38', '61'],
  370. fresno: ['15', '24'],
  371. internet: ['20', '26', '27', '45', '46', '47'],
  372. kansas: ['40', '44'],
  373. memphis: ['94', '95'],
  374. ogden: ['80', '90'],
  375. philadelphia: ['33', '39', '41', '42', '43', '46', '48', '62', '63', '64', '66', '68', '71', '72', '73', '74', '75', '76', '77', '81', '82', '83', '84', '85', '86', '87', '88', '91', '92', '93', '98', '99'],
  376. sba: ['31']
  377. };
  378. // Return an array of all US IRS campus prefixes
  379. function enUsGetPrefixes() {
  380. var prefixes = [];
  381. for (var location in enUsCampusPrefix) {
  382. // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes
  383. // istanbul ignore else
  384. if (enUsCampusPrefix.hasOwnProperty(location)) {
  385. prefixes.push.apply(prefixes, _toConsumableArray(enUsCampusPrefix[location]));
  386. }
  387. }
  388. return prefixes;
  389. }
  390. /*
  391. * en-US validation function
  392. * Verify that the TIN starts with a valid IRS campus prefix
  393. */
  394. function enUsCheck(tin) {
  395. return enUsGetPrefixes().indexOf(tin.slice(0, 2)) !== -1;
  396. }
  397. /*
  398. * es-AR validation function
  399. * Clave Única de Identificación Tributaria (CUIT/CUIL)
  400. * Sourced from:
  401. * - https://servicioscf.afip.gob.ar/publico/abc/ABCpaso2.aspx?id_nivel1=3036&id_nivel2=3040&p=Conceptos%20b%C3%A1sicos
  402. * - https://es.wikipedia.org/wiki/Clave_%C3%9Anica_de_Identificaci%C3%B3n_Tributaria
  403. */
  404. function esArCheck(tin) {
  405. var accum = 0;
  406. var digits = tin.split('');
  407. var digit = parseInt(digits.pop(), 10);
  408. for (var i = 0; i < digits.length; i++) {
  409. accum += digits[9 - i] * (2 + i % 6);
  410. }
  411. var verif = 11 - accum % 11;
  412. if (verif === 11) {
  413. verif = 0;
  414. } else if (verif === 10) {
  415. verif = 9;
  416. }
  417. return digit === verif;
  418. }
  419. /*
  420. * es-ES validation function
  421. * (Documento Nacional de Identidad (DNI)
  422. * or Número de Identificación de Extranjero (NIE), persons only)
  423. * Verify TIN validity by calculating check (last) character
  424. */
  425. function esEsCheck(tin) {
  426. // Split characters into an array for further processing
  427. var chars = tin.toUpperCase().split('');
  428. // Replace initial letter if needed
  429. if (isNaN(parseInt(chars[0], 10)) && chars.length > 1) {
  430. var lead_replace = 0;
  431. switch (chars[0]) {
  432. case 'Y':
  433. lead_replace = 1;
  434. break;
  435. case 'Z':
  436. lead_replace = 2;
  437. break;
  438. default:
  439. }
  440. chars.splice(0, 1, lead_replace);
  441. // Fill with zeros if smaller than proper
  442. } else {
  443. while (chars.length < 9) {
  444. chars.unshift(0);
  445. }
  446. }
  447. // Calculate checksum and check according to lookup
  448. var lookup = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'];
  449. chars = chars.join('');
  450. var checksum = parseInt(chars.slice(0, 8), 10) % 23;
  451. return chars[8] === lookup[checksum];
  452. }
  453. /*
  454. * et-EE validation function
  455. * (Isikukood (IK), persons only)
  456. * Checks if birth date (century digit and six following) is valid and calculates check (last) digit
  457. * Material not in DG TAXUD document sourced from:
  458. * - `https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Estonia-TIN.pdf`
  459. */
  460. function etEeCheck(tin) {
  461. // Extract year and add century
  462. var full_year = tin.slice(1, 3);
  463. var century_digit = tin.slice(0, 1);
  464. switch (century_digit) {
  465. case '1':
  466. case '2':
  467. full_year = "18".concat(full_year);
  468. break;
  469. case '3':
  470. case '4':
  471. full_year = "19".concat(full_year);
  472. break;
  473. default:
  474. full_year = "20".concat(full_year);
  475. break;
  476. }
  477. // Check date validity
  478. var date = "".concat(full_year, "/").concat(tin.slice(3, 5), "/").concat(tin.slice(5, 7));
  479. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  480. return false;
  481. }
  482. // Split digits into an array for further processing
  483. var digits = tin.split('').map(function (a) {
  484. return parseInt(a, 10);
  485. });
  486. var checksum = 0;
  487. var weight = 1;
  488. // Multiply by weight and add to checksum
  489. for (var i = 0; i < 10; i++) {
  490. checksum += digits[i] * weight;
  491. weight += 1;
  492. if (weight === 10) {
  493. weight = 1;
  494. }
  495. }
  496. // Do again if modulo 11 of checksum is 10
  497. if (checksum % 11 === 10) {
  498. checksum = 0;
  499. weight = 3;
  500. for (var _i3 = 0; _i3 < 10; _i3++) {
  501. checksum += digits[_i3] * weight;
  502. weight += 1;
  503. if (weight === 10) {
  504. weight = 1;
  505. }
  506. }
  507. if (checksum % 11 === 10) {
  508. return digits[10] === 0;
  509. }
  510. }
  511. return checksum % 11 === digits[10];
  512. }
  513. /*
  514. * fi-FI validation function
  515. * (Henkilötunnus (HETU), persons only)
  516. * Checks if birth date (first six digits plus century symbol) is valid
  517. * and calculates check (last) digit
  518. */
  519. function fiFiCheck(tin) {
  520. // Extract year and add century
  521. var full_year = tin.slice(4, 6);
  522. var century_symbol = tin.slice(6, 7);
  523. switch (century_symbol) {
  524. case '+':
  525. full_year = "18".concat(full_year);
  526. break;
  527. case '-':
  528. full_year = "19".concat(full_year);
  529. break;
  530. default:
  531. full_year = "20".concat(full_year);
  532. break;
  533. }
  534. // Check date validity
  535. var date = "".concat(full_year, "/").concat(tin.slice(2, 4), "/").concat(tin.slice(0, 2));
  536. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  537. return false;
  538. }
  539. // Calculate check character
  540. var checksum = parseInt(tin.slice(0, 6) + tin.slice(7, 10), 10) % 31;
  541. if (checksum < 10) {
  542. return checksum === parseInt(tin.slice(10), 10);
  543. }
  544. checksum -= 10;
  545. var letters_lookup = ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y'];
  546. return letters_lookup[checksum] === tin.slice(10);
  547. }
  548. /*
  549. * fr/nl-BE validation function
  550. * (Numéro national (N.N.), persons only)
  551. * Checks if birth date (first six digits) is valid and calculates check (last two) digits
  552. */
  553. function frBeCheck(tin) {
  554. // Zero month/day value is acceptable
  555. if (tin.slice(2, 4) !== '00' || tin.slice(4, 6) !== '00') {
  556. // Extract date from first six digits of TIN
  557. var date = "".concat(tin.slice(0, 2), "/").concat(tin.slice(2, 4), "/").concat(tin.slice(4, 6));
  558. if (!(0, _isDate.default)(date, 'YY/MM/DD')) {
  559. return false;
  560. }
  561. }
  562. var checksum = 97 - parseInt(tin.slice(0, 9), 10) % 97;
  563. var checkdigits = parseInt(tin.slice(9, 11), 10);
  564. if (checksum !== checkdigits) {
  565. checksum = 97 - parseInt("2".concat(tin.slice(0, 9)), 10) % 97;
  566. if (checksum !== checkdigits) {
  567. return false;
  568. }
  569. }
  570. return true;
  571. }
  572. /*
  573. * fr-FR validation function
  574. * (Numéro fiscal de référence (numéro SPI), persons only)
  575. * Verify TIN validity by calculating check (last three) digits
  576. */
  577. function frFrCheck(tin) {
  578. tin = tin.replace(/\s/g, '');
  579. var checksum = parseInt(tin.slice(0, 10), 10) % 511;
  580. var checkdigits = parseInt(tin.slice(10, 13), 10);
  581. return checksum === checkdigits;
  582. }
  583. /*
  584. * fr/lb-LU validation function
  585. * (numéro d’identification personnelle, persons only)
  586. * Verify birth date validity and run Luhn and Verhoeff checks
  587. */
  588. function frLuCheck(tin) {
  589. // Extract date and check validity
  590. var date = "".concat(tin.slice(0, 4), "/").concat(tin.slice(4, 6), "/").concat(tin.slice(6, 8));
  591. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  592. return false;
  593. }
  594. // Run Luhn check
  595. if (!algorithms.luhnCheck(tin.slice(0, 12))) {
  596. return false;
  597. }
  598. // Remove Luhn check digit and run Verhoeff check
  599. return algorithms.verhoeffCheck("".concat(tin.slice(0, 11)).concat(tin[12]));
  600. }
  601. /*
  602. * hr-HR validation function
  603. * (Osobni identifikacijski broj (OIB), persons/entities)
  604. * Verify TIN validity by calling iso7064Check(digits)
  605. */
  606. function hrHrCheck(tin) {
  607. return algorithms.iso7064Check(tin);
  608. }
  609. /*
  610. * hu-HU validation function
  611. * (Adóazonosító jel, persons only)
  612. * Verify TIN validity by calculating check (last) digit
  613. */
  614. function huHuCheck(tin) {
  615. // split digits into an array for further processing
  616. var digits = tin.split('').map(function (a) {
  617. return parseInt(a, 10);
  618. });
  619. var checksum = 8;
  620. for (var i = 1; i < 9; i++) {
  621. checksum += digits[i] * (i + 1);
  622. }
  623. return checksum % 11 === digits[9];
  624. }
  625. /*
  626. * lt-LT validation function (should go here if needed)
  627. * (Asmens kodas, persons/entities respectively)
  628. * Current validation check is alias of etEeCheck- same format applies
  629. */
  630. /*
  631. * it-IT first/last name validity check
  632. * Accepts it-IT TIN-encoded names as a three-element character array and checks their validity
  633. * Due to lack of clarity between resources ("Are only Italian consonants used?
  634. * What happens if a person has X in their name?" etc.) only two test conditions
  635. * have been implemented:
  636. * Vowels may only be followed by other vowels or an X character
  637. * and X characters after vowels may only be followed by other X characters.
  638. */
  639. function itItNameCheck(name) {
  640. // true at the first occurence of a vowel
  641. var vowelflag = false;
  642. // true at the first occurence of an X AFTER vowel
  643. // (to properly handle last names with X as consonant)
  644. var xflag = false;
  645. for (var i = 0; i < 3; i++) {
  646. if (!vowelflag && /[AEIOU]/.test(name[i])) {
  647. vowelflag = true;
  648. } else if (!xflag && vowelflag && name[i] === 'X') {
  649. xflag = true;
  650. } else if (i > 0) {
  651. if (vowelflag && !xflag) {
  652. if (!/[AEIOU]/.test(name[i])) {
  653. return false;
  654. }
  655. }
  656. if (xflag) {
  657. if (!/X/.test(name[i])) {
  658. return false;
  659. }
  660. }
  661. }
  662. }
  663. return true;
  664. }
  665. /*
  666. * it-IT validation function
  667. * (Codice fiscale (TIN-IT), persons only)
  668. * Verify name, birth date and codice catastale validity
  669. * and calculate check character.
  670. * Material not in DG-TAXUD document sourced from:
  671. * `https://en.wikipedia.org/wiki/Italian_fiscal_code`
  672. */
  673. function itItCheck(tin) {
  674. // Capitalize and split characters into an array for further processing
  675. var chars = tin.toUpperCase().split('');
  676. // Check first and last name validity calling itItNameCheck()
  677. if (!itItNameCheck(chars.slice(0, 3))) {
  678. return false;
  679. }
  680. if (!itItNameCheck(chars.slice(3, 6))) {
  681. return false;
  682. }
  683. // Convert letters in number spaces back to numbers if any
  684. var number_locations = [6, 7, 9, 10, 12, 13, 14];
  685. var number_replace = {
  686. L: '0',
  687. M: '1',
  688. N: '2',
  689. P: '3',
  690. Q: '4',
  691. R: '5',
  692. S: '6',
  693. T: '7',
  694. U: '8',
  695. V: '9'
  696. };
  697. for (var _i4 = 0, _number_locations = number_locations; _i4 < _number_locations.length; _i4++) {
  698. var i = _number_locations[_i4];
  699. if (chars[i] in number_replace) {
  700. chars.splice(i, 1, number_replace[chars[i]]);
  701. }
  702. }
  703. // Extract month and day, and check date validity
  704. var month_replace = {
  705. A: '01',
  706. B: '02',
  707. C: '03',
  708. D: '04',
  709. E: '05',
  710. H: '06',
  711. L: '07',
  712. M: '08',
  713. P: '09',
  714. R: '10',
  715. S: '11',
  716. T: '12'
  717. };
  718. var month = month_replace[chars[8]];
  719. var day = parseInt(chars[9] + chars[10], 10);
  720. if (day > 40) {
  721. day -= 40;
  722. }
  723. if (day < 10) {
  724. day = "0".concat(day);
  725. }
  726. var date = "".concat(chars[6]).concat(chars[7], "/").concat(month, "/").concat(day);
  727. if (!(0, _isDate.default)(date, 'YY/MM/DD')) {
  728. return false;
  729. }
  730. // Calculate check character by adding up even and odd characters as numbers
  731. var checksum = 0;
  732. for (var _i5 = 1; _i5 < chars.length - 1; _i5 += 2) {
  733. var char_to_int = parseInt(chars[_i5], 10);
  734. if (isNaN(char_to_int)) {
  735. char_to_int = chars[_i5].charCodeAt(0) - 65;
  736. }
  737. checksum += char_to_int;
  738. }
  739. var odd_convert = {
  740. // Maps of characters at odd places
  741. A: 1,
  742. B: 0,
  743. C: 5,
  744. D: 7,
  745. E: 9,
  746. F: 13,
  747. G: 15,
  748. H: 17,
  749. I: 19,
  750. J: 21,
  751. K: 2,
  752. L: 4,
  753. M: 18,
  754. N: 20,
  755. O: 11,
  756. P: 3,
  757. Q: 6,
  758. R: 8,
  759. S: 12,
  760. T: 14,
  761. U: 16,
  762. V: 10,
  763. W: 22,
  764. X: 25,
  765. Y: 24,
  766. Z: 23,
  767. 0: 1,
  768. 1: 0
  769. };
  770. for (var _i6 = 0; _i6 < chars.length - 1; _i6 += 2) {
  771. var _char_to_int = 0;
  772. if (chars[_i6] in odd_convert) {
  773. _char_to_int = odd_convert[chars[_i6]];
  774. } else {
  775. var multiplier = parseInt(chars[_i6], 10);
  776. _char_to_int = 2 * multiplier + 1;
  777. if (multiplier > 4) {
  778. _char_to_int += 2;
  779. }
  780. }
  781. checksum += _char_to_int;
  782. }
  783. if (String.fromCharCode(65 + checksum % 26) !== chars[15]) {
  784. return false;
  785. }
  786. return true;
  787. }
  788. /*
  789. * lv-LV validation function
  790. * (Personas kods (PK), persons only)
  791. * Check validity of birth date and calculate check (last) digit
  792. * Support only for old format numbers (not starting with '32', issued before 2017/07/01)
  793. * Material not in DG TAXUD document sourced from:
  794. * `https://boot.ritakafija.lv/forums/index.php?/topic/88314-personas-koda-algoritms-%C4%8Deksumma/`
  795. */
  796. function lvLvCheck(tin) {
  797. tin = tin.replace(/\W/, '');
  798. // Extract date from TIN
  799. var day = tin.slice(0, 2);
  800. if (day !== '32') {
  801. // No date/checksum check if new format
  802. var month = tin.slice(2, 4);
  803. if (month !== '00') {
  804. // No date check if unknown month
  805. var full_year = tin.slice(4, 6);
  806. switch (tin[6]) {
  807. case '0':
  808. full_year = "18".concat(full_year);
  809. break;
  810. case '1':
  811. full_year = "19".concat(full_year);
  812. break;
  813. default:
  814. full_year = "20".concat(full_year);
  815. break;
  816. }
  817. // Check date validity
  818. var date = "".concat(full_year, "/").concat(tin.slice(2, 4), "/").concat(day);
  819. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  820. return false;
  821. }
  822. }
  823. // Calculate check digit
  824. var checksum = 1101;
  825. var multip_lookup = [1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  826. for (var i = 0; i < tin.length - 1; i++) {
  827. checksum -= parseInt(tin[i], 10) * multip_lookup[i];
  828. }
  829. return parseInt(tin[10], 10) === checksum % 11;
  830. }
  831. return true;
  832. }
  833. /*
  834. * mt-MT validation function
  835. * (Identity Card Number or Unique Taxpayer Reference, persons/entities)
  836. * Verify Identity Card Number structure (no other tests found)
  837. */
  838. function mtMtCheck(tin) {
  839. if (tin.length !== 9) {
  840. // No tests for UTR
  841. var chars = tin.toUpperCase().split('');
  842. // Fill with zeros if smaller than proper
  843. while (chars.length < 8) {
  844. chars.unshift(0);
  845. }
  846. // Validate format according to last character
  847. switch (tin[7]) {
  848. case 'A':
  849. case 'P':
  850. if (parseInt(chars[6], 10) === 0) {
  851. return false;
  852. }
  853. break;
  854. default:
  855. {
  856. var first_part = parseInt(chars.join('').slice(0, 5), 10);
  857. if (first_part > 32000) {
  858. return false;
  859. }
  860. var second_part = parseInt(chars.join('').slice(5, 7), 10);
  861. if (first_part === second_part) {
  862. return false;
  863. }
  864. }
  865. }
  866. }
  867. return true;
  868. }
  869. /*
  870. * nl-NL validation function
  871. * (Burgerservicenummer (BSN) or Rechtspersonen Samenwerkingsverbanden Informatie Nummer (RSIN),
  872. * persons/entities respectively)
  873. * Verify TIN validity by calculating check (last) digit (variant of MOD 11)
  874. */
  875. function nlNlCheck(tin) {
  876. return algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(function (a) {
  877. return parseInt(a, 10);
  878. }), 9) % 11 === parseInt(tin[8], 10);
  879. }
  880. /*
  881. * pl-PL validation function
  882. * (Powszechny Elektroniczny System Ewidencji Ludności (PESEL)
  883. * or Numer identyfikacji podatkowej (NIP), persons/entities)
  884. * Verify TIN validity by validating birth date (PESEL) and calculating check (last) digit
  885. */
  886. function plPlCheck(tin) {
  887. // NIP
  888. if (tin.length === 10) {
  889. // Calculate last digit by multiplying with lookup
  890. var lookup = [6, 5, 7, 2, 3, 4, 5, 6, 7];
  891. var _checksum = 0;
  892. for (var i = 0; i < lookup.length; i++) {
  893. _checksum += parseInt(tin[i], 10) * lookup[i];
  894. }
  895. _checksum %= 11;
  896. if (_checksum === 10) {
  897. return false;
  898. }
  899. return _checksum === parseInt(tin[9], 10);
  900. }
  901. // PESEL
  902. // Extract full year using month
  903. var full_year = tin.slice(0, 2);
  904. var month = parseInt(tin.slice(2, 4), 10);
  905. if (month > 80) {
  906. full_year = "18".concat(full_year);
  907. month -= 80;
  908. } else if (month > 60) {
  909. full_year = "22".concat(full_year);
  910. month -= 60;
  911. } else if (month > 40) {
  912. full_year = "21".concat(full_year);
  913. month -= 40;
  914. } else if (month > 20) {
  915. full_year = "20".concat(full_year);
  916. month -= 20;
  917. } else {
  918. full_year = "19".concat(full_year);
  919. }
  920. // Add leading zero to month if needed
  921. if (month < 10) {
  922. month = "0".concat(month);
  923. }
  924. // Check date validity
  925. var date = "".concat(full_year, "/").concat(month, "/").concat(tin.slice(4, 6));
  926. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  927. return false;
  928. }
  929. // Calculate last digit by mulitplying with odd one-digit numbers except 5
  930. var checksum = 0;
  931. var multiplier = 1;
  932. for (var _i7 = 0; _i7 < tin.length - 1; _i7++) {
  933. checksum += parseInt(tin[_i7], 10) * multiplier % 10;
  934. multiplier += 2;
  935. if (multiplier > 10) {
  936. multiplier = 1;
  937. } else if (multiplier === 5) {
  938. multiplier += 2;
  939. }
  940. }
  941. checksum = 10 - checksum % 10;
  942. return checksum === parseInt(tin[10], 10);
  943. }
  944. /*
  945. * pt-BR validation function
  946. * (Cadastro de Pessoas Físicas (CPF, persons)
  947. * Cadastro Nacional de Pessoas Jurídicas (CNPJ, entities)
  948. * Both inputs will be validated
  949. */
  950. function ptBrCheck(tin) {
  951. if (tin.length === 11) {
  952. var _sum;
  953. var remainder;
  954. _sum = 0;
  955. if (
  956. // Reject known invalid CPFs
  957. tin === '11111111111' || tin === '22222222222' || tin === '33333333333' || tin === '44444444444' || tin === '55555555555' || tin === '66666666666' || tin === '77777777777' || tin === '88888888888' || tin === '99999999999' || tin === '00000000000') return false;
  958. for (var i = 1; i <= 9; i++) _sum += parseInt(tin.substring(i - 1, i), 10) * (11 - i);
  959. remainder = _sum * 10 % 11;
  960. if (remainder === 10) remainder = 0;
  961. if (remainder !== parseInt(tin.substring(9, 10), 10)) return false;
  962. _sum = 0;
  963. for (var _i8 = 1; _i8 <= 10; _i8++) _sum += parseInt(tin.substring(_i8 - 1, _i8), 10) * (12 - _i8);
  964. remainder = _sum * 10 % 11;
  965. if (remainder === 10) remainder = 0;
  966. if (remainder !== parseInt(tin.substring(10, 11), 10)) return false;
  967. return true;
  968. }
  969. if (
  970. // Reject know invalid CNPJs
  971. tin === '00000000000000' || tin === '11111111111111' || tin === '22222222222222' || tin === '33333333333333' || tin === '44444444444444' || tin === '55555555555555' || tin === '66666666666666' || tin === '77777777777777' || tin === '88888888888888' || tin === '99999999999999') {
  972. return false;
  973. }
  974. var length = tin.length - 2;
  975. var identifiers = tin.substring(0, length);
  976. var verificators = tin.substring(length);
  977. var sum = 0;
  978. var pos = length - 7;
  979. for (var _i9 = length; _i9 >= 1; _i9--) {
  980. sum += identifiers.charAt(length - _i9) * pos;
  981. pos -= 1;
  982. if (pos < 2) {
  983. pos = 9;
  984. }
  985. }
  986. var result = sum % 11 < 2 ? 0 : 11 - sum % 11;
  987. if (result !== parseInt(verificators.charAt(0), 10)) {
  988. return false;
  989. }
  990. length += 1;
  991. identifiers = tin.substring(0, length);
  992. sum = 0;
  993. pos = length - 7;
  994. for (var _i10 = length; _i10 >= 1; _i10--) {
  995. sum += identifiers.charAt(length - _i10) * pos;
  996. pos -= 1;
  997. if (pos < 2) {
  998. pos = 9;
  999. }
  1000. }
  1001. result = sum % 11 < 2 ? 0 : 11 - sum % 11;
  1002. if (result !== parseInt(verificators.charAt(1), 10)) {
  1003. return false;
  1004. }
  1005. return true;
  1006. }
  1007. /*
  1008. * pt-PT validation function
  1009. * (Número de identificação fiscal (NIF), persons/entities)
  1010. * Verify TIN validity by calculating check (last) digit (variant of MOD 11)
  1011. */
  1012. function ptPtCheck(tin) {
  1013. var checksum = 11 - algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(function (a) {
  1014. return parseInt(a, 10);
  1015. }), 9) % 11;
  1016. if (checksum > 9) {
  1017. return parseInt(tin[8], 10) === 0;
  1018. }
  1019. return checksum === parseInt(tin[8], 10);
  1020. }
  1021. /*
  1022. * ro-RO validation function
  1023. * (Cod Numeric Personal (CNP) or Cod de înregistrare fiscală (CIF),
  1024. * persons only)
  1025. * Verify CNP validity by calculating check (last) digit (test not found for CIF)
  1026. * Material not in DG TAXUD document sourced from:
  1027. * `https://en.wikipedia.org/wiki/National_identification_number#Romania`
  1028. */
  1029. function roRoCheck(tin) {
  1030. if (tin.slice(0, 4) !== '9000') {
  1031. // No test found for this format
  1032. // Extract full year using century digit if possible
  1033. var full_year = tin.slice(1, 3);
  1034. switch (tin[0]) {
  1035. case '1':
  1036. case '2':
  1037. full_year = "19".concat(full_year);
  1038. break;
  1039. case '3':
  1040. case '4':
  1041. full_year = "18".concat(full_year);
  1042. break;
  1043. case '5':
  1044. case '6':
  1045. full_year = "20".concat(full_year);
  1046. break;
  1047. default:
  1048. }
  1049. // Check date validity
  1050. var date = "".concat(full_year, "/").concat(tin.slice(3, 5), "/").concat(tin.slice(5, 7));
  1051. if (date.length === 8) {
  1052. if (!(0, _isDate.default)(date, 'YY/MM/DD')) {
  1053. return false;
  1054. }
  1055. } else if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  1056. return false;
  1057. }
  1058. // Calculate check digit
  1059. var digits = tin.split('').map(function (a) {
  1060. return parseInt(a, 10);
  1061. });
  1062. var multipliers = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9];
  1063. var checksum = 0;
  1064. for (var i = 0; i < multipliers.length; i++) {
  1065. checksum += digits[i] * multipliers[i];
  1066. }
  1067. if (checksum % 11 === 10) {
  1068. return digits[12] === 1;
  1069. }
  1070. return digits[12] === checksum % 11;
  1071. }
  1072. return true;
  1073. }
  1074. /*
  1075. * sk-SK validation function
  1076. * (Rodné číslo (RČ) or bezvýznamové identifikačné číslo (BIČ), persons only)
  1077. * Checks validity of pre-1954 birth numbers (rodné číslo) only
  1078. * Due to the introduction of the pseudo-random BIČ it is not possible to test
  1079. * post-1954 birth numbers without knowing whether they are BIČ or RČ beforehand
  1080. */
  1081. function skSkCheck(tin) {
  1082. if (tin.length === 9) {
  1083. tin = tin.replace(/\W/, '');
  1084. if (tin.slice(6) === '000') {
  1085. return false;
  1086. } // Three-zero serial not assigned before 1954
  1087. // Extract full year from TIN length
  1088. var full_year = parseInt(tin.slice(0, 2), 10);
  1089. if (full_year > 53) {
  1090. return false;
  1091. }
  1092. if (full_year < 10) {
  1093. full_year = "190".concat(full_year);
  1094. } else {
  1095. full_year = "19".concat(full_year);
  1096. }
  1097. // Extract month from TIN and normalize
  1098. var month = parseInt(tin.slice(2, 4), 10);
  1099. if (month > 50) {
  1100. month -= 50;
  1101. }
  1102. if (month < 10) {
  1103. month = "0".concat(month);
  1104. }
  1105. // Check date validity
  1106. var date = "".concat(full_year, "/").concat(month, "/").concat(tin.slice(4, 6));
  1107. if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  1108. return false;
  1109. }
  1110. }
  1111. return true;
  1112. }
  1113. /*
  1114. * sl-SI validation function
  1115. * (Davčna številka, persons/entities)
  1116. * Verify TIN validity by calculating check (last) digit (variant of MOD 11)
  1117. */
  1118. function slSiCheck(tin) {
  1119. var checksum = 11 - algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 7).map(function (a) {
  1120. return parseInt(a, 10);
  1121. }), 8) % 11;
  1122. if (checksum === 10) {
  1123. return parseInt(tin[7], 10) === 0;
  1124. }
  1125. return checksum === parseInt(tin[7], 10);
  1126. }
  1127. /*
  1128. * sv-SE validation function
  1129. * (Personnummer or samordningsnummer, persons only)
  1130. * Checks validity of birth date and calls luhnCheck() to validate check (last) digit
  1131. */
  1132. function svSeCheck(tin) {
  1133. // Make copy of TIN and normalize to two-digit year form
  1134. var tin_copy = tin.slice(0);
  1135. if (tin.length > 11) {
  1136. tin_copy = tin_copy.slice(2);
  1137. }
  1138. // Extract date of birth
  1139. var full_year = '';
  1140. var month = tin_copy.slice(2, 4);
  1141. var day = parseInt(tin_copy.slice(4, 6), 10);
  1142. if (tin.length > 11) {
  1143. full_year = tin.slice(0, 4);
  1144. } else {
  1145. full_year = tin.slice(0, 2);
  1146. if (tin.length === 11 && day < 60) {
  1147. // Extract full year from centenarian symbol
  1148. // Should work just fine until year 10000 or so
  1149. var current_year = new Date().getFullYear().toString();
  1150. var current_century = parseInt(current_year.slice(0, 2), 10);
  1151. current_year = parseInt(current_year, 10);
  1152. if (tin[6] === '-') {
  1153. if (parseInt("".concat(current_century).concat(full_year), 10) > current_year) {
  1154. full_year = "".concat(current_century - 1).concat(full_year);
  1155. } else {
  1156. full_year = "".concat(current_century).concat(full_year);
  1157. }
  1158. } else {
  1159. full_year = "".concat(current_century - 1).concat(full_year);
  1160. if (current_year - parseInt(full_year, 10) < 100) {
  1161. return false;
  1162. }
  1163. }
  1164. }
  1165. }
  1166. // Normalize day and check date validity
  1167. if (day > 60) {
  1168. day -= 60;
  1169. }
  1170. if (day < 10) {
  1171. day = "0".concat(day);
  1172. }
  1173. var date = "".concat(full_year, "/").concat(month, "/").concat(day);
  1174. if (date.length === 8) {
  1175. if (!(0, _isDate.default)(date, 'YY/MM/DD')) {
  1176. return false;
  1177. }
  1178. } else if (!(0, _isDate.default)(date, 'YYYY/MM/DD')) {
  1179. return false;
  1180. }
  1181. return algorithms.luhnCheck(tin.replace(/\W/, ''));
  1182. }
  1183. /**
  1184. * uk-UA validation function
  1185. * Verify TIN validity by calculating check (last) digit (variant of MOD 11)
  1186. */
  1187. function ukUaCheck(tin) {
  1188. // Calculate check digit
  1189. var digits = tin.split('').map(function (a) {
  1190. return parseInt(a, 10);
  1191. });
  1192. var multipliers = [-1, 5, 7, 9, 4, 6, 10, 5, 7];
  1193. var checksum = 0;
  1194. for (var i = 0; i < multipliers.length; i++) {
  1195. checksum += digits[i] * multipliers[i];
  1196. }
  1197. return checksum % 11 === 10 ? digits[9] === 0 : digits[9] === checksum % 11;
  1198. }
  1199. // Locale lookup objects
  1200. /*
  1201. * Tax id regex formats for various locales
  1202. *
  1203. * Where not explicitly specified in DG-TAXUD document both
  1204. * uppercase and lowercase letters are acceptable.
  1205. */
  1206. var taxIdFormat = {
  1207. 'bg-BG': /^\d{10}$/,
  1208. 'cs-CZ': /^\d{6}\/{0,1}\d{3,4}$/,
  1209. 'de-AT': /^\d{9}$/,
  1210. 'de-DE': /^[1-9]\d{10}$/,
  1211. 'dk-DK': /^\d{6}-{0,1}\d{4}$/,
  1212. 'el-CY': /^[09]\d{7}[A-Z]$/,
  1213. 'el-GR': /^([0-4]|[7-9])\d{8}$/,
  1214. 'en-CA': /^\d{9}$/,
  1215. 'en-GB': /^\d{10}$|^(?!GB|NK|TN|ZZ)(?![DFIQUV])[A-Z](?![DFIQUVO])[A-Z]\d{6}[ABCD ]$/i,
  1216. 'en-IE': /^\d{7}[A-W][A-IW]{0,1}$/i,
  1217. 'en-US': /^\d{2}[- ]{0,1}\d{7}$/,
  1218. 'es-AR': /(20|23|24|27|30|33|34)[0-9]{8}[0-9]/,
  1219. 'es-ES': /^(\d{0,8}|[XYZKLM]\d{7})[A-HJ-NP-TV-Z]$/i,
  1220. 'et-EE': /^[1-6]\d{6}(00[1-9]|0[1-9][0-9]|[1-6][0-9]{2}|70[0-9]|710)\d$/,
  1221. 'fi-FI': /^\d{6}[-+A]\d{3}[0-9A-FHJ-NPR-Y]$/i,
  1222. 'fr-BE': /^\d{11}$/,
  1223. 'fr-FR': /^[0-3]\d{12}$|^[0-3]\d\s\d{2}(\s\d{3}){3}$/,
  1224. // Conforms both to official spec and provided example
  1225. 'fr-LU': /^\d{13}$/,
  1226. 'hr-HR': /^\d{11}$/,
  1227. 'hu-HU': /^8\d{9}$/,
  1228. 'it-IT': /^[A-Z]{6}[L-NP-V0-9]{2}[A-EHLMPRST][L-NP-V0-9]{2}[A-ILMZ][L-NP-V0-9]{3}[A-Z]$/i,
  1229. 'lv-LV': /^\d{6}-{0,1}\d{5}$/,
  1230. // Conforms both to DG TAXUD spec and original research
  1231. 'mt-MT': /^\d{3,7}[APMGLHBZ]$|^([1-8])\1\d{7}$/i,
  1232. 'nl-NL': /^\d{9}$/,
  1233. 'pl-PL': /^\d{10,11}$/,
  1234. 'pt-BR': /(?:^\d{11}$)|(?:^\d{14}$)/,
  1235. 'pt-PT': /^\d{9}$/,
  1236. 'ro-RO': /^\d{13}$/,
  1237. 'sk-SK': /^\d{6}\/{0,1}\d{3,4}$/,
  1238. 'sl-SI': /^[1-9]\d{7}$/,
  1239. 'sv-SE': /^(\d{6}[-+]{0,1}\d{4}|(18|19|20)\d{6}[-+]{0,1}\d{4})$/,
  1240. 'uk-UA': /^\d{10}$/
  1241. };
  1242. // taxIdFormat locale aliases
  1243. taxIdFormat['lb-LU'] = taxIdFormat['fr-LU'];
  1244. taxIdFormat['lt-LT'] = taxIdFormat['et-EE'];
  1245. taxIdFormat['nl-BE'] = taxIdFormat['fr-BE'];
  1246. taxIdFormat['fr-CA'] = taxIdFormat['en-CA'];
  1247. // Algorithmic tax id check functions for various locales
  1248. var taxIdCheck = {
  1249. 'bg-BG': bgBgCheck,
  1250. 'cs-CZ': csCzCheck,
  1251. 'de-AT': deAtCheck,
  1252. 'de-DE': deDeCheck,
  1253. 'dk-DK': dkDkCheck,
  1254. 'el-CY': elCyCheck,
  1255. 'el-GR': elGrCheck,
  1256. 'en-CA': isCanadianSIN,
  1257. 'en-IE': enIeCheck,
  1258. 'en-US': enUsCheck,
  1259. 'es-AR': esArCheck,
  1260. 'es-ES': esEsCheck,
  1261. 'et-EE': etEeCheck,
  1262. 'fi-FI': fiFiCheck,
  1263. 'fr-BE': frBeCheck,
  1264. 'fr-FR': frFrCheck,
  1265. 'fr-LU': frLuCheck,
  1266. 'hr-HR': hrHrCheck,
  1267. 'hu-HU': huHuCheck,
  1268. 'it-IT': itItCheck,
  1269. 'lv-LV': lvLvCheck,
  1270. 'mt-MT': mtMtCheck,
  1271. 'nl-NL': nlNlCheck,
  1272. 'pl-PL': plPlCheck,
  1273. 'pt-BR': ptBrCheck,
  1274. 'pt-PT': ptPtCheck,
  1275. 'ro-RO': roRoCheck,
  1276. 'sk-SK': skSkCheck,
  1277. 'sl-SI': slSiCheck,
  1278. 'sv-SE': svSeCheck,
  1279. 'uk-UA': ukUaCheck
  1280. };
  1281. // taxIdCheck locale aliases
  1282. taxIdCheck['lb-LU'] = taxIdCheck['fr-LU'];
  1283. taxIdCheck['lt-LT'] = taxIdCheck['et-EE'];
  1284. taxIdCheck['nl-BE'] = taxIdCheck['fr-BE'];
  1285. taxIdCheck['fr-CA'] = taxIdCheck['en-CA'];
  1286. // Regexes for locales where characters should be omitted before checking format
  1287. var allsymbols = /[-\\\/!@#$%\^&\*\(\)\+\=\[\]]+/g;
  1288. var sanitizeRegexes = {
  1289. 'de-AT': allsymbols,
  1290. 'de-DE': /[\/\\]/g,
  1291. 'fr-BE': allsymbols
  1292. };
  1293. // sanitizeRegexes locale aliases
  1294. sanitizeRegexes['nl-BE'] = sanitizeRegexes['fr-BE'];
  1295. /*
  1296. * Validator function
  1297. * Return true if the passed string is a valid tax identification number
  1298. * for the specified locale.
  1299. * Throw an error exception if the locale is not supported.
  1300. */
  1301. function isTaxID(str) {
  1302. var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'en-US';
  1303. (0, _assertString.default)(str);
  1304. // Copy TIN to avoid replacement if sanitized
  1305. var strcopy = str.slice(0);
  1306. if (locale in taxIdFormat) {
  1307. if (locale in sanitizeRegexes) {
  1308. strcopy = strcopy.replace(sanitizeRegexes[locale], '');
  1309. }
  1310. if (!taxIdFormat[locale].test(strcopy)) {
  1311. return false;
  1312. }
  1313. if (locale in taxIdCheck) {
  1314. return taxIdCheck[locale](strcopy);
  1315. }
  1316. // Fallthrough; not all locales have algorithmic checks
  1317. return true;
  1318. }
  1319. throw new Error("Invalid locale '".concat(locale, "'"));
  1320. }
  1321. module.exports = exports.default;
  1322. module.exports.default = exports.default;