Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ How you can help! This library currently support about half the countries in the
| Canada | CA | SIN | Person | Person Identifier (Social Insurance Number) |
| Cuba | CU | NI | Person | Número de identidad, Cuban identity card numbers |
| Cyprus | CY | VAT | Company | Αριθμός Εγγραφής Φ.Π.Α. (Cypriot VAT number) |
| Czech Republic | CZ | DIC | Company | Daňové identifikační číslo, Czech VAT number |
| Czech Republic | CZ | DIC | Vat | Daňové identifikační číslo, Czech VAT number |
| Czech Republic | CZ | ICO | Company | Identifikační číslo osoby, Czech Company Identification Number |
| Czech Republic | CZ | RC | Person | Rodné číslo, the Czech birth number |
| Swisserland | CH | SSN | Person | Swiss social security number ("Sozialversicherungsnummer") |
| Swisserland | CH | UID | Company | Unternehmens-Identifikationsnummer, Swiss business identifier |
Expand Down
64 changes: 64 additions & 0 deletions src/cz/ico.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { validate, format } from './ico';
import { InvalidLength, InvalidChecksum, InvalidComponent } from '../exceptions';

describe('cz/ico', () => {
it('format:25596641', () => {
const result = format('25596641');

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

it('validate:25596641 (Avast Software)', () => {
const result = validate('25596641');

expect(result.isValid && result.compact).toEqual('25596641');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current test assertion is a bit weak as it doesn't verify all properties of a successful validation, such as isCompany and isIndividual. Using toEqual with the expected result object would make the test more robust and its intent clearer. This suggestion applies to the other successful validation tests in this file as well.

Suggested change
expect(result.isValid && result.compact).toEqual('25596641');
expect(result).toEqual({
isValid: true,
compact: '25596641',
isIndividual: false,
isCompany: true,
});

});

it('validate:27082440 (Alza.cz)', () => {
const result = validate('27082440');

expect(result.isValid && result.compact).toEqual('27082440');
});

it('validate:45274649 (Škoda Auto)', () => {
const result = validate('45274649');

expect(result.isValid && result.compact).toEqual('45274649');
});

it('validate:00023205 (ČEZ)', () => {
const result = validate('00023205');

expect(result.isValid && result.compact).toEqual('00023205');
});

it('validate:00075370 (ČSÚ)', () => {
const result = validate('00075370');

expect(result.isValid && result.compact).toEqual('00075370');
});

it('validate:12345678 (invalid checksum)', () => {
const result = validate('12345678');

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

it('validate:1234567 (too short)', () => {
const result = validate('1234567');

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

it('validate:90000001 (reserved range)', () => {
const result = validate('90000001');

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

it('validate with spaces: 255 96 641', () => {
const result = validate('255 96 641');

expect(result.isValid && result.compact).toEqual('25596641');
});
});
81 changes: 81 additions & 0 deletions src/cz/ico.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* IČO (Identifikační číslo osoby, Czech Company Identification Number).
*
* The IČO is an 8-digit identifier assigned to every business entity
* registered in the Czech Republic. It uses a weighted modulus-11 checksum.
*
* ENTITY
*/

import * as exceptions from '../exceptions';
import { strings, weightedSum } from '../util';
import { Validator, ValidateReturn } from '../types';

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

function checksum(value: string): boolean {
const [front, check] = strings.splitAt(value, -1);

const sum = weightedSum(front, {
modulus: 11,
weights: [8, 7, 6, 5, 4, 3, 2, 1],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The weights array contains 8 elements, but the checksum is calculated on the first 7 digits of the IČO number, so front has a length of 7. The last weight, 1, is never used. To improve clarity and prevent confusion, it's best to have the weights array match the length of the data it's applied to.

Suggested change
weights: [8, 7, 6, 5, 4, 3, 2, 1],
weights: [8, 7, 6, 5, 4, 3, 2],

});

const v = (11 - sum) % 11;

return (v === 0 ? '1' : String(v % 10)) === check;
}

const impl: Validator = {
name: 'Czech Company Identification Number',
localName: 'Identifikační číslo osoby',
abbreviation: 'IČO',

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() };
}
if (value.startsWith('9')) {
return { isValid: false, error: new exceptions.InvalidComponent() };
}
if (!checksum(value)) {
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;
1 change: 1 addition & 0 deletions src/cz/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * as dic from './dic';
export * as ico from './ico';
export * as rc from './rc';
Loading