Skip to content

Commit

Permalink
feat:added ME/PIB - Montenegro VAT
Browse files Browse the repository at this point in the history
  • Loading branch information
koblas committed Jul 6, 2023
1 parent 9a612f0 commit 26265a8
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ All country validators are in the "namespace" of the ISO country code.
| Mexico | MX | CURP | Person | Individual Identifier (Clave Única de Registro de Población) |
| Mexico | MX | CLABE | Bank | Bank Account (Clave Bancaria Estandarizada) |
| Montenegro | ME | JMBG | Person | Unique Master Citizen Number |
| Montenegro | ME | PIB | Tax/Vat | Poreski Identifikacioni Broj, Montenegro tax number |
| Malaysia | MY | NRIC | Person | Malaysian National Registration Identity Card Number |
| Netherlands | NL | BSN | Person | Burgerservicenummer, the Dutch citizen identification number |
| Netherlands | NL | BTW | Vat | Btw-identificatienummer (Omzetbelastingnummer, the Dutch VAT number) |
Expand Down
1 change: 1 addition & 0 deletions src/me/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * as jmbg from './jmbg';
export * as pib from './pib';
158 changes: 158 additions & 0 deletions src/me/pib.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { InvalidChecksum, InvalidLength } from '../exceptions';
import { validate, format } from './pib';

describe('me/pib', () => {
it('format:02000989', () => {
const result = format('02000989');

expect(result).toEqual('02000989');
});

test.each([
'02000989',
'02005115',
'02005328',
'02007479',
'02008599',
'02015099',
'02017105',
'02018560',
'02026325',
'02033143',
'02033356',
'02044188',
'02046954',
'02047403',
'02051664',
'02052822',
'02082390',
'02085020',
'02087723',
'02094754',
'02096064',
'02096099',
'02106183',
'02118912',
'02126265',
'02131013',
'02132419',
'02160102',
'02171058',
'02194007',
'02196727',
'02216078',
'02219603',
'02241102',
'02259974',
'02264811',
'02265435',
'02272296',
'02291266',
'02293099',
'02303213',
'02305054',
'02305623',
'02309084',
'02310783',
'02313987',
'02335450',
'02355388',
'02357950',
'02383136',
'02384337',
'02385040',
'02389231',
'02395673',
'02404281',
'02407515',
'02436159',
'02437643',
'02440768',
'02448076',
'02454190',
'02455455',
'02462494',
'02465787',
'02467593',
'02628988',
'02630419',
'02653753',
'02656515',
'02671930',
'02694638',
'02697904',
'02702967',
'02705001',
'02707942',
'02709392',
'02717557',
'02739500',
'02751372',
'02759519',
'02766515',
'02769336',
'02783746',
'02865971',
'02868474',
'02880474',
'02894998',
'02896753',
'02904870',
'02908433',
'02952165',
'02959801',
'02983303',
'03016480',
'03022480',
'03037002',
'03099873',
'03183246',
'03313468',
'03328139',
'03350479',
'03350487',
'03350495',
'03350509',
'03350517',
'03350525',
'03350533',
'03350541',
'03350550',
'03350568',
'03350576',
'03350584',
'03350592',
'03350606',
'03350614',
'03350622',
'03350665',
'03350673',
'03350681',
'03350690',
'03350703',
'03350789',
'03351483',
'03352480',
'03353486',
'03354482',
'03355489',
'03356485',
'03357481',
])('validate:%s', value => {
const result = validate(value);

expect(result.isValid).toEqual(true);
});

it('validate:0335348', () => {
const result = validate('0335348');

expect(result.error).toBeInstanceOf(InvalidLength);
});

it('validate:03353487', () => {
const result = validate('03353487');

expect(result.error).toBeInstanceOf(InvalidChecksum);
});
});
77 changes: 77 additions & 0 deletions src/me/pib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* PIB (Poreski Identifikacioni Broj, Montenegro tax number).
*
* This number consists of 8 digits.
*
* Source
* http://www.pretraga.crps.me:8083/
* https://www.vatify.eu/montenegro-vat-number.html
*
* ENTITY
*/
import * as exceptions from '../exceptions';
import { strings } from '../util';
import { Validator, ValidateReturn } from '../types';
import { weightedSum } from '../util/checksum';

function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
return strings.cleanUnicode(input, ' -');
}

const impl: Validator = {
name: 'Montenegro tax number',
localName: 'Poreski Identifikacioni Broj',
abbreviation: 'PIB',

compact(input: string): string {
const [value, err] = clean(input);

if (err) {
throw err;
}

return value;
},

format(input: string): string {
const [value] = clean(input);

return value;
},

validate(input: string): ValidateReturn {
const [value, error] = clean(input);

if (error) {
return { isValid: false, error };
}
if (value.length !== 8) {
return { isValid: false, error: new exceptions.InvalidLength() };
}

if (!strings.isdigits(value)) {
return { isValid: false, error: new exceptions.InvalidFormat() };
}

const [front, check] = strings.splitAt(value, 7);

const sum = weightedSum(front, {
weights: [8, 7, 6, 5, 4, 3, 2],
modulus: 11,
});

if (String(((11 - sum) % 11) % 10) !== check) {
return { isValid: false, error: new exceptions.InvalidChecksum() };
}

return {
isValid: true,
compact: value,
isIndividual: false,
isCompany: true,
};
},
};

export const { name, localName, abbreviation, validate, format, compact } =
impl;

0 comments on commit 26265a8

Please sign in to comment.