From d0ee78c017a259bb7ed14946be857ae9fca9027c Mon Sep 17 00:00:00 2001 From: vegandiet705 Date: Sat, 18 May 2024 02:32:05 +0200 Subject: [PATCH] fix: fixing many special cases --- README.md | 121 +++++++++++++++++++++++++++++++ src/country.ts | 2 - src/specialCaseValidator.ts | 35 +++++---- test/postalCodeValidator.test.ts | 4 +- test/utils.ts | 11 ++- 5 files changed, 149 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e69de29..c5a2c2c 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,121 @@ +## :toolbox: Functions + +- [isValidCountryVat](#gear-isvalidcountryvat) +- [isValidVat](#gear-isvalidvat) + +### :gear: isValidCountryVat + +| Function | Type | +| ---------- | ---------- | +| `isValidCountryVat` | `(vat: string, country: Country) => boolean` | + +### :gear: isValidVat + +| Function | Type | +| ---------- | ---------- | +| `isValidVat` | `(vat: string) => boolean` | + + +## :wrench: Constants + +- [countryRegexMap](#gear-countryregexmap) +- [countrySpecialCaseMap](#gear-countryspecialcasemap) + +### :gear: countryRegexMap + +| Constant | Type | +| ---------- | ---------- | +| `countryRegexMap` | `Map` | + +### :gear: countrySpecialCaseMap + +| Constant | Type | +| ---------- | ---------- | +| `countrySpecialCaseMap` | `Map boolean>` | + + + +## :nut_and_bolt: Enum + +- [Country](#gear-country) + +### :gear: Country + + + +| Property | Type | Description | +| ---------- | ---------- | ---------- | +| `Albania` | `'Albania'` | | +| `Argentina` | `'Argentina'` | | +| `Australia` | `'Australia'` | | +| `Austria` | `'Austria'` | | +| `Belarus` | `'Belarus'` | | +| `Belgium` | `'Belgium'` | | +| `Belize` | `'Belize'` | | +| `Bolivia` | `'Bolivia'` | | +| `BosniaHerzegovina` | `'Bosnia Herzegovina'` | | +| `Brazil` | `'Brazil'` | | +| `Bulgaria` | `'Bulgaria'` | | +| `Canada` | `'Canada'` | | +| `Chile` | `'Chile'` | | +| `China` | `'China'` | | +| `Colombia` | `'Colombia'` | | +| `CostaRica` | `'Costa Rica'` | | +| `Croatia` | `'Croatia'` | | +| `Cyprus` | `'Cyprus'` | | +| `CzechRepublic` | `'Czech Republic'` | | +| `Denmark` | `'Denmark'` | | +| `DominicanRepublic` | `'Dominican Republic'` | | +| `Ecuador` | `'Ecuador'` | | +| `ElSalvador` | `'El Salvador'` | | +| `Estonia` | `'Estonia'` | | +| `Finland` | `'Finland'` | | +| `France` | `'France'` | | +| `Germany` | `'Germany'` | | +| `Greece` | `'Greece'` | | +| `Guatemala` | `'Guatemala'` | | +| `Hungary` | `'Hungary'` | | +| `Iceland` | `'Iceland'` | | +| `India` | `'India'` | | +| `Indonesia` | `'Indonesia'` | | +| `Ireland` | `'Ireland'` | | +| `IsleOfMan` | `'Isle of Man'` | | +| `Israel` | `'Israel'` | | +| `Italy` | `'Italy'` | | +| `Japan` | `'Japan'` | | +| `Kazakhstan` | `'Kazakhstan'` | | +| `Latvia` | `'Latvia'` | | +| `Lithuania` | `'Lithuania'` | | +| `Luxembourg` | `'Luxembourg'` | | +| `Malta` | `'Malta'` | | +| `Mexico` | `'Mexico'` | | +| `Monaco` | `'Monaco'` | | +| `Netherlands` | `'Netherlands'` | | +| `NewZealand` | `'New Zealand'` | | +| `Nicaragua` | `'Nicaragua'` | | +| `Nigeria` | `'Nigeria'` | | +| `NorthMacedonia` | `'North Macedonia'` | | +| `Norway` | `'Norway'` | | +| `Paraguay` | `'Paraguay'` | | +| `Peru` | `'Peru'` | | +| `Philippines` | `'Philippines'` | | +| `Poland` | `'Poland'` | | +| `Portugal` | `'Portugal'` | | +| `Romania` | `'Romania'` | | +| `Russia` | `'Russia'` | | +| `SanMarino` | `'San Marino'` | | +| `SaudiArabia` | `'Saudi Arabia'` | | +| `Serbia` | `'Serbia'` | | +| `Slovakia` | `'Slovakia'` | | +| `Slovenia` | `'Slovenia'` | | +| `Spain` | `'Spain'` | | +| `Sweden` | `'Sweden'` | | +| `Switzerland` | `'Switzerland'` | | +| `Taiwan` | `'Taiwan'` | | +| `Turkey` | `'Turkey'` | | +| `Ukraine` | `'Ukraine'` | | +| `UnitedKingdom` | `'United Kingdom'` | | +| `Uruguay` | `'Uruguay'` | | +| `Uzbekistan` | `'Uzbekistan'` | | +| `Venezuela` | `'Venezuela'` | | + diff --git a/src/country.ts b/src/country.ts index 0ee4925..2e73798 100644 --- a/src/country.ts +++ b/src/country.ts @@ -28,7 +28,6 @@ export enum Country { Germany = 'Germany', Greece = 'Greece', Guatemala = 'Guatemala', - Honduras = 'Honduras', Hungary = 'Hungary', Iceland = 'Iceland', India = 'India', @@ -51,7 +50,6 @@ export enum Country { Nigeria = 'Nigeria', NorthMacedonia = 'North Macedonia', Norway = 'Norway', - Panama = 'Panama', Paraguay = 'Paraguay', Peru = 'Peru', Philippines = 'Philippines', diff --git a/src/specialCaseValidator.ts b/src/specialCaseValidator.ts index f2312e3..d0a733c 100644 --- a/src/specialCaseValidator.ts +++ b/src/specialCaseValidator.ts @@ -67,18 +67,20 @@ function validateAustralianVat(vat: string): boolean { return false; } - const identifier = vat.substring(0, 9); - const checkDigits = vat.substring(9); - let total = 0; + const number = vat.slice(2); + const checkDigit = vat.slice(0, 2); + const weights = [3, 5, 7, 9, 11, 13, 15, 17, 19]; + let sum = 0 - for (let i = 0; i < identifier.length; i++) { - const digit = parseInt(identifier[i]); - total = (total * 10 + digit) % 89; + for (let i = 0; i < weights.length; ++i) { + sum += (-weights[i] * parseInt(number.charAt(i))); } - const calculatedCheckDigits = total.toString().padStart(2, '0'); + const modResult = (sum - 1) % 89; + const positiveModResult = modResult < 0 ? modResult + 89 : modResult; + const expectedCheckDigit = String(11 + positiveModResult); - return calculatedCheckDigits === checkDigits; + return checkDigit === expectedCheckDigit; } function validateIsraeliVat(vat: string): boolean { @@ -355,9 +357,8 @@ function validateDominicanRepublicVat(vat: string): boolean { return false; } - const checkDigit = vat.charAt(10); - const digits = vat.slice(0, 9); - + const checkDigit = vat.charAt(8); + const digits = vat.slice(0, 8); const weights = [7, 9, 8, 6, 5, 4, 3, 2]; let sum = 0; @@ -366,7 +367,10 @@ function validateDominicanRepublicVat(vat: string): boolean { } const remainder = sum % 11; - const calculatedCheckDigit = ((10 - remainder) % 9) + 1; + const result = 10 - remainder; + const positiveModResult = ((result % 9) + 9) % 9; + const calculatedCheckDigit = positiveModResult + 1; + return parseInt(checkDigit) === calculatedCheckDigit; } @@ -387,7 +391,9 @@ function validateParaguayVat(vat: string): boolean { sum += (i + 2) * parseInt(digits.charAt(digits.length - i - 1)); } - const calculatedCheckDigit = String((-sum % 11) % 10); + const mod11 = ((-sum % 11) + 11) % 11; + const mod10 = (mod11 % 10 + 10) % 10; + const calculatedCheckDigit = String(mod10); return checkDigit === calculatedCheckDigit; } @@ -427,7 +433,8 @@ function validateUruguayanVat(vat: string): boolean { const digit = parseInt(number.charAt(index)); return sum + digit * weight; }, 0); - const calculatedCheckDigit = (-total % 11).toString(); + const mod11 = ((-total % 11) + 11) % 11; + const calculatedCheckDigit = mod11.toString(); const providedCheckDigit = vat.charAt(11); return calculatedCheckDigit === providedCheckDigit; diff --git a/test/postalCodeValidator.test.ts b/test/postalCodeValidator.test.ts index 88185e8..af74a24 100644 --- a/test/postalCodeValidator.test.ts +++ b/test/postalCodeValidator.test.ts @@ -8,7 +8,7 @@ import { describe('isValidCountryVat', () => { test.each(validVats)( - 'returns true for valid VAT number in specified country', + 'returns true for valid VAT number in test %s', (entry) => { const result = isValidCountryVat(entry.vat, entry.country); expect(result).toBe(true); @@ -16,7 +16,7 @@ describe('isValidCountryVat', () => { ); test.each(invalidVats)( - 'returns false for invalid VAT number in specified country', + 'returns false for invalid VAT number in test %s', (entry) => { const result = isValidCountryVat(entry.vat, entry.country); expect(result).toBe(false); diff --git a/test/utils.ts b/test/utils.ts index 7881dc5..c7fe7c8 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,19 +1,19 @@ import { Country } from '../src/country'; export const validVats: { country: Country; vat: string }[] = [ - { vat: 'IT12345678901', country: Country.Italy }, + { vat: 'IT00743110157', country: Country.Italy }, { vat: 'NL999999999B01', country: Country.Netherlands }, { vat: 'PL9999999999', country: Country.Poland }, { vat: 'PL999-999-99-99', country: Country.Poland }, { vat: 'PL999-99-99-999', country: Country.Poland }, - { vat: 'SK1234567890', country: Country.Slovakia }, + { vat: 'SK2022749619', country: Country.Slovakia }, { vat: 'SI99999999', country: Country.Slovenia }, { vat: 'ESX99999999', country: Country.Spain }, { vat: 'ESX9999999R', country: Country.Spain }, { vat: 'SE999999999901', country: Country.Sweden }, { vat: 'K99999999L', country: Country.Albania }, { vat: 'L99999999G', country: Country.Albania }, - { vat: '12345678901', country: Country.Australia }, + { vat: '83914571673', country: Country.Australia }, { vat: '123456789', country: Country.Canada }, { vat: '91310000717860841G', country: Country.China }, { vat: '123456', country: Country.Iceland }, @@ -43,7 +43,7 @@ export const validVats: { country: Country; vat: string }[] = [ { vat: '18609823-4', country: Country.Chile }, { vat: '12391279-9', country: Country.Chile }, { vat: '623456789-1', country: Country.Colombia }, - { vat: '130002458', country: Country.DominicanRepublic }, + { vat: '101850043', country: Country.DominicanRepublic }, { vat: '0614-050707-104-8', country: Country.ElSalvador }, { vat: '0614-241287-102-5', country: Country.ElSalvador }, { vat: '1234567-1', country: Country.Guatemala }, @@ -53,7 +53,6 @@ export const validVats: { country: Country; vat: string }[] = [ { vat: '20512333797', country: Country.Peru }, { vat: '211003420017', country: Country.Uruguay }, { vat: 'V-114702834', country: Country.Venezuela }, - { vat: 'J-305959918', country: Country.Venezuela }, ]; export const invalidVats: { country: Country; vat: string }[] = [ @@ -62,4 +61,4 @@ export const invalidVats: { country: Country; vat: string }[] = [ export const validVatsArray = ['22150']; -export const invalidVatsArray = ['abcdef']; +export const invalidVatsArray = ['1YUIY65465HGFHYIUY6656'];