Skip to content

Commit

Permalink
feat: rdwDataToParams
Browse files Browse the repository at this point in the history
  • Loading branch information
hongaar committed Jan 24, 2023
1 parent 4070a9b commit 2e9f132
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 11 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

**Motorrijtuigenbelasting (MRB) berekenen in JavaScript**

## Installatie

```bash
yarn|npm add motorrijtuigenbelasting
```

## Gebruik

```js
import {
berekenMrb,
Expand All @@ -24,6 +28,27 @@ const bedrag = berekenMrb({
});
```

## Gebruik met RDW data

```js
import { berekenMrb, rdwDataToParams } from "motorrijtuigenbelasting";

const kenteken = "1-ABC-123";

const rdw = (resource) =>
fetch(
`https://opendata.rdw.nl/resource/${resource}.json?kenteken=${kenteken}`
).then((res: any) => res.json());

const basis = (await rdw("m9d7-ebf2"))[0];
const brandstof = await rdw("8ys7-d773");

const params = rdwDataToParams({ basis, brandstof });

// bedrag is motorrijtuigenbelasting per tijdvak van 3 maanden in euro's
const bedrag = berekenMrb({ ...params, provincie: Provincie.Utrecht });
```

## Roadmap

- [x] Benzine
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"repository": "github:hongaar/motorrijtuigenbelasting",
"license": "MIT",
"author": "Joram van den Boezem <joram@vandenboezem.nl>",
"sideEffects": false,
"type": "module",
"main": "dist/index.js",
"types": "types/index.d.ts",
Expand Down
23 changes: 23 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export class NotImplementedError extends Error {
constructor() {
super();
this.message = "Deze combinatie van parameters wordt nog niet ondersteund";
this.name = "NotImplementedError";
}
}

export class InvalidParameters extends Error {
constructor(message: string) {
super();
this.message = `Ongeldige parameter ontvangen (${message})`;
this.name = "InvalidParameters";
}
}

export class InvalidRdwData extends Error {
constructor() {
super();
this.message = "Ongeldige RDW data ontvangen";
this.name = "InvalidRdwData";
}
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from "./berekenMrb.js";
export * from "./errors.js";
export * from "./params.js";
export * from "./rdwDataToParams.js";
2 changes: 1 addition & 1 deletion src/models/2023/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NotImplementedError } from "../../errors.js";
import { ModelParams, Voertuigtype } from "../../params.js";
import { NotImplementedError } from "../errors.js";
import { Model_2023_Personenauto } from "./personenauto.js";

export function Model_2023(params: ModelParams) {
Expand Down
11 changes: 10 additions & 1 deletion src/models/2023/opcenten.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { InvalidParameters } from "../../errors.js";
import { Provincie } from "../../params.js";

// https://opendata.cbs.nl/statline/#/CBS/nl/dataset/80889NED/table
Expand All @@ -17,5 +18,13 @@ export const data = {
};

export function Model_2023_Opcenten(provincie: Provincie | null): number {
return provincie === null ? 0 : data[provincie];
if (provincie === null) {
return 0;
}

if (provincie in data) {
return data[provincie];
}

throw new InvalidParameters(`provincie: ${provincie}`);
}
6 changes: 0 additions & 6 deletions src/models/errors.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/models/personenauto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NotImplementedError } from "../errors.js";
import { Brandstof, ModelParams } from "../params.js";
import { NotImplementedError } from "./errors.js";

type Tarief = {
threshold_kg: number;
Expand Down
179 changes: 179 additions & 0 deletions src/rdwDataToParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { InvalidRdwData, NotImplementedError } from "./errors.js";
import { Brandstof, Voertuigtype } from "./params.js";

export type KentekenData = {
kenteken: string;
europese_voertuigcategorie: string;
massa_ledig_voertuig: string;

vervaldatum_apk?: string;
bruto_bpm?: string;
aantal_zitplaatsen?: string;
cilinderinhoud?: string;
toegestane_maximum_massa_voertuig?: string;
maximum_massa_trekken_ongeremd?: string;
maximum_trekken_massa_geremd?: string;
catalogusprijs?: string;
plaats_chassisnummer?: string;
type?: string;
type_gasinstallatie?: string;
typegoedkeuringsnummer?: string;
variant?: string;
uitvoering?: string;
aantal_rolstoelplaatsen?: string;
maximum_ondersteunende_snelheid?: string;
vervaldatum_apk_dt?: string;
hoogte_voertuig?: string;
zuinigheidsclassificatie?: string;
voertuigsoort?: string;
merk?: string;
handelsbenaming?: string;
datum_tenaamstelling?: string;
inrichting?: string;
eerste_kleur?: string;
tweede_kleur?: string;
aantal_cilinders?: string;
massa_rijklaar?: string;
datum_eerste_toelating?: string;
datum_eerste_tenaamstelling_in_nederland?: string;
wacht_op_keuren?: string;
wam_verzekerd?: string;
aantal_deuren?: string;
aantal_wielen?: string;
afstand_hart_koppeling_tot_achterzijde_voertuig?: string;
afstand_voorzijde_voertuig_tot_hart_koppeling?: string;
lengte?: string;
breedte?: string;
technische_max_massa_voertuig?: string;
volgnummer_wijziging_eu_typegoedkeuring?: string;
vermogen_massarijklaar?: string;
wielbasis?: string;
export_indicator?: string;
openstaande_terugroepactie_indicator?: string;
taxi_indicator?: string;
maximum_massa_samenstelling?: string;
jaar_laatste_registratie_tellerstand?: string;
tellerstandoordeel?: string;
code_toelichting_tellerstandoordeel?: string;
tenaamstellen_mogelijk?: string;
datum_tenaamstelling_dt?: string;
datum_eerste_toelating_dt?: string;
datum_eerste_tenaamstelling_in_nederland_dt?: string;
api_gekentekende_voertuigen_assen?: string;
api_gekentekende_voertuigen_brandstof?: string;
api_gekentekende_voertuigen_carrosserie?: string;
api_gekentekende_voertuigen_carrosserie_specifiek?: string;
api_gekentekende_voertuigen_voertuigklasse?: string;
};

export type BrandstofData = {
kenteken: string;
brandstof_volgnummer: string;
brandstof_omschrijving: string;

brandstofverbruik_buiten?: string;
brandstofverbruik_gecombineerd?: string;
brandstofverbruik_stad?: string;
co2_uitstoot_gecombineerd?: string;
geluidsniveau_rijdend?: string;
geluidsniveau_stationair?: string;
emissiecode_omschrijving?: string;
milieuklasse_eg_goedkeuring_licht?: string;
nettomaximumvermogen?: string;
toerental_geluidsniveau?: string;
uitlaatemissieniveau?: string;
};

export type RdwData = {
basis: KentekenData;
brandstof: BrandstofData[];
};

/**
* Voertuigcategorie
*
* Europese voertuigcategorie, gevolgd door de nationale voertuigsoort zoals
* deze staat geregistreerd in het kentekenregister. De nationale voertuigsoort
* is afgeleid van de Europese voertuigcategorie.
* De RDW onderscheidt momenteel de volgende voertuigsoorten:
*
* M1
* Personenauto
* N1, N2, N3
* Bedrijfsauto
* M2, M3
* Bus
* L3e, L4e
* Motorfiets
* L5e, L7e
* Driewielig motorrijtuig
* L1e, L2e, L6e
* Bromfiets
* O1, O2, O3, O4
* Aanhangwagen (Oplegger)
* T, C, U, Z
* Landbouw- of bosbouwtrekker
* R, S
* Landbouw- of bosbouwtrekker Landbouw- of bosbouw AHW of VGU
*
* Een 'G' achter de voertuigcategorie is de aanduiding voor 'Geländefahrzeug'.
* Een voertuig met de toevoeging ‘G’ achter de voertuigcategorie is een
* voertuig dat gebouwd is als ‘terreinvoertuig’. Onder ‘terreinvoertuig’ wordt
* verstaan een voertuig van categorie M of N met specifieke technische
* kenmerken waardoor het buiten de normale wegen kan worden gebruikt.
*/
function toVoertuigType(rdwData: RdwData) {
switch (rdwData.basis.europese_voertuigcategorie) {
case "M1":
return Voertuigtype.Personenauto;

case "N1":
// @todo: ??
return Voertuigtype["Bestelauto ondernemer"];

case "N2":
case "N3":
// @todo: ??
return Voertuigtype.Vrachtauto;

default:
throw new NotImplementedError();
}
}

function toGewicht(rdwData: RdwData) {
return Number(rdwData.basis.massa_ledig_voertuig);
}

function toBrandstof(rdwData: RdwData) {
const { brandstof } = rdwData;

if (brandstof.length === 0) {
throw new InvalidRdwData();
}

// const sortedBrandstoffen = [...brandstof].sort((a, b) =>
// Number(a.brandstof_volgnummer) > Number(b.brandstof_volgnummer) ? 1 : -1
// );

return Brandstof.Benzine;
}

function toElektrischOfWaterstof(rdwData: RdwData) {
const { brandstof } = rdwData;

if (brandstof.length === 0) {
throw new InvalidRdwData();
}

return false;
}

export function rdwDataToParams(rdwData: RdwData) {
return {
voertuigtype: toVoertuigType(rdwData),
gewicht: toGewicht(rdwData),
brandstof: toBrandstof(rdwData),
elektrisch_of_waterstof: toElektrischOfWaterstof(rdwData),
};
}
14 changes: 13 additions & 1 deletion tests/models/2023/personenauto.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Model_2023_Personenauto } from "../../../src/models/2023/personenauto.js";
import { Brandstof, Provincie, Voertuigtype } from "../../../src/params.js";

test("0/benzine", () => {
test("0/benzine/geen_provincie", () => {
expect(
Model_2023_Personenauto({
brandstof: Brandstof.Benzine,
Expand Down Expand Up @@ -86,3 +86,15 @@ test("lage_uitstoot", () => {
})
).toBe(53);
});

test("invalid_provincie", () => {
expect(() =>
Model_2023_Personenauto({
brandstof: Brandstof.Benzine,
elektrisch_of_waterstof: false,
voertuigtype: Voertuigtype.Personenauto,
provincie: "invalid" as Provincie,
gewicht: 0,
})
).toThrow();
});
27 changes: 27 additions & 0 deletions tests/rdwDataToParams.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { rdwDataToParams } from "../src/rdwDataToParams.js";

const exampleDataBasis = {
kenteken: "1-ABC-23",
massa_ledig_voertuig: "1000",
};

const exampleDataBrandstof = {
kenteken: "1-ABC-23",
brandstof_volgnummer: "1",
};

test("Personenauto/Benzine", () => {
expect(
rdwDataToParams({
basis: { ...exampleDataBasis, europese_voertuigcategorie: "M1" },
brandstof: [
{ ...exampleDataBrandstof, brandstof_omschrijving: "Benzine" },
],
})
).toStrictEqual({
brandstof: "Benzine",
elektrisch_of_waterstof: false,
gewicht: 1000,
voertuigtype: "Personenauto",
});
});
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node 18 + ESM + Strictest",
"compilerOptions": {
"lib": ["es2022"],
"lib": ["es2022", "dom"],
"module": "es2022",
"target": "es2022",
"strict": true,
Expand Down

0 comments on commit 2e9f132

Please sign in to comment.