isTaxID.js 42 KB

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