isVAT.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. import assertString from './util/assertString';
  2. import * as algorithms from './util/algorithms';
  3. var CH = function CH(str) {
  4. // @see {@link https://www.ech.ch/de/ech/ech-0097/5.2.0}
  5. var hasValidCheckNumber = function hasValidCheckNumber(digits) {
  6. var lastDigit = digits.pop(); // used as check number
  7. var weights = [5, 4, 3, 2, 7, 6, 5, 4];
  8. var calculatedCheckNumber = (11 - digits.reduce(function (acc, el, idx) {
  9. return acc + el * weights[idx];
  10. }, 0) % 11) % 11;
  11. return lastDigit === calculatedCheckNumber;
  12. }; // @see {@link https://www.estv.admin.ch/estv/de/home/mehrwertsteuer/uid/mwst-uid-nummer.html}
  13. return /^(CHE[- ]?)?(\d{9}|(\d{3}\.\d{3}\.\d{3})|(\d{3} \d{3} \d{3})) ?(TVA|MWST|IVA)?$/.test(str) && hasValidCheckNumber(str.match(/\d/g).map(function (el) {
  14. return +el;
  15. }));
  16. };
  17. var PT = function PT(str) {
  18. var match = str.match(/^(PT)?(\d{9})$/);
  19. if (!match) {
  20. return false;
  21. }
  22. var tin = match[2];
  23. var checksum = 11 - algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(function (a) {
  24. return parseInt(a, 10);
  25. }), 9) % 11;
  26. if (checksum > 9) {
  27. return parseInt(tin[8], 10) === 0;
  28. }
  29. return checksum === parseInt(tin[8], 10);
  30. };
  31. export var vatMatchers = {
  32. /**
  33. * European Union VAT identification numbers
  34. */
  35. AT: function AT(str) {
  36. return /^(AT)?U\d{8}$/.test(str);
  37. },
  38. BE: function BE(str) {
  39. return /^(BE)?\d{10}$/.test(str);
  40. },
  41. BG: function BG(str) {
  42. return /^(BG)?\d{9,10}$/.test(str);
  43. },
  44. HR: function HR(str) {
  45. return /^(HR)?\d{11}$/.test(str);
  46. },
  47. CY: function CY(str) {
  48. return /^(CY)?\w{9}$/.test(str);
  49. },
  50. CZ: function CZ(str) {
  51. return /^(CZ)?\d{8,10}$/.test(str);
  52. },
  53. DK: function DK(str) {
  54. return /^(DK)?\d{8}$/.test(str);
  55. },
  56. EE: function EE(str) {
  57. return /^(EE)?\d{9}$/.test(str);
  58. },
  59. FI: function FI(str) {
  60. return /^(FI)?\d{8}$/.test(str);
  61. },
  62. FR: function FR(str) {
  63. return /^(FR)?\w{2}\d{9}$/.test(str);
  64. },
  65. DE: function DE(str) {
  66. return /^(DE)?\d{9}$/.test(str);
  67. },
  68. EL: function EL(str) {
  69. return /^(EL)?\d{9}$/.test(str);
  70. },
  71. HU: function HU(str) {
  72. return /^(HU)?\d{8}$/.test(str);
  73. },
  74. IE: function IE(str) {
  75. return /^(IE)?\d{7}\w{1}(W)?$/.test(str);
  76. },
  77. IT: function IT(str) {
  78. return /^(IT)?\d{11}$/.test(str);
  79. },
  80. LV: function LV(str) {
  81. return /^(LV)?\d{11}$/.test(str);
  82. },
  83. LT: function LT(str) {
  84. return /^(LT)?\d{9,12}$/.test(str);
  85. },
  86. LU: function LU(str) {
  87. return /^(LU)?\d{8}$/.test(str);
  88. },
  89. MT: function MT(str) {
  90. return /^(MT)?\d{8}$/.test(str);
  91. },
  92. NL: function NL(str) {
  93. return /^(NL)?\d{9}B\d{2}$/.test(str);
  94. },
  95. PL: function PL(str) {
  96. return /^(PL)?(\d{10}|(\d{3}-\d{3}-\d{2}-\d{2})|(\d{3}-\d{2}-\d{2}-\d{3}))$/.test(str);
  97. },
  98. PT: PT,
  99. RO: function RO(str) {
  100. return /^(RO)?\d{2,10}$/.test(str);
  101. },
  102. SK: function SK(str) {
  103. return /^(SK)?\d{10}$/.test(str);
  104. },
  105. SI: function SI(str) {
  106. return /^(SI)?\d{8}$/.test(str);
  107. },
  108. ES: function ES(str) {
  109. return /^(ES)?\w\d{7}[A-Z]$/.test(str);
  110. },
  111. SE: function SE(str) {
  112. return /^(SE)?\d{12}$/.test(str);
  113. },
  114. /**
  115. * VAT numbers of non-EU countries
  116. */
  117. AL: function AL(str) {
  118. return /^(AL)?\w{9}[A-Z]$/.test(str);
  119. },
  120. MK: function MK(str) {
  121. return /^(MK)?\d{13}$/.test(str);
  122. },
  123. AU: function AU(str) {
  124. return /^(AU)?\d{11}$/.test(str);
  125. },
  126. BY: function BY(str) {
  127. return /^(УНП )?\d{9}$/.test(str);
  128. },
  129. CA: function CA(str) {
  130. return /^(CA)?\d{9}$/.test(str);
  131. },
  132. IS: function IS(str) {
  133. return /^(IS)?\d{5,6}$/.test(str);
  134. },
  135. IN: function IN(str) {
  136. return /^(IN)?\d{15}$/.test(str);
  137. },
  138. ID: function ID(str) {
  139. return /^(ID)?(\d{15}|(\d{2}.\d{3}.\d{3}.\d{1}-\d{3}.\d{3}))$/.test(str);
  140. },
  141. IL: function IL(str) {
  142. return /^(IL)?\d{9}$/.test(str);
  143. },
  144. KZ: function KZ(str) {
  145. return /^(KZ)?\d{9}$/.test(str);
  146. },
  147. NZ: function NZ(str) {
  148. return /^(NZ)?\d{9}$/.test(str);
  149. },
  150. NG: function NG(str) {
  151. return /^(NG)?(\d{12}|(\d{8}-\d{4}))$/.test(str);
  152. },
  153. NO: function NO(str) {
  154. return /^(NO)?\d{9}MVA$/.test(str);
  155. },
  156. PH: function PH(str) {
  157. return /^(PH)?(\d{12}|\d{3} \d{3} \d{3} \d{3})$/.test(str);
  158. },
  159. RU: function RU(str) {
  160. return /^(RU)?(\d{10}|\d{12})$/.test(str);
  161. },
  162. SM: function SM(str) {
  163. return /^(SM)?\d{5}$/.test(str);
  164. },
  165. SA: function SA(str) {
  166. return /^(SA)?\d{15}$/.test(str);
  167. },
  168. RS: function RS(str) {
  169. return /^(RS)?\d{9}$/.test(str);
  170. },
  171. CH: CH,
  172. TR: function TR(str) {
  173. return /^(TR)?\d{10}$/.test(str);
  174. },
  175. UA: function UA(str) {
  176. return /^(UA)?\d{12}$/.test(str);
  177. },
  178. GB: function GB(str) {
  179. return /^GB((\d{3} \d{4} ([0-8][0-9]|9[0-6]))|(\d{9} \d{3})|(((GD[0-4])|(HA[5-9]))[0-9]{2}))$/.test(str);
  180. },
  181. UZ: function UZ(str) {
  182. return /^(UZ)?\d{9}$/.test(str);
  183. },
  184. /**
  185. * VAT numbers of Latin American countries
  186. */
  187. AR: function AR(str) {
  188. return /^(AR)?\d{11}$/.test(str);
  189. },
  190. BO: function BO(str) {
  191. return /^(BO)?\d{7}$/.test(str);
  192. },
  193. BR: function BR(str) {
  194. return /^(BR)?((\d{2}.\d{3}.\d{3}\/\d{4}-\d{2})|(\d{3}.\d{3}.\d{3}-\d{2}))$/.test(str);
  195. },
  196. CL: function CL(str) {
  197. return /^(CL)?\d{8}-\d{1}$/.test(str);
  198. },
  199. CO: function CO(str) {
  200. return /^(CO)?\d{10}$/.test(str);
  201. },
  202. CR: function CR(str) {
  203. return /^(CR)?\d{9,12}$/.test(str);
  204. },
  205. EC: function EC(str) {
  206. return /^(EC)?\d{13}$/.test(str);
  207. },
  208. SV: function SV(str) {
  209. return /^(SV)?\d{4}-\d{6}-\d{3}-\d{1}$/.test(str);
  210. },
  211. GT: function GT(str) {
  212. return /^(GT)?\d{7}-\d{1}$/.test(str);
  213. },
  214. HN: function HN(str) {
  215. return /^(HN)?$/.test(str);
  216. },
  217. MX: function MX(str) {
  218. return /^(MX)?\w{3,4}\d{6}\w{3}$/.test(str);
  219. },
  220. NI: function NI(str) {
  221. return /^(NI)?\d{3}-\d{6}-\d{4}\w{1}$/.test(str);
  222. },
  223. PA: function PA(str) {
  224. return /^(PA)?$/.test(str);
  225. },
  226. PY: function PY(str) {
  227. return /^(PY)?\d{6,8}-\d{1}$/.test(str);
  228. },
  229. PE: function PE(str) {
  230. return /^(PE)?\d{11}$/.test(str);
  231. },
  232. DO: function DO(str) {
  233. return /^(DO)?(\d{11}|(\d{3}-\d{7}-\d{1})|[1,4,5]{1}\d{8}|([1,4,5]{1})-\d{2}-\d{5}-\d{1})$/.test(str);
  234. },
  235. UY: function UY(str) {
  236. return /^(UY)?\d{12}$/.test(str);
  237. },
  238. VE: function VE(str) {
  239. return /^(VE)?[J,G,V,E]{1}-(\d{9}|(\d{8}-\d{1}))$/.test(str);
  240. }
  241. };
  242. export default function isVAT(str, countryCode) {
  243. assertString(str);
  244. assertString(countryCode);
  245. if (countryCode in vatMatchers) {
  246. return vatMatchers[countryCode](str);
  247. }
  248. throw new Error("Invalid country code: '".concat(countryCode, "'"));
  249. }