Skip to content

Commit

Permalink
Oplossing voor problemen mbt hypotheekrenteaftrek berekening (#39)
Browse files Browse the repository at this point in the history
- In Beschikbaar inkomen werd hypotheekrente dubbel meegerekend; omdat het in wonen zit, die ook voor huurwoningen wordt gebruikt, zat dit ook in berekening nettoInkomen. Daar moet wonen alleen meegenomen worden bij huren omdat bij koop al in de nettoLoon berekening wordt meegenomen.
- In Marginaledruk berekening wrdt ook hypotheek dubbel meegenomen.
- In Maginaledruk nettoLoonBelasting voor in grafiek moet juist alleen negatieve getall worden meegenomen (dat komt omdat waarden sinds vorige wijzig als negatief getal worden aangemaakt)
- Legenda van marginaledruk in grafiek wat duidelijker gemaakt, zodat het meer op een echte som lijkt.
- Unit test voor samenvatting gerepareerd, was omgevallen naar tekstuele verbetering in vorige test.
Closes #38
  • Loading branch information
Hilbrand authored Nov 8, 2024
1 parent 5b71f05 commit 77d008f
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 44 deletions.
1 change: 0 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

<script>
import { defineComponent } from "vue";
import { NConfigProvider } from "naive-ui";
import FooterPaneel from "./components/FooterPaneel.vue";
const themeOverrides = {
Expand Down
8 changes: 8 additions & 0 deletions src/components/Legenda.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
</div>
<n-table :single-line="false" size="tiny" class="table">
<tbody>
<tr v-for="(gd, idx) in data.bovenaan" :key="gd.naam">
<td colspan="2" class="tekst lijnBeneden">{{ gd.naam }}</td>
<td v-if="gd.percentage" class="nr lijnBeneden">{{ gd.percentage }}</td>
<td class="nr lijnBeneden">{{ gd.bedrag }}</td>
</tr>
<tr v-for="(gd, idx) in data.grafiek" :key="gd.naam">
<td><div class="dot" :style="'background-color:' + gd.color" /></td>
<td>{{ gd.naam }}</td>
Expand Down Expand Up @@ -48,6 +53,9 @@
.streep {
border-top: 1px solid black;
}
.lijnBeneden {
border-bottom: 1px solid black;
}
</style>

<script>
Expand Down
12 changes: 7 additions & 5 deletions src/js/berekeningen/BeschikbaarInkomen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
InvoerGegevensType,
LeeftijdType,
VisualisatieTypeType,
WoningType,
} from "../../ts/types";
import { Legenda } from "../grafieken/Legenda";
import zorgtoeslag from "../belasting/zorgtoeslag";
Expand Down Expand Up @@ -61,8 +62,8 @@ export class BeschikbaarInkomen extends Berekenen {
const ibBox1 = inkomen.inkomstenBelasting(this.vis.jaar, toetsingsInkomen, aow);
// Belasting die betaald zou zijn alleen over arbeid
const ibBox1Arbeid = inkomen.inkomstenBelasting(this.vis.jaar, arbeidsinkomen, aow);
// Maximaal (of eigenlijk minimaal te betalen belasting)
const ibBox1Max = Math.min(ibBox1, ibBox1Arbeid);
// Belasting die betaald moet worden over arbeid of met eventuele hypotheek verrekening.
const ibBox1Effectief = Math.min(ibBox1, ibBox1Arbeid);

// Potentieel aftrekbare hypotheekrente is verschil tussen arbeidsinkomen belasting
// en belasting van inkomen met hypotheekrente verrekend in het inkomen.
Expand All @@ -71,8 +72,8 @@ export class BeschikbaarInkomen extends Berekenen {
// Arbeidskorting gaat over alleen arbeidsinkomen
// Maar kan niet hoger zijn dan maximum te betalen belasting.
let arbeidskortingMax = inkomen.arbeidskorting(this.vis.jaar, arbeidsinkomen, aow);
let arbeidskorting = Math.min(ibBox1Max, arbeidskortingMax);
let maxBelastingNaAK = functies.negatiefIsNul(ibBox1Max - arbeidskorting);
let arbeidskorting = Math.min(ibBox1Effectief, arbeidskortingMax);
let maxBelastingNaAK = functies.negatiefIsNul(ibBox1Effectief - arbeidskorting);

// Inkomensafhankelijke combinatie korting
let inACKMax =
Expand Down Expand Up @@ -125,13 +126,14 @@ export class BeschikbaarInkomen extends Berekenen {
arbeidsinkomen - (arbeidskorting + algemeneHeffingsKorting + inACK + hraMax + maxBelasting);

// Netto inkomen is arbeidsinkomen minus arbeidsinkomen belasting.
const huurtoeslag = this.wonen.woning_type === WoningType.HUUR ? wonen : 0;
let nettoInkomen =
nettoLoon +
// In de tabel wordt kinderbijslag niet getoond en dus niet meegenomen in nettoInkomen berekening
(visualisatie == VisualisatieTypeType.T ? 0 : this.algemeneGegevens.kinderbijslag) +
kindgebondenBudget +
zorgtoeslag +
wonen;
huurtoeslag;

let beschikbaarInkomen: BeschikbaarInkomenResultaatType = {
arbeidsinkomen: arbeidsinkomen,
Expand Down
38 changes: 22 additions & 16 deletions src/js/berekeningen/MarginaleDruk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
InvoerGegevensType,
MarginaleDrukResultaatType,
VisualisatieTypeType,
WoningType,
} from "../../ts/types";

export class MarginaleDruk extends Berekenen {
Expand Down Expand Up @@ -67,6 +68,7 @@ export class MarginaleDruk extends Berekenen {
percentage(Δbedrag: number, Δtotaal: number, inverse: boolean): number {
const percentage = Δtotaal == 0 ? 0 : Δbedrag / Δtotaal;
const result: number = +(percentage * 100).toFixed(2);

return Math.max(0, isNaN(result) || result == 0 ? 0 : inverse ? -result : 1 * result);
}

Expand All @@ -75,9 +77,8 @@ export class MarginaleDruk extends Berekenen {
berekening2: BeschikbaarInkomenResultaatType,
visualisatie: VisualisatieTypeType
): MarginaleDrukResultaatType {
const tabel = visualisatie === VisualisatieTypeType.T;
const grafiek = visualisatie === VisualisatieTypeType.G;
const presentatieFunctie = tabel ? this.absolute : this.percentage;
const presentatieFunctie = grafiek ? this.percentage : this.absolute;

const ΔextraLoon = berekening2.arbeidsinkomen - berekening1.arbeidsinkomen;
const ΔibBox1 = this.mdAbsolute(berekening1.ibBox1, berekening2.ibBox1, false);
Expand All @@ -93,16 +94,6 @@ export class MarginaleDruk extends Berekenen {
const ΔahkMax = this.mdAbsolute(berekening1.ahkMax, berekening2.ahkMax, false);

const Δnvzk = this.mdAbsolute(berekening1.nvzk, berekening2.nvzk, false);
// als grafiek dan
const maxLoonBelasting = grafiek
? -functies.negatiefIsNul(
ΔibBox1 -
(functies.negatiefIsNul(Δahk) +
functies.negatiefIsNul(Δak) +
functies.negatiefIsNul(Δiack) +
functies.negatiefIsNul(Δnvzk))
)
: this.mdAbsolute(berekening1.nettoLoonBelasting, berekening2.nettoLoonBelasting, false);

const Δzt = this.mdAbsolute(berekening1.zt, berekening2.zt, false);
const Δwonen = this.mdAbsolute(berekening1.wonen, berekening2.wonen, false);
Expand All @@ -111,14 +102,29 @@ export class MarginaleDruk extends Berekenen {

const ΔnettoLoon = berekening2.nettoLoon - berekening1.nettoLoon;
const ΔnettoInkomen = berekening2.nettoInkomen - berekening1.nettoInkomen;
const ΔnettoArbeidsinkomen = ΔnettoLoon + (Δzt + Δwonen + Δkb + Δkgb);
const md = ΔextraLoon - ΔnettoArbeidsinkomen;
const Δhuurtoeslag = this.wonen.woning_type === WoningType.HUUR ? Δwonen : 0;
const ΔnettoArbeidsinkomen = ΔnettoLoon + (Δzt + Δhuurtoeslag + Δkb + Δkgb);

const ΔnettoLoonBelasting = this.mdAbsolute(berekening1.nettoLoonBelasting, berekening2.nettoLoonBelasting, false);
// Als grafiek dan trek positieve kortingen van loonbelasting af omdat grafiek geen positieve
// bedragen toont wordt dit verrekend met de te betalen belasting. In de legenda zijn positieve
// bedragen ook niet te zien. Maar wel als de tabel wordt getoond.
const nettoLoonBelastingPresentatie = grafiek
? -functies.negatiefIsNul(
ΔnettoLoonBelasting +
functies.positiefIsNul(Δahk) +
functies.positiefIsNul(Δak) +
functies.positiefIsNul(Δiack) +
functies.positiefIsNul(Δnvzk)
)
: ΔnettoLoonBelasting;
const md = ΔextraLoon - ΔnettoInkomen;

return {
arbeidsinkomen: berekening1.arbeidsinkomen,
extraLoon: ΔextraLoon,
ibBox1: presentatieFunctie(ΔibBox1, ΔextraLoon, true),
nettoLoonBelasting: presentatieFunctie(maxLoonBelasting, ΔextraLoon, grafiek),
nettoLoonBelasting: presentatieFunctie(nettoLoonBelastingPresentatie, ΔextraLoon, grafiek),
nettoInkomen: presentatieFunctie(ΔnettoInkomen, ΔextraLoon, grafiek),
nettoArbeidsinkomen: presentatieFunctie(ΔnettoArbeidsinkomen, ΔextraLoon, grafiek),
nettoLoon: presentatieFunctie(ΔnettoLoon, ΔextraLoon, grafiek),
Expand All @@ -129,7 +135,7 @@ export class MarginaleDruk extends Berekenen {
akMax: presentatieFunctie(ΔakMax, ΔextraLoon, grafiek),
iack: presentatieFunctie(Δiack, ΔextraLoon, grafiek),
iackMax: presentatieFunctie(ΔiackMax, ΔextraLoon, grafiek),
ahk: presentatieFunctie(tabel ? Δahk : Δahk - Δnvzk, ΔextraLoon, grafiek),
ahk: presentatieFunctie(grafiek ? Δahk - Δnvzk : Δahk, ΔextraLoon, grafiek),
ahkMax: presentatieFunctie(ΔahkMax, ΔextraLoon, grafiek),
nvzk: presentatieFunctie(Δnvzk, ΔextraLoon, grafiek),

Expand Down
1 change: 1 addition & 0 deletions src/js/grafieken/BelastingdrukLegenda.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class BelastingdrukLegenda extends Legenda {
grafiek: [],
titel: "Belastingdruk",
arbeidsInkomen: data[offset].id.toFixed(),
bovenaan: [],
};

ld.grafiek.push({
Expand Down
1 change: 1 addition & 0 deletions src/js/grafieken/BeschikbaarInkomenLegenda.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class BeschikbaarInkomenLegenda extends Legenda {
grafiek: [],
titel: "Beschikbaar inkomen",
arbeidsInkomen: data[offset].id.toFixed(),
bovenaan: [],
};

for (let j = 0; j < length; j++) {
Expand Down
19 changes: 11 additions & 8 deletions src/js/grafieken/MarginaleDrukLegenda.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,24 @@ export class MarginaleDrukLegenda extends Legenda {
bedrag: this.geld(b.extraLoon * factor * (-getal / 100)),
});
}
ld.totals = [
ld.bovenaan = [
{
naam: "marginale druk",
percentage: this.percentage(b.marginaleDruk),
bedrag: this.geld(b.marginaleDruk * factor * b.extraLoon * 0.01),
naam: "bruto extra loon",
percentage: this.percentage(100),
bedrag: this.geld(b.extraLoon * factor),
},
];

ld.totals = [
{
naam: "netto extra loon",
percentage: this.percentage(b.nettoInkomen / (b.extraLoon * 100)),
percentage: this.percentage(b.nettoInkomen / (b.extraLoon * 0.01)),
bedrag: this.geld(b.nettoInkomen * factor),
},
{
naam: "bruto extra loon",
percentage: this.percentage(100),
bedrag: this.geld(b.extraLoon * factor),
naam: "marginale druk",
percentage: this.percentage(b.marginaleDruk),
bedrag: this.geld(b.marginaleDruk * factor * b.extraLoon * 0.01),
},
];
this.legendaFunction(ld);
Expand Down
5 changes: 5 additions & 0 deletions src/ts/functies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ function negatiefIsNul(getal: number): number {
return Math.max(0, getal);
}

function positiefIsNul(getal: number): number {
return Math.min(0, getal);
}

function factorBerekening(periode: PeriodeType): number {
return PeriodeType.MAAND == periode ? 1 / 12 : 1;
}
Expand All @@ -62,5 +66,6 @@ export default {
aow,
isHuur,
negatiefIsNul,
positiefIsNul,
factorBerekening,
};
4 changes: 2 additions & 2 deletions test/js/berekeningen/BeschikbaarInkomen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ test("Bereken 2024 beschikbaar inkomen 47500 eenverdiener, 2 kinderen, koop", ()
kb: 2736,
kgb: 4212,
nettoArbeidsinkomen: 28762,
nettoInkomen: 50353,
nettoInkomen: 45776,
nettoLoon: 41303,
nettoLoonBelasting: 4330,
nvzk: 0,
Expand All @@ -130,7 +130,7 @@ test("Bereken 2024 beschikbaar inkomen 80000 alleenstaande, koop", () => {
kb: 0,
kgb: 0,
nettoArbeidsinkomen: 49862,
nettoInkomen: 63589,
nettoInkomen: 58450,
nettoLoon: 58450,
nettoLoonBelasting: 21550,
nvzk: 0,
Expand Down
30 changes: 21 additions & 9 deletions test/js/berekeningen/MarginaleDruk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,24 @@
import { expect, test } from "vitest";
import { BeschikbaarInkomen } from "../../../src/js/berekeningen/BeschikbaarInkomen.js";
import { MarginaleDruk } from "../../../src/js/berekeningen/MarginaleDruk.js";
import { InvoerGegevensType, MarginaleDrukResultaatType, VisualisatieTypeType } from "../../../src/ts/types.js";
import {
InvoerGegevensType,
LeeftijdType,
MarginaleDrukResultaatType,
PeriodeType,
PersoonType,
SalarisVerhogingType,
VisualisatieType,
VisualisatieTypeType,
WonenType,
WoningType,
} from "../../../src/ts/types.js";
import {
alleenstaande2KinderenHuur,
alleenstaandeKoop,
eenverdiener2KinderenHuur,
eenverdiener2kinderenKoop,
invoerGegevens,
} from "./invoer";

function bereken(
Expand All @@ -40,7 +52,7 @@ function bereken(

test("Bereken 2024 marginale druk alleenstaande 27500, 2 kinderen, huur 674", () => {
const arbeidsinkomen: number = 29206; /* Brutoloon: 30.000*/
const berekening = bereken(arbeidsinkomen, alleenstaande2KinderenHuur("bi"), 939, VisualisatieTypeType.T);
const berekening = bereken(arbeidsinkomen, alleenstaande2KinderenHuur("md"), 939, VisualisatieTypeType.T);
const expected: MarginaleDrukResultaatType = {
ahk: 126,
ahkMax: -63,
Expand Down Expand Up @@ -68,7 +80,7 @@ test("Bereken 2024 marginale druk alleenstaande 27500, 2 kinderen, huur 674", ()

test("Bereken 2024 beschikbaar inkomen eenverdiener 47500, 2 kinderen, huur 674", () => {
const arbeidsinkomen: number = 45633; // Brutoloon: 47500
const berekening = bereken(arbeidsinkomen, eenverdiener2KinderenHuur("bi"), 939, VisualisatieTypeType.T);
const berekening = bereken(arbeidsinkomen, eenverdiener2KinderenHuur("md"), 939, VisualisatieTypeType.T);
const expected: MarginaleDrukResultaatType = {
ahk: -63,
ahkMax: -63,
Expand Down Expand Up @@ -96,7 +108,7 @@ test("Bereken 2024 beschikbaar inkomen eenverdiener 47500, 2 kinderen, huur 674"

test("Bereken 2024 beschikbaar inkomen meestverdiener 45000, 2 kinderen, huur 674", () => {
const arbeidsinkomen: number = 43313; // Brutoloon: 45000
const gegevens = eenverdiener2KinderenHuur("bi");
const gegevens = eenverdiener2KinderenHuur("md");
gegevens.personen[1].bruto_inkomen = 21969;

const berekening = bereken(arbeidsinkomen, gegevens, 939, VisualisatieTypeType.T);
Expand Down Expand Up @@ -127,7 +139,7 @@ test("Bereken 2024 beschikbaar inkomen meestverdiener 45000, 2 kinderen, huur 67

test("Bereken 2024 beschikbaar inkomen 47500 eenverdiener, 2 kinderen, koop", () => {
const arbeidsinkomen: number = 45633; // Brutoloon: 47500
const berekening = bereken(arbeidsinkomen, eenverdiener2kinderenKoop("bi"), 939, VisualisatieTypeType.T);
const berekening = bereken(arbeidsinkomen, eenverdiener2kinderenKoop("md"), 939, VisualisatieTypeType.T);
const expected: MarginaleDrukResultaatType = {
ahk: -62,
ahkMax: -62,
Expand Down Expand Up @@ -155,7 +167,7 @@ test("Bereken 2024 beschikbaar inkomen 47500 eenverdiener, 2 kinderen, koop", ()

test("Bereken 2024 beschikbaar inkomen 80000 alleenstaande, koop", () => {
const arbeidsinkomen: number = 80000;
const berekening = bereken(arbeidsinkomen, alleenstaandeKoop("bi"), 939, VisualisatieTypeType.T);
const berekening = bereken(arbeidsinkomen, alleenstaandeKoop("md"), 939, VisualisatieTypeType.T);
const expected: MarginaleDrukResultaatType = {
ahk: -62,
ahkMax: -62,
Expand All @@ -169,9 +181,9 @@ test("Bereken 2024 beschikbaar inkomen 80000 alleenstaande, koop", () => {
ibBox1: -465,
kb: 0,
kgb: 0,
marginaleDruk: 37.49,
nettoArbeidsinkomen: 587,
nettoInkomen: 587,
marginaleDruk: 50.05,
nettoArbeidsinkomen: 469,
nettoInkomen: 469,
nettoLoon: 469,
nettoLoonBelasting: 470,
nvzk: 0,
Expand Down
2 changes: 1 addition & 1 deletion test/js/berekeningen/invoer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const koop: WonenType = {
woz: 315000,
};

function invoerGegevens(
export function invoerGegevens(
tab: string,
personen: PersoonType[],
wonen: WonenType,
Expand Down
4 changes: 2 additions & 2 deletions test/ts/samenvating.test.ts → test/ts/samenvatting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ test("Samenvatting alleenstaande, 2 kinderen 6-11, huur 674", () => {
test("Samenvatting eenverdiener, 1 kind 0-5, 2 kinderen 6-11, koop", () => {
const expected =
"Eenverdiener met een kind tussen 0 en 5 jaar en twee kinderen tussen 6 en 11 jaar, " +
"maandelijkse hypotheek rente &euro; 13482 voor een huis met WOZ-waarde: &euro; 315000";
"jaarlijkse hypotheek rente &euro; 13482 voor een huis met WOZ-waarde: &euro; 315000";
const gegevens = eenverdiener2kinderenKoop("bi");

gegevens.personen.push({ leeftijd: LeeftijdType.K05 });
Expand All @@ -40,7 +40,7 @@ test("Samenvatting eenverdiener, 1 kind 0-5, 2 kinderen 6-11, koop", () => {
test("Samenvatting meerdere verdieners, 2 kinderen 6-11, koop", () => {
const expected =
"Meerdere verdieners met twee kinderen tussen 6 en 11 jaar, " +
"maandelijkse hypotheek rente &euro; 13482 voor een huis met WOZ-waarde: &euro; 315000";
"jaarlijkse hypotheek rente &euro; 13482 voor een huis met WOZ-waarde: &euro; 315000";
const gegevens = eenverdiener2kinderenKoop("bi");

gegevens.personen.push({ leeftijd: LeeftijdType.V, bruto_inkomen: 10000 });
Expand Down

0 comments on commit 77d008f

Please sign in to comment.