stdnum 1.10.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/no/fodselsnummer.js +2 -2
- package/lib/esm/no/fodselsnummer.js +2 -2
- package/package.json +5 -2
- package/src/ad/index.ts +1 -0
- package/src/ad/nrt.spec.ts +36 -0
- package/src/ad/nrt.ts +87 -0
- package/src/al/index.ts +1 -0
- package/src/al/nipt.spec.ts +43 -0
- package/src/al/nipt.ts +111 -0
- package/src/ar/cbu.spec.ts +28 -0
- package/src/ar/cbu.ts +96 -0
- package/src/ar/cuit.spec.ts +28 -0
- package/src/ar/cuit.ts +102 -0
- package/src/ar/dni.spec.ts +22 -0
- package/src/ar/dni.ts +72 -0
- package/src/ar/index.ts +3 -0
- package/src/at/businessid.spec.ts +34 -0
- package/src/at/businessid.ts +73 -0
- package/src/at/index.ts +4 -0
- package/src/at/tin.spec.ts +173 -0
- package/src/at/tin.ts +140 -0
- package/src/at/uid.spec.ts +44 -0
- package/src/at/uid.ts +84 -0
- package/src/at/vnr.spec.ts +38 -0
- package/src/at/vnr.ts +84 -0
- package/src/au/abn.spec.ts +28 -0
- package/src/au/abn.ts +78 -0
- package/src/au/acn.spec.ts +34 -0
- package/src/au/acn.ts +76 -0
- package/src/au/index.ts +3 -0
- package/src/au/tfn.spec.ts +28 -0
- package/src/au/tfn.ts +79 -0
- package/src/az/index.ts +2 -0
- package/src/az/pin.spec.ts +16 -0
- package/src/az/pin.ts +61 -0
- package/src/az/tin.spec.ts +28 -0
- package/src/az/tin.ts +64 -0
- package/src/ba/index.ts +1 -0
- package/src/ba/jmbg.spec.ts +28 -0
- package/src/ba/jmbg.ts +85 -0
- package/src/be/bis.spec.ts +184 -0
- package/src/be/bis.ts +85 -0
- package/src/be/index.ts +4 -0
- package/src/be/insz.spec.ts +51 -0
- package/src/be/insz.ts +55 -0
- package/src/be/nn.spec.ts +117 -0
- package/src/be/nn.ts +77 -0
- package/src/be/personIdentifierHelpers.spec.ts +254 -0
- package/src/be/personIdentifierHelpers.ts +130 -0
- package/src/be/vat.spec.ts +46 -0
- package/src/be/vat.ts +84 -0
- package/src/bg/egn.spec.ts +28 -0
- package/src/bg/egn.ts +75 -0
- package/src/bg/index.ts +3 -0
- package/src/bg/pnf.spec.ts +28 -0
- package/src/bg/pnf.ts +73 -0
- package/src/bg/vat.spec.ts +34 -0
- package/src/bg/vat.ts +120 -0
- package/src/br/cnpj.spec.ts +34 -0
- package/src/br/cnpj.ts +89 -0
- package/src/br/cpf.spec.ts +34 -0
- package/src/br/cpf.ts +87 -0
- package/src/br/index.ts +2 -0
- package/src/by/index.ts +1 -0
- package/src/by/unp.spec.ts +34 -0
- package/src/by/unp.ts +108 -0
- package/src/bz/index.ts +1 -0
- package/src/bz/tin.spec.ts +28 -0
- package/src/bz/tin.ts +67 -0
- package/src/ca/bn.spec.ts +40 -0
- package/src/ca/bn.ts +88 -0
- package/src/ca/gst.spec.ts +34 -0
- package/src/ca/gst.ts +70 -0
- package/src/ca/index.ts +5 -0
- package/src/ca/pst.spec.ts +28 -0
- package/src/ca/pst.ts +71 -0
- package/src/ca/qst.spec.ts +47 -0
- package/src/ca/qst.ts +88 -0
- package/src/ca/sin.spec.ts +34 -0
- package/src/ca/sin.ts +72 -0
- package/src/ch/index.ts +3 -0
- package/src/ch/ssn.spec.ts +50 -0
- package/src/ch/ssn.ts +74 -0
- package/src/ch/uid.spec.ts +34 -0
- package/src/ch/uid.ts +82 -0
- package/src/ch/vat.spec.ts +28 -0
- package/src/ch/vat.ts +83 -0
- package/src/cl/index.ts +2 -0
- package/src/cl/run.ts +13 -0
- package/src/cl/rut.spec.ts +50 -0
- package/src/cl/rut.ts +97 -0
- package/src/cn/index.ts +2 -0
- package/src/cn/ric.spec.ts +34 -0
- package/src/cn/ric.ts +86 -0
- package/src/cn/uscc.spec.ts +34 -0
- package/src/cn/uscc.ts +110 -0
- package/src/co/index.ts +1 -0
- package/src/co/nit.spec.ts +40 -0
- package/src/co/nit.ts +85 -0
- package/src/cr/cpf.spec.ts +34 -0
- package/src/cr/cpf.ts +93 -0
- package/src/cr/cpj.spec.ts +28 -0
- package/src/cr/cpj.ts +111 -0
- package/src/cr/cr.spec.ts +28 -0
- package/src/cr/cr.ts +75 -0
- package/src/cr/index.ts +3 -0
- package/src/cu/index.ts +1 -0
- package/src/cu/ni.spec.ts +34 -0
- package/src/cu/ni.ts +74 -0
- package/src/cy/index.ts +1 -0
- package/src/cy/vat.spec.ts +28 -0
- package/src/cy/vat.ts +98 -0
- package/src/cz/dic.spec.ts +28 -0
- package/src/cz/dic.ts +127 -0
- package/src/cz/index.ts +2 -0
- package/src/cz/rc.spec.ts +44 -0
- package/src/cz/rc.ts +95 -0
- package/src/de/idnr.spec.ts +34 -0
- package/src/de/idnr.ts +91 -0
- package/src/de/index.ts +6 -0
- package/src/de/passport.spec.ts +31 -0
- package/src/de/passport.ts +86 -0
- package/src/de/pwnr.spec.ts +62 -0
- package/src/de/pwnr.ts +190 -0
- package/src/de/stnr.spec.ts +85 -0
- package/src/de/stnr.ts +193 -0
- package/src/de/svnr.spec.ts +56 -0
- package/src/de/svnr.ts +158 -0
- package/src/de/vat.spec.ts +28 -0
- package/src/de/vat.ts +74 -0
- package/src/dk/cpr.spec.ts +34 -0
- package/src/dk/cpr.ts +129 -0
- package/src/dk/cvr.spec.ts +28 -0
- package/src/dk/cvr.ts +81 -0
- package/src/dk/index.ts +2 -0
- package/src/do/cedula.spec.ts +34 -0
- package/src/do/cedula.ts +67 -0
- package/src/do/index.ts +3 -0
- package/src/do/ncf.spec.ts +34 -0
- package/src/do/ncf.ts +133 -0
- package/src/do/rnc.spec.ts +40 -0
- package/src/do/rnc.ts +74 -0
- package/src/dz/index.ts +1 -0
- package/src/dz/nif.spec.ts +39 -0
- package/src/dz/nif.ts +80 -0
- package/src/ec/ci.spec.ts +28 -0
- package/src/ec/ci.ts +92 -0
- package/src/ec/index.ts +2 -0
- package/src/ec/ruc.spec.ts +37 -0
- package/src/ec/ruc.ts +117 -0
- package/src/ee/ik.spec.ts +28 -0
- package/src/ee/ik.ts +114 -0
- package/src/ee/index.ts +3 -0
- package/src/ee/kmkr.spec.ts +28 -0
- package/src/ee/kmkr.ts +76 -0
- package/src/ee/registrikood.spec.ts +28 -0
- package/src/ee/registrikood.ts +80 -0
- package/src/eg/index.ts +1 -0
- package/src/eg/tn.spec.ts +44 -0
- package/src/eg/tn.ts +96 -0
- package/src/es/cif.spec.ts +43 -0
- package/src/es/cif.ts +84 -0
- package/src/es/dni.spec.ts +28 -0
- package/src/es/dni.ts +83 -0
- package/src/es/index.ts +5 -0
- package/src/es/nie.spec.ts +28 -0
- package/src/es/nie.ts +79 -0
- package/src/es/nif.spec.ts +52 -0
- package/src/es/nif.ts +95 -0
- package/src/es/nss.spec.ts +28 -0
- package/src/es/nss.ts +132 -0
- package/src/exceptions.ts +66 -0
- package/src/fi/alv.spec.ts +28 -0
- package/src/fi/alv.ts +76 -0
- package/src/fi/hetu.spec.ts +37 -0
- package/src/fi/hetu.ts +108 -0
- package/src/fi/index.ts +3 -0
- package/src/fi/ytunnus.spec.ts +28 -0
- package/src/fi/ytunnus.ts +49 -0
- package/src/fo/index.ts +1 -0
- package/src/fo/vn.spec.ts +34 -0
- package/src/fo/vn.ts +71 -0
- package/src/fr/index.ts +5 -0
- package/src/fr/nif.spec.ts +34 -0
- package/src/fr/nif.ts +82 -0
- package/src/fr/nir.spec.ts +36 -0
- package/src/fr/nir.ts +98 -0
- package/src/fr/siren.spec.ts +28 -0
- package/src/fr/siren.ts +68 -0
- package/src/fr/siret.spec.ts +38 -0
- package/src/fr/siret.ts +79 -0
- package/src/fr/tva.spec.ts +40 -0
- package/src/fr/tva.ts +125 -0
- package/src/gb/index.ts +3 -0
- package/src/gb/nino-prefixes.ts +245 -0
- package/src/gb/nino.spec.ts +80 -0
- package/src/gb/nino.ts +80 -0
- package/src/gb/utr.spec.ts +28 -0
- package/src/gb/utr.ts +76 -0
- package/src/gb/vat.spec.ts +40 -0
- package/src/gb/vat.ts +112 -0
- package/src/gen/ean.spec.ts +34 -0
- package/src/gen/ean.ts +71 -0
- package/src/gen/index.ts +1 -0
- package/src/gh/index.ts +1 -0
- package/src/gh/tin.spec.ts +42 -0
- package/src/gh/tin.ts +93 -0
- package/src/gn/index.ts +1 -0
- package/src/gn/nifp.spec.ts +40 -0
- package/src/gn/nifp.ts +72 -0
- package/src/gr/amka.spec.ts +28 -0
- package/src/gr/amka.ts +76 -0
- package/src/gr/index.ts +2 -0
- package/src/gr/vat.spec.ts +34 -0
- package/src/gr/vat.ts +84 -0
- package/src/gt/cui.spec.ts +34 -0
- package/src/gt/cui.ts +110 -0
- package/src/gt/index.ts +2 -0
- package/src/gt/nit.spec.ts +34 -0
- package/src/gt/nit.ts +86 -0
- package/src/hk/hkid.spec.ts +52 -0
- package/src/hk/hkid.ts +90 -0
- package/src/hk/index.ts +1 -0
- package/src/hr/index.ts +1 -0
- package/src/hr/oib.spec.ts +28 -0
- package/src/hr/oib.ts +67 -0
- package/src/hu/anum.spec.ts +28 -0
- package/src/hu/anum.ts +71 -0
- package/src/hu/index.ts +1 -0
- package/src/id/index.ts +1 -0
- package/src/id/npwp.spec.ts +34 -0
- package/src/id/npwp.ts +116 -0
- package/src/ie/index.ts +2 -0
- package/src/ie/pps.spec.ts +58 -0
- package/src/ie/pps.ts +81 -0
- package/src/ie/vat.spec.ts +40 -0
- package/src/ie/vat.ts +99 -0
- package/src/il/hp.spec.ts +38 -0
- package/src/il/hp.ts +75 -0
- package/src/il/idnr.spec.ts +28 -0
- package/src/il/idnr.ts +70 -0
- package/src/il/index.ts +2 -0
- package/src/in/aadhaar.spec.ts +40 -0
- package/src/in/aadhaar.ts +85 -0
- package/src/in/epic.spec.ts +34 -0
- package/src/in/epic.ts +85 -0
- package/src/in/gstin.spec.ts +34 -0
- package/src/in/gstin.ts +156 -0
- package/src/in/index.ts +4 -0
- package/src/in/pan.spec.ts +40 -0
- package/src/in/pan.ts +93 -0
- package/src/index.ts +404 -0
- package/src/is/index.ts +2 -0
- package/src/is/kennitala.spec.ts +46 -0
- package/src/is/kennitala.ts +80 -0
- package/src/is/vsk.spec.ts +22 -0
- package/src/is/vsk.ts +60 -0
- package/src/it/aic.spec.ts +40 -0
- package/src/it/aic.ts +97 -0
- package/src/it/codicefiscale.spec.ts +28 -0
- package/src/it/codicefiscale.ts +167 -0
- package/src/it/index.ts +3 -0
- package/src/it/iva.spec.ts +28 -0
- package/src/it/iva.ts +65 -0
- package/src/jp/cn.spec.ts +28 -0
- package/src/jp/cn.ts +77 -0
- package/src/jp/index.ts +1 -0
- package/src/ke/index.ts +1 -0
- package/src/ke/pin.spec.ts +34 -0
- package/src/ke/pin.ts +77 -0
- package/src/kr/brn.spec.ts +28 -0
- package/src/kr/brn.ts +91 -0
- package/src/kr/index.ts +2 -0
- package/src/kr/rrn.spec.ts +34 -0
- package/src/kr/rrn.ts +104 -0
- package/src/li/index.ts +1 -0
- package/src/li/peid.spec.ts +22 -0
- package/src/li/peid.ts +71 -0
- package/src/lt/asmens.spec.ts +28 -0
- package/src/lt/asmens.ts +73 -0
- package/src/lt/index.ts +2 -0
- package/src/lt/pvm.spec.ts +34 -0
- package/src/lt/pvm.ts +75 -0
- package/src/lu/index.ts +1 -0
- package/src/lu/tva.spec.ts +28 -0
- package/src/lu/tva.ts +70 -0
- package/src/lv/index.ts +1 -0
- package/src/lv/pvn.spec.ts +44 -0
- package/src/lv/pvn.ts +102 -0
- package/src/ma/ice.spec.ts +39 -0
- package/src/ma/ice.ts +72 -0
- package/src/ma/ice9.spec.ts +28 -0
- package/src/ma/ice9.ts +62 -0
- package/src/ma/index.ts +2 -0
- package/src/mc/index.ts +1 -0
- package/src/mc/tva.spec.ts +28 -0
- package/src/mc/tva.ts +67 -0
- package/src/md/idno.spec.ts +28 -0
- package/src/md/idno.ts +78 -0
- package/src/md/index.ts +1 -0
- package/src/me/index.ts +2 -0
- package/src/me/jmbg.ts +17 -0
- package/src/me/pib.spec.ts +158 -0
- package/src/me/pib.ts +77 -0
- package/src/mk/edb.spec.ts +50 -0
- package/src/mk/edb.ts +88 -0
- package/src/mk/index.ts +2 -0
- package/src/mk/jmbg.ts +17 -0
- package/src/mt/index.ts +1 -0
- package/src/mt/vat.spec.ts +28 -0
- package/src/mt/vat.ts +69 -0
- package/src/mu/index.ts +1 -0
- package/src/mu/nid.spec.ts +34 -0
- package/src/mu/nid.ts +89 -0
- package/src/mx/banks.ts +658 -0
- package/src/mx/clabe.spec.ts +68 -0
- package/src/mx/clabe.ts +105 -0
- package/src/mx/curp.spec.ts +28 -0
- package/src/mx/curp.ts +261 -0
- package/src/mx/index.ts +3 -0
- package/src/mx/rfc.spec.ts +69 -0
- package/src/mx/rfc.ts +193 -0
- package/src/my/index.ts +1 -0
- package/src/my/nric.spec.ts +40 -0
- package/src/my/nric.ts +91 -0
- package/src/nl/bsn.spec.ts +68 -0
- package/src/nl/bsn.ts +81 -0
- package/src/nl/btw.spec.ts +40 -0
- package/src/nl/btw.ts +95 -0
- package/src/nl/index.ts +3 -0
- package/src/nl/onderwijsnummer.spec.ts +34 -0
- package/src/nl/onderwijsnummer.ts +77 -0
- package/src/no/fodselsnummer.spec.ts +56 -0
- package/src/no/fodselsnummer.ts +118 -0
- package/src/no/index.ts +4 -0
- package/src/no/kontonr.spec.ts +34 -0
- package/src/no/kontonr.ts +84 -0
- package/src/no/mva.spec.ts +28 -0
- package/src/no/mva.ts +80 -0
- package/src/no/orgnr.spec.ts +28 -0
- package/src/no/orgnr.ts +75 -0
- package/src/nz/bank.spec.ts +28 -0
- package/src/nz/bank.ts +238 -0
- package/src/nz/index.ts +2 -0
- package/src/nz/ird.spec.ts +34 -0
- package/src/nz/ird.ts +102 -0
- package/src/pe/ce.spec.ts +46 -0
- package/src/pe/ce.ts +61 -0
- package/src/pe/cui.spec.ts +28 -0
- package/src/pe/cui.ts +85 -0
- package/src/pe/index.ts +3 -0
- package/src/pe/ruc.spec.ts +46 -0
- package/src/pe/ruc.ts +84 -0
- package/src/pk/cnic.spec.ts +34 -0
- package/src/pk/cnic.ts +97 -0
- package/src/pk/index.ts +2 -0
- package/src/pk/ntn.spec.ts +22 -0
- package/src/pk/ntn.ts +65 -0
- package/src/pl/index.ts +3 -0
- package/src/pl/nip.spec.ts +34 -0
- package/src/pl/nip.ts +74 -0
- package/src/pl/pesel.spec.ts +34 -0
- package/src/pl/pesel.ts +97 -0
- package/src/pl/regon.spec.ts +52 -0
- package/src/pl/regon.ts +88 -0
- package/src/pt/cc.spec.ts +43 -0
- package/src/pt/cc.ts +74 -0
- package/src/pt/index.ts +3 -0
- package/src/pt/nif.spec.ts +28 -0
- package/src/pt/nif.ts +78 -0
- package/src/pt/nipc.ts +27 -0
- package/src/py/cedula.spec.ts +46 -0
- package/src/py/cedula.ts +73 -0
- package/src/py/index.ts +2 -0
- package/src/py/ruc.spec.ts +40 -0
- package/src/py/ruc.ts +93 -0
- package/src/ro/cif.spec.ts +40 -0
- package/src/ro/cif.ts +62 -0
- package/src/ro/cnp.spec.ts +50 -0
- package/src/ro/cnp.ts +158 -0
- package/src/ro/cui.spec.ts +28 -0
- package/src/ro/cui.ts +83 -0
- package/src/ro/index.ts +4 -0
- package/src/ro/onrc.spec.ts +28 -0
- package/src/ro/onrc.ts +109 -0
- package/src/rs/index.ts +2 -0
- package/src/rs/jmbg.ts +16 -0
- package/src/rs/pib.spec.ts +28 -0
- package/src/rs/pib.ts +69 -0
- package/src/ru/index.ts +1 -0
- package/src/ru/inn.spec.ts +32 -0
- package/src/ru/inn.ts +106 -0
- package/src/se/index.ts +3 -0
- package/src/se/orgnr.spec.ts +28 -0
- package/src/se/orgnr.ts +68 -0
- package/src/se/personnummer.spec.ts +45 -0
- package/src/se/personnummer.ts +143 -0
- package/src/se/vat.spec.ts +28 -0
- package/src/se/vat.ts +73 -0
- package/src/sg/index.ts +1 -0
- package/src/sg/uen.spec.ts +46 -0
- package/src/sg/uen.ts +209 -0
- package/src/si/ddv.spec.ts +28 -0
- package/src/si/ddv.ts +76 -0
- package/src/si/emso.spec.ts +15 -0
- package/src/si/emso.ts +27 -0
- package/src/si/index.ts +3 -0
- package/src/si/jmbg.ts +20 -0
- package/src/sk/dph.spec.ts +28 -0
- package/src/sk/dph.ts +71 -0
- package/src/sk/index.ts +2 -0
- package/src/sk/rc.ts +12 -0
- package/src/sm/coe.spec.ts +34 -0
- package/src/sm/coe.ts +80 -0
- package/src/sm/index.ts +1 -0
- package/src/sv/index.ts +1 -0
- package/src/sv/nit.spec.ts +34 -0
- package/src/sv/nit.ts +117 -0
- package/src/th/idnr.spec.ts +41 -0
- package/src/th/idnr.ts +80 -0
- package/src/th/index.ts +3 -0
- package/src/th/moa.spec.ts +62 -0
- package/src/th/moa.ts +85 -0
- package/src/th/tin.spec.ts +77 -0
- package/src/th/tin.ts +56 -0
- package/src/tn/index.ts +1 -0
- package/src/tn/mf.spec.ts +37 -0
- package/src/tn/mf.ts +169 -0
- package/src/tr/index.ts +2 -0
- package/src/tr/tckimlik.spec.ts +40 -0
- package/src/tr/tckimlik.ts +87 -0
- package/src/tr/vkn.spec.ts +28 -0
- package/src/tr/vkn.ts +87 -0
- package/src/tw/ban.spec.ts +28 -0
- package/src/tw/ban.ts +67 -0
- package/src/tw/index.ts +5 -0
- package/src/tw/natid.spec.ts +28 -0
- package/src/tw/natid.ts +105 -0
- package/src/tw/tax_code.spec.ts +34 -0
- package/src/tw/tax_code.ts +98 -0
- package/src/tw/ubn.spec.ts +28 -0
- package/src/tw/ubn.ts +80 -0
- package/src/tw/ui.spec.ts +38 -0
- package/src/tw/ui.ts +107 -0
- package/src/types.ts +82 -0
- package/src/ua/edrpou.spec.ts +28 -0
- package/src/ua/edrpou.ts +88 -0
- package/src/ua/index.ts +2 -0
- package/src/ua/rntrc.spec.ts +28 -0
- package/src/ua/rntrc.ts +77 -0
- package/src/us/ein.spec.ts +28 -0
- package/src/us/ein.ts +179 -0
- package/src/us/index.ts +2 -0
- package/src/us/ssn.spec.ts +28 -0
- package/src/us/ssn.ts +117 -0
- package/src/util/checksum.spec.ts +70 -0
- package/src/util/checksum.ts +258 -0
- package/src/util/index.ts +13 -0
- package/src/util/isValidDate.spec.ts +49 -0
- package/src/util/isValidDate.ts +87 -0
- package/src/util/iso7064.spec.ts +17 -0
- package/src/util/iso7064.ts +8 -0
- package/src/util/pymod.ts +8 -0
- package/src/util/strings/char.ts +18 -0
- package/src/util/strings/clean.spec.ts +15 -0
- package/src/util/strings/clean.ts +305 -0
- package/src/util/strings/format.ts +18 -0
- package/src/util/strings/index.ts +5 -0
- package/src/util/strings/reverseString.ts +3 -0
- package/src/util/strings/splitAt.spec.ts +15 -0
- package/src/util/strings/splitAt.ts +16 -0
- package/src/uy/cedula.spec.ts +28 -0
- package/src/uy/cedula.ts +74 -0
- package/src/uy/index.ts +3 -0
- package/src/uy/nie.spec.ts +28 -0
- package/src/uy/nie.ts +84 -0
- package/src/uy/rut.spec.ts +34 -0
- package/src/uy/rut.ts +99 -0
- package/src/ve/index.ts +1 -0
- package/src/ve/rif.spec.ts +38 -0
- package/src/ve/rif.ts +92 -0
- package/src/vn/index.ts +1 -0
- package/src/vn/mst.spec.ts +40 -0
- package/src/vn/mst.ts +100 -0
- package/src/za/idnr.spec.ts +28 -0
- package/src/za/idnr.ts +84 -0
- package/src/za/index.ts +2 -0
- package/src/za/tin.spec.ts +28 -0
- package/src/za/tin.ts +75 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {
|
|
2
|
+
validStructure,
|
|
3
|
+
validChecksum,
|
|
4
|
+
toDateArray,
|
|
5
|
+
} from './personIdentifierHelpers';
|
|
6
|
+
|
|
7
|
+
describe('personIdentifierHelpers', () => {
|
|
8
|
+
const toDob = (string: string): string => {
|
|
9
|
+
const [y, m, d] = toDateArray(string).map(s => parseInt(s, 10));
|
|
10
|
+
return [y, m - 1, d].map(n => `${n}`.padStart(2, '0')).join('');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe('validStructure', () => {
|
|
14
|
+
describe('default dob conversion', () => {
|
|
15
|
+
it('returns true for a valid 20th century date', () => {
|
|
16
|
+
expect(validStructure('99012599999')).toEqual(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('returns true for a potential 21st century date', () => {
|
|
20
|
+
expect(validStructure('01012599999')).toEqual(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('returns true for an unknown date of birth', () => {
|
|
24
|
+
expect(validStructure('01009999999')).toEqual(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('returns false for a string that is neither an unknown date of birth or a valid date of birth', () => {
|
|
28
|
+
expect(validStructure('99999999999')).toEqual(false);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('specified dob conversion', () => {
|
|
33
|
+
it('returns true for a valid 20th century date', () => {
|
|
34
|
+
expect(validStructure('991331999999', toDob)).toEqual(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('returns true for a potential 21st century date', () => {
|
|
38
|
+
expect(validStructure('011331999999', toDob)).toEqual(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('returns true for an unknown date of birth', () => {
|
|
42
|
+
expect(validStructure('990199999999', toDob)).toEqual(true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('returns false for a string that is neither an unknown date of birth or a valid date of birth', () => {
|
|
46
|
+
expect(validStructure('99999999999', toDob)).toEqual(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('validChecksum', () => {
|
|
52
|
+
const range = Array.from({ length: 100 }, (_, n) => n);
|
|
53
|
+
|
|
54
|
+
describe('default dob conversion', () => {
|
|
55
|
+
describe('a date of birth valid in the 20th century only', () => {
|
|
56
|
+
const baseString = '990430999';
|
|
57
|
+
const checksum = 14;
|
|
58
|
+
|
|
59
|
+
it('returns true when the checksum is valid', () => {
|
|
60
|
+
const string = `${baseString}${checksum}`;
|
|
61
|
+
expect(validChecksum(string)).toEqual(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('returns false when the checksum is invalid', () => {
|
|
65
|
+
const toCheck = range.filter(x => x !== checksum);
|
|
66
|
+
toCheck.forEach(cs => {
|
|
67
|
+
const string = `${baseString}${cs}`;
|
|
68
|
+
expect(validChecksum(string)).toEqual(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('a date of birth valid in the 21st century only', () => {
|
|
74
|
+
const baseString = '000229999'; // 1900 was not a leap year
|
|
75
|
+
const checksum = 17;
|
|
76
|
+
|
|
77
|
+
it('returns true when the checksum is valid', () => {
|
|
78
|
+
const string = `${baseString}${checksum}`;
|
|
79
|
+
expect(validChecksum(string)).toEqual(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('returns false when the checksum is invalid', () => {
|
|
83
|
+
const toCheck = range.filter(x => x !== checksum);
|
|
84
|
+
toCheck.forEach(cs => {
|
|
85
|
+
const string = `${baseString}${cs}`;
|
|
86
|
+
expect(validChecksum(string)).toEqual(false);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('a date of birth valid in either the 20th or 21st century', () => {
|
|
92
|
+
const baseString = '100430999';
|
|
93
|
+
const twentiethCenturyChecksum = 85;
|
|
94
|
+
const twentyfirstCenturyChecksum = 17;
|
|
95
|
+
|
|
96
|
+
it('returns true when the checksum is valid for the 20th century', () => {
|
|
97
|
+
const string = `${baseString}${twentiethCenturyChecksum}`;
|
|
98
|
+
expect(validChecksum(string)).toEqual(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('returns true when the checksum is valid for the 21th century', () => {
|
|
102
|
+
const string = `${baseString}${twentyfirstCenturyChecksum}`;
|
|
103
|
+
expect(validChecksum(string)).toEqual(true);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('returns false when the checksum is invalid', () => {
|
|
107
|
+
const excludedChecksums = [
|
|
108
|
+
twentiethCenturyChecksum,
|
|
109
|
+
twentyfirstCenturyChecksum,
|
|
110
|
+
];
|
|
111
|
+
const toCheck = range.filter(x => !excludedChecksums.includes(x));
|
|
112
|
+
toCheck.forEach(cs => {
|
|
113
|
+
const string = `${baseString}${cs}`;
|
|
114
|
+
expect(validChecksum(string)).toEqual(false);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('an unknown date of birth', () => {
|
|
120
|
+
const baseString = '100001999';
|
|
121
|
+
const twentiethCenturyChecksum = 54;
|
|
122
|
+
const twentyfirstCenturyChecksum = 83;
|
|
123
|
+
|
|
124
|
+
it('returns true when the checksum is valid for the 20th century', () => {
|
|
125
|
+
const string = `${baseString}${twentiethCenturyChecksum}`;
|
|
126
|
+
expect(validChecksum(string)).toEqual(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('returns true when the checksum is valid for the 21th century', () => {
|
|
130
|
+
const string = `${baseString}${twentyfirstCenturyChecksum}`;
|
|
131
|
+
expect(validChecksum(string)).toEqual(true);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('returns false when the checksum is invalid', () => {
|
|
135
|
+
const excludedChecksums = [
|
|
136
|
+
twentiethCenturyChecksum,
|
|
137
|
+
twentyfirstCenturyChecksum,
|
|
138
|
+
];
|
|
139
|
+
const toCheck = range.filter(x => !excludedChecksums.includes(x));
|
|
140
|
+
toCheck.forEach(cs => {
|
|
141
|
+
const string = `${baseString}${cs}`;
|
|
142
|
+
expect(validChecksum(string)).toEqual(false);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('specified dob conversion', () => {
|
|
149
|
+
describe('a date of birth valid in the 20th century only', () => {
|
|
150
|
+
const baseString = '990631999';
|
|
151
|
+
const checksum = 95;
|
|
152
|
+
|
|
153
|
+
it('returns true when the checksum is valid', () => {
|
|
154
|
+
const string = `${baseString}${checksum}`;
|
|
155
|
+
expect(validChecksum(string, toDob)).toEqual(true);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('returns false when the checksum is invalid', () => {
|
|
159
|
+
const toCheck = range.filter(x => x !== checksum);
|
|
160
|
+
toCheck.forEach(cs => {
|
|
161
|
+
const string = `${baseString}${cs}`;
|
|
162
|
+
expect(validChecksum(string, toDob)).toEqual(false);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('a date of birth valid in the 21st century only', () => {
|
|
168
|
+
const baseString = '000329999'; // 1900 was not a leap year
|
|
169
|
+
const checksum = 24;
|
|
170
|
+
|
|
171
|
+
it('returns true when the checksum is valid', () => {
|
|
172
|
+
const string = `${baseString}${checksum}`;
|
|
173
|
+
expect(validChecksum(string, toDob)).toEqual(true);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('returns false when the checksum is invalid', () => {
|
|
177
|
+
const toCheck = range.filter(x => x !== checksum);
|
|
178
|
+
toCheck.forEach(cs => {
|
|
179
|
+
const string = `${baseString}${cs}`;
|
|
180
|
+
expect(validChecksum(string, toDob)).toEqual(false);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('a date of birth valid in either the 20th or 21st century', () => {
|
|
186
|
+
const baseString = '100430999';
|
|
187
|
+
const twentiethCenturyChecksum = 85;
|
|
188
|
+
const twentyfirstCenturyChecksum = 17;
|
|
189
|
+
|
|
190
|
+
it('returns true when the checksum is valid for the 20th century', () => {
|
|
191
|
+
const string = `${baseString}${twentiethCenturyChecksum}`;
|
|
192
|
+
expect(validChecksum(string, toDob)).toEqual(true);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('returns true when the checksum is valid for the 21th century', () => {
|
|
196
|
+
const string = `${baseString}${twentyfirstCenturyChecksum}`;
|
|
197
|
+
expect(validChecksum(string, toDob)).toEqual(true);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('returns false when the checksum is invalid', () => {
|
|
201
|
+
const excludedChecksums = [
|
|
202
|
+
twentiethCenturyChecksum,
|
|
203
|
+
twentyfirstCenturyChecksum,
|
|
204
|
+
];
|
|
205
|
+
const toCheck = range.filter(x => !excludedChecksums.includes(x));
|
|
206
|
+
toCheck.forEach(cs => {
|
|
207
|
+
const string = `${baseString}${cs}`;
|
|
208
|
+
expect(validChecksum(string, toDob)).toEqual(false);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('an unknown date of birth', () => {
|
|
214
|
+
const baseString = '100101999';
|
|
215
|
+
const twentiethCenturyChecksum = 61;
|
|
216
|
+
const twentyfirstCenturyChecksum = 90;
|
|
217
|
+
|
|
218
|
+
it('returns true when the checksum is valid for the 20th century', () => {
|
|
219
|
+
const string = `${baseString}${twentiethCenturyChecksum}`;
|
|
220
|
+
expect(validChecksum(string, toDob)).toEqual(true);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('returns true when the checksum is valid for the 21th century', () => {
|
|
224
|
+
const string = `${baseString}${twentyfirstCenturyChecksum}`;
|
|
225
|
+
expect(validChecksum(string, toDob)).toEqual(true);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('returns false when the checksum is invalid', () => {
|
|
229
|
+
const excludedChecksums = [
|
|
230
|
+
twentiethCenturyChecksum,
|
|
231
|
+
twentyfirstCenturyChecksum,
|
|
232
|
+
];
|
|
233
|
+
const toCheck = range.filter(x => !excludedChecksums.includes(x));
|
|
234
|
+
toCheck.forEach(cs => {
|
|
235
|
+
const string = `${baseString}${cs}`;
|
|
236
|
+
expect(validChecksum(string, toDob)).toEqual(false);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe('toDateArray', () => {
|
|
244
|
+
it('works with a string of length 6', () => {
|
|
245
|
+
const string = '013150';
|
|
246
|
+
expect(toDateArray(string)).toEqual(['01', '31', '50']);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('works with a string of length greater than 6', () => {
|
|
250
|
+
const string = '013150999';
|
|
251
|
+
expect(toDateArray(string)).toEqual(['01', '31', '50']);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { strings, isValidDateCompactYYYYMMDD } from '../util';
|
|
2
|
+
|
|
3
|
+
function getApproximatelyNow() {
|
|
4
|
+
const ONE_DAY = 1000 * 60 * 60 * 24;
|
|
5
|
+
return new Date(Date.now() + ONE_DAY);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function isInPast(date: string | number): boolean {
|
|
9
|
+
return new Date(String(date)) <= getApproximatelyNow();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getFullYears(yy: string | number): number[] {
|
|
13
|
+
const yval = typeof yy === 'string' ? parseInt(yy, 10) : yy;
|
|
14
|
+
|
|
15
|
+
return [1900 + yval, 2000 + yval];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getFirstSix(number: string): string {
|
|
19
|
+
return strings.splitAt(number, 6)[0];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getBaseNumber(number: string): string {
|
|
23
|
+
return strings.splitAt(number, 9)[0];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getChecksum(number: string): number {
|
|
27
|
+
const checksumString = strings.splitAt(number, 9)[1];
|
|
28
|
+
return parseInt(checksumString, 10);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function toDateArray(number: string): string[] {
|
|
32
|
+
const [yy, mm, dd] = strings.splitAt(number, 2, 4, 6);
|
|
33
|
+
|
|
34
|
+
return [yy, mm, dd];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getValidPastDates(yymmdd: string): Array<string> {
|
|
38
|
+
const [yy, mm, dd] = toDateArray(yymmdd);
|
|
39
|
+
|
|
40
|
+
return getFullYears(yy)
|
|
41
|
+
.filter(yyyy => isValidDateCompactYYYYMMDD(`${yyyy}${mm}${dd}`))
|
|
42
|
+
.map(yyyy => `${yyyy}-${mm}-${dd}`)
|
|
43
|
+
.filter(isInPast);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isUnknownDob(dob: string): boolean {
|
|
47
|
+
if (['000001', '002001', '004001'].includes(dob)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const [yy, mm, dd] = toDateArray(dob);
|
|
52
|
+
|
|
53
|
+
return strings.isdigits(yy) && mm === '00' && strings.isdigits(dd);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function toChecksumBasis(year: number, baseNumber: string): number {
|
|
57
|
+
return parseInt(year < 2000 ? baseNumber : `${2}${baseNumber}`, 10);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isValidDob(dob: string): boolean {
|
|
61
|
+
return Boolean(getValidPastDates(dob).length);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function defaultToDob(origFirstSix: string): string {
|
|
65
|
+
return origFirstSix;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isValidFirstSix(
|
|
69
|
+
firstSix: string,
|
|
70
|
+
toDob: typeof defaultToDob,
|
|
71
|
+
): boolean {
|
|
72
|
+
const dob = toDob(firstSix);
|
|
73
|
+
return isUnknownDob(dob) || isValidDob(dob);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function validStructure(
|
|
77
|
+
number: string,
|
|
78
|
+
toDob: typeof defaultToDob = defaultToDob,
|
|
79
|
+
): boolean {
|
|
80
|
+
const firstSix = getFirstSix(number);
|
|
81
|
+
return isValidFirstSix(firstSix, toDob);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getChecksumBasesUnknownDob(baseNumber: string): Array<number> {
|
|
85
|
+
const firstSix = getFirstSix(baseNumber);
|
|
86
|
+
const [yy] = toDateArray(firstSix);
|
|
87
|
+
|
|
88
|
+
return getFullYears(yy)
|
|
89
|
+
.filter(isInPast)
|
|
90
|
+
.map(year => toChecksumBasis(year, baseNumber));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function getChecksumBasesForStandardDob(
|
|
94
|
+
baseNumber: string,
|
|
95
|
+
toDob: typeof defaultToDob,
|
|
96
|
+
): Array<number> {
|
|
97
|
+
const firstSix = getFirstSix(baseNumber);
|
|
98
|
+
const dob = toDob(firstSix);
|
|
99
|
+
const validPastDates = getValidPastDates(dob);
|
|
100
|
+
const extractYearFromDate = (date: string): number =>
|
|
101
|
+
parseInt(date.split('-')[0], 10);
|
|
102
|
+
const validPastYears = validPastDates.map(extractYearFromDate);
|
|
103
|
+
return validPastYears.map(year => toChecksumBasis(year, baseNumber));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getChecksumBases(
|
|
107
|
+
number: string,
|
|
108
|
+
toDob: typeof defaultToDob,
|
|
109
|
+
): Array<number> {
|
|
110
|
+
const firstSix = getFirstSix(number);
|
|
111
|
+
const dob = toDob(firstSix);
|
|
112
|
+
const baseNumber = getBaseNumber(number);
|
|
113
|
+
|
|
114
|
+
if (isUnknownDob(dob)) return getChecksumBasesUnknownDob(baseNumber);
|
|
115
|
+
|
|
116
|
+
return getChecksumBasesForStandardDob(baseNumber, toDob);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isValidChecksumPair(checksumBasis: number, checksum: number): boolean {
|
|
120
|
+
return !((checksumBasis + checksum) % 97);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function validChecksum(
|
|
124
|
+
number: string,
|
|
125
|
+
toDob: typeof defaultToDob = defaultToDob,
|
|
126
|
+
): boolean {
|
|
127
|
+
const checksumBases = getChecksumBases(number, toDob);
|
|
128
|
+
const checksum = getChecksum(number);
|
|
129
|
+
return checksumBases.some(csb => isValidChecksumPair(csb, checksum));
|
|
130
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { validate, format } from './vat';
|
|
2
|
+
import { InvalidLength, InvalidChecksum } from '../exceptions';
|
|
3
|
+
|
|
4
|
+
describe('be/vat', () => {
|
|
5
|
+
it('format:403019261', () => {
|
|
6
|
+
const result = format('403019261');
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual('0403019261');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('validate:BE403019261', () => {
|
|
12
|
+
const result = validate('BE403019261');
|
|
13
|
+
|
|
14
|
+
expect(result.isValid && result.compact).toEqual('0403019261');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('validate:(0)403019261', () => {
|
|
18
|
+
const result = validate('(0)403019261');
|
|
19
|
+
|
|
20
|
+
expect(result.isValid && result.compact).toEqual('0403019261');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('validate:BE 428759497', () => {
|
|
24
|
+
const result = validate('BE 428759497');
|
|
25
|
+
|
|
26
|
+
expect(result.isValid && result.compact).toEqual('0428759497');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('validate:BE 0417497106', () => {
|
|
30
|
+
const result = validate('BE 0417497106');
|
|
31
|
+
|
|
32
|
+
expect(result.isValid && result.compact).toEqual('0417497106');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('validate:12345678', () => {
|
|
36
|
+
const result = validate('12345678');
|
|
37
|
+
|
|
38
|
+
expect(result.error).toBeInstanceOf(InvalidLength);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('validate:BE431150351', () => {
|
|
42
|
+
const result = validate('BE431150351');
|
|
43
|
+
|
|
44
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
45
|
+
});
|
|
46
|
+
});
|
package/src/be/vat.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BTW, TVA, NWSt, ondernemingsnummer (Belgian enterprise number).
|
|
3
|
+
*
|
|
4
|
+
* The enterprise number (ondernemingsnummer) is a unique identifier of
|
|
5
|
+
* companies within the Belgian administrative services. It was previously
|
|
6
|
+
* the VAT ID number. The number consists of 10 digits.
|
|
7
|
+
*
|
|
8
|
+
* ENTITY
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as exceptions from '../exceptions';
|
|
12
|
+
import { strings } from '../util';
|
|
13
|
+
import { Validator, ValidateReturn } from '../types';
|
|
14
|
+
|
|
15
|
+
function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
|
|
16
|
+
// eslint-disable-next-line prefer-const
|
|
17
|
+
let [value, err] = strings.cleanUnicode(input, ' -.');
|
|
18
|
+
|
|
19
|
+
if (err !== null) {
|
|
20
|
+
return [value, err];
|
|
21
|
+
}
|
|
22
|
+
if (value.startsWith('BE')) {
|
|
23
|
+
value = value.substr(2);
|
|
24
|
+
}
|
|
25
|
+
if (value.startsWith('(0)')) {
|
|
26
|
+
value = `0${value.substr(3)}`;
|
|
27
|
+
}
|
|
28
|
+
if (value.length === 9) {
|
|
29
|
+
value = `0${value}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return [value, null];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const impl: Validator = {
|
|
36
|
+
name: 'Belgian VAT Number',
|
|
37
|
+
localName: 'Ondernemingsnummer',
|
|
38
|
+
abbreviation: 'BTW, NWSt',
|
|
39
|
+
compact(input: string): string {
|
|
40
|
+
const [value, err] = clean(input);
|
|
41
|
+
|
|
42
|
+
if (err) {
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return value;
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
format(input: string): string {
|
|
50
|
+
const [value] = clean(input);
|
|
51
|
+
|
|
52
|
+
return value;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
validate(input: string): ValidateReturn {
|
|
56
|
+
const [value, error] = clean(input);
|
|
57
|
+
|
|
58
|
+
if (error) {
|
|
59
|
+
return { isValid: false, error };
|
|
60
|
+
}
|
|
61
|
+
if (value.length !== 10) {
|
|
62
|
+
return { isValid: false, error: new exceptions.InvalidLength() };
|
|
63
|
+
}
|
|
64
|
+
if (!strings.isdigits(value)) {
|
|
65
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const [front, sum] = strings.splitAt(value, -2);
|
|
69
|
+
|
|
70
|
+
if (97 - (parseInt(front, 10) % 97) !== parseInt(sum, 10)) {
|
|
71
|
+
return { isValid: false, error: new exceptions.InvalidChecksum() };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
isValid: true,
|
|
76
|
+
compact: value,
|
|
77
|
+
isIndividual: false,
|
|
78
|
+
isCompany: true,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const { name, localName, abbreviation, validate, format, compact } =
|
|
84
|
+
impl;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { validate, format } from './egn';
|
|
2
|
+
import { InvalidLength, InvalidChecksum } from '../exceptions';
|
|
3
|
+
|
|
4
|
+
describe('bg/egn', () => {
|
|
5
|
+
it('format:752316 926 3', () => {
|
|
6
|
+
const result = format('752316 926 3');
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual('7523169263');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('validate:8032056031', () => {
|
|
12
|
+
const result = validate('8032056031');
|
|
13
|
+
|
|
14
|
+
expect(result.isValid && result.compact).toEqual('8032056031');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('validate:12345678', () => {
|
|
18
|
+
const result = validate('12345678');
|
|
19
|
+
|
|
20
|
+
expect(result.error).toBeInstanceOf(InvalidLength);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('validate:8032056032', () => {
|
|
24
|
+
const result = validate('8032056032');
|
|
25
|
+
|
|
26
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
27
|
+
});
|
|
28
|
+
});
|
package/src/bg/egn.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EGN (ЕГН, Единен граждански номер, Bulgarian personal identity codes).
|
|
3
|
+
*
|
|
4
|
+
* It is a 10-digit number of which the first 6 digits denote the person's
|
|
5
|
+
* birth date, the next three digits represent a birth order number from
|
|
6
|
+
* which the person's gender can be determined and the last digit is a check
|
|
7
|
+
* digit.
|
|
8
|
+
*
|
|
9
|
+
* PERSON
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as exceptions from '../exceptions';
|
|
13
|
+
import { strings } from '../util';
|
|
14
|
+
import { Validator, ValidateReturn } from '../types';
|
|
15
|
+
import { weightedSum } from '../util/checksum';
|
|
16
|
+
|
|
17
|
+
function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
|
|
18
|
+
return strings.cleanUnicode(input, ' -.');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const impl: Validator = {
|
|
22
|
+
name: 'Bulgarian Personal Identity Codes',
|
|
23
|
+
localName: 'Единен граждански номер',
|
|
24
|
+
abbreviation: 'ЕГН (EGN)',
|
|
25
|
+
compact(input: string): string {
|
|
26
|
+
const [value, err] = clean(input);
|
|
27
|
+
|
|
28
|
+
if (err) {
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return value;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
format(input: string): string {
|
|
36
|
+
const [value] = clean(input);
|
|
37
|
+
|
|
38
|
+
return value;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
validate(input: string): ValidateReturn {
|
|
42
|
+
const [value, error] = clean(input);
|
|
43
|
+
|
|
44
|
+
if (error) {
|
|
45
|
+
return { isValid: false, error };
|
|
46
|
+
}
|
|
47
|
+
if (value.length !== 10) {
|
|
48
|
+
return { isValid: false, error: new exceptions.InvalidLength() };
|
|
49
|
+
}
|
|
50
|
+
if (!strings.isdigits(value)) {
|
|
51
|
+
return { isValid: false, error: new exceptions.InvalidFormat() };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const [front, check] = strings.splitAt(value, -1);
|
|
55
|
+
|
|
56
|
+
const sum = weightedSum(front, {
|
|
57
|
+
modulus: 11,
|
|
58
|
+
weights: [2, 4, 8, 5, 10, 9, 7, 3, 6],
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (String(sum % 10) !== check) {
|
|
62
|
+
return { isValid: false, error: new exceptions.InvalidChecksum() };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
isValid: true,
|
|
67
|
+
compact: value,
|
|
68
|
+
isIndividual: true,
|
|
69
|
+
isCompany: false,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const { name, localName, abbreviation, validate, format, compact } =
|
|
75
|
+
impl;
|
package/src/bg/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { validate, format } from './pnf';
|
|
2
|
+
import { InvalidLength, InvalidChecksum } from '../exceptions';
|
|
3
|
+
|
|
4
|
+
describe('bg/pnf', () => {
|
|
5
|
+
it('format:7111 042 925', () => {
|
|
6
|
+
const result = format('7111 042 925');
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual('7111042925');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('validate:7111 042 925', () => {
|
|
12
|
+
const result = validate('7111 042 925');
|
|
13
|
+
|
|
14
|
+
expect(result.isValid && result.compact).toEqual('7111042925');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('validate:12345678', () => {
|
|
18
|
+
const result = validate('12345678');
|
|
19
|
+
|
|
20
|
+
expect(result.error).toBeInstanceOf(InvalidLength);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('validate:7111 042 926', () => {
|
|
24
|
+
const result = validate('7111 042 926');
|
|
25
|
+
|
|
26
|
+
expect(result.error).toBeInstanceOf(InvalidChecksum);
|
|
27
|
+
});
|
|
28
|
+
});
|