From 98d5b3767af80ed9adac9031c1c372965eed5a64 Mon Sep 17 00:00:00 2001 From: vfarylevych Date: Sat, 13 Jan 2024 16:40:11 +0200 Subject: [PATCH] feat(isTaxID): added TaxID for Ukraine uk-UA --- README.md | 2 +- src/lib/isTaxID.js | 17 +++++++++++++++++ test/validators.test.js | 13 +++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e00b7cfac..bbe1f1259 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ Validator | Description **isSlug(str)** | check if the string is of type slug. **isStrongPassword(str [, options])** | check if the string can be considered a strong password or not. Allows for custom requirements or scoring rules. If `returnScore` is true, then the function returns an integer score for the password rather than a boolean.
Default options:
`{ minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1, returnScore: false, pointsPerUnique: 1, pointsPerRepeat: 0.5, pointsForContainingLower: 10, pointsForContainingUpper: 10, pointsForContainingNumber: 10, pointsForContainingSymbol: 10 }` **isTime(str [, options])** | check if the string is a valid time e.g. [`23:01:59`, new Date().toLocaleTimeString()].

`options` is an object which can contain the keys `hourFormat` or `mode`.

`hourFormat` is a key and defaults to `'hour24'`.

`mode` is a key and defaults to `'default'`.

`hourFomat` can contain the values `'hour12'` or `'hour24'`, `'hour24'` will validate hours in 24 format and `'hour12'` will validate hours in 12 format.

`mode` can contain the values `'default'` or `'withSeconds'`, `'default'` will validate `HH:MM` format, `'withSeconds'` will validate the `HH:MM:SS` format. -**isTaxID(str, locale)** | check if the string is a valid Tax Identification Number. Default locale is `en-US`.

More info about exact TIN support can be found in `src/lib/isTaxID.js`.

Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-AR', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV', 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE' ]`. +**isTaxID(str, locale)** | check if the string is a valid Tax Identification Number. Default locale is `en-US`.

More info about exact TIN support can be found in `src/lib/isTaxID.js`.

Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-AR', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV', 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE', 'uk-UA']`. **isURL(str [, options])** | check if the string is a URL.

`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_port: false, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, allow_fragments: true, allow_query_components: true, disallow_auth: false, validate_length: true }`.

`require_protocol` - if set to true isURL will return false if protocol is not present in the URL.
`require_valid_protocol` - isURL will check if the URL's protocol is present in the protocols option.
`protocols` - valid protocols can be modified with this option.
`require_host` - if set to false isURL will not check if host is present in the URL.
`require_port` - if set to true isURL will check if port is present in the URL.
`allow_protocol_relative_urls` - if set to true protocol relative URLs will be allowed.
`allow_fragments` - if set to false isURL will return false if fragments are present.
`allow_query_components` - if set to false isURL will return false if query components are present.
`validate_length` - if set to false isURL will skip string length validation (2083 characters is IE max URL length). **isUUID(str [, version])** | check if the string is a UUID (version 1, 2, 3, 4 or 5). **isVariableWidth(str)** | check if the string contains a mixture of full and half-width chars. diff --git a/src/lib/isTaxID.js b/src/lib/isTaxID.js index b82156ed1..d13229f69 100644 --- a/src/lib/isTaxID.js +++ b/src/lib/isTaxID.js @@ -1141,6 +1141,21 @@ function svSeCheck(tin) { return algorithms.luhnCheck(tin.replace(/\W/, '')); } +/** + * uk-UA validation function + * Verify TIN validity by calculating check (last) digit (variant of MOD 11) + */ +function ukUaCheck(tin) { + // Calculate check digit + const digits = tin.split('').map(a => parseInt(a, 10)); + const multipliers = [-1, 5, 7, 9, 4, 6, 10, 5, 7]; + let checksum = 0; + for (let i = 0; i < multipliers.length; i++) { + checksum += digits[i] * multipliers[i]; + } + return checksum % 11 === 10 ? digits[9] === 0 : digits[9] === checksum % 11; +} + // Locale lookup objects /* @@ -1181,6 +1196,7 @@ const taxIdFormat = { 'sk-SK': /^\d{6}\/{0,1}\d{3,4}$/, 'sl-SI': /^[1-9]\d{7}$/, 'sv-SE': /^(\d{6}[-+]{0,1}\d{4}|(18|19|20)\d{6}[-+]{0,1}\d{4})$/, + 'uk-UA': /^\d{10}$/, }; // taxIdFormat locale aliases taxIdFormat['lb-LU'] = taxIdFormat['fr-LU']; @@ -1220,6 +1236,7 @@ const taxIdCheck = { 'sk-SK': skSkCheck, 'sl-SI': slSiCheck, 'sv-SE': svSeCheck, + 'uk-UA': ukUaCheck, }; // taxIdCheck locale aliases taxIdCheck['lb-LU'] = taxIdCheck['fr-LU']; diff --git a/test/validators.test.js b/test/validators.test.js index 6c68cd71a..beea8660f 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -12827,6 +12827,19 @@ describe('Validators', () => { '19640823-32333', '1964082332333'], }); + test({ + validator: 'isTaxID', + args: ['uk-UA'], + valid: [ + '3006321856', + '3003102490', + '2164212906'], + invalid: [ + '2565975632', + '256597563287', + 'КС00123456', + '2896235845'], + }); test({ validator: 'isTaxID', valid: [