Skip to content

4. Toepassingsopgave – versies 1 en 2

4.1. De opgave

Image

Met bovenstaande tabel kan de belasting worden berekend in het vereenvoudigde geval van een belastingplichtige die alleen zijn salaris hoeft aan te geven. Zoals aangegeven in voetnoot (1), is de aldus berekende belasting de belasting vóór drie mechanismen:

  • de plafonnering van het gezinsquotiënt die geldt voor hoge inkomens;
  • de belastingvermindering en -korting die van toepassing zijn op lage inkomens;

De berekening van de belasting omvat dus de volgende stappen [http://impotsurlerevenu.org/comprendre-le-calcul-de-l-impot/1217-calcul-de-l-impot-2019.php]:

Image

We stellen voor een programma te schrijven waarmee de belasting van een belastingplichtige kan worden berekend in het vereenvoudigde geval waarin de belastingplichtige alleen zijn salaris hoeft aan te geven:

4.1.1. Berekening van de brutobelasting

De bruto belasting kan als volgt worden berekend:

Eerst wordt het aantal aandelen van de belastingplichtige berekend:

    • elke ouder telt voor 1 aandeel;
    • de eerste twee kinderen dragen elk 1/2 aandeel bij;
    • de volgende kinderen dragen elk 1 aandeel bij:

Het aantal aandelen is dus:

  • nbParts=1+nbEnfants*0,5+(aantalKinderen-2)*0,5 als de werknemer ongehuwd is;
  • aantal delen = 2 + aantal kinderen * 0,5 + (aantal kinderen - 2) * 0,5 als hij getrouwd is;

waarbij nbEnfants het aantal kinderen is;

  • het belastbaar inkomen R wordt berekend als R = 0,9 * S, waarbij S het jaarsalaris is;
  • het gezinsquotiënt QF = R/nbParts wordt berekend;
  • de bruto belasting I wordt berekend op basis van de volgende gegevens (2019):
9964
0
0
27519
0,14
1394,96
73779
0,3
5798
156.244
0,41
13913,69
0
0,45
20163,45

Elke regel heeft 3 velden: champ1, champ2, champ3. Om belasting I te berekenen, zoeken we de eerste regel waarbij QF <= veld1 en nemen we de waarden van die regel. Bijvoorbeeld, voor een gehuwde werknemer met twee kinderen en een jaarsalaris S van 50.000 euro:

Belastbaar inkomen: R=0,9*S=45.000

Aantal delen: nbParts = 2 + 2 * 0,5 = 3

Gezinsquotiënt: QF = 45.000 / 3 = 15.000

De eerste regel waarbij QF <= veld1 is, luidt als volgt:

    27519        0.14    1394.96

De belasting I is dan gelijk aan 0,14*R – 1394,96*nbParts=[0,14*45000-1394,96*3]=2115. De belasting wordt naar beneden afgerond op de dichtstbijzijnde euro.

Als de relatie QF <= veld1 vanaf de eerste regel geldt, dan is de belasting nul.

Als QF zodanig is dat de relatie QF<=veld1 nooit wordt vervuld, dan worden de coëfficiënten van de laatste regel gebruikt. Hier:

    0            0.45        20163.45

wat de bruto belasting I = 0,45*R – 20163,45*nbParts oplevert.

4.1.2. Maximum van het gezinsquotiënt

Image

Om te bepalen of de maximering van het gezinsquotiënt QF van toepassing is, wordt de bruto belasting opnieuw berekend zonder de kinderen. Nog steeds voor de gehuwde werknemer met twee kinderen en een jaarsalaris S van 50.000 euro:

Belastbaar inkomen: R = 0,9 * S = 45.000

Aantal delen: nbParts = 2 (de kinderen worden niet meer meegeteld)

Gezinsquotiënt: QF=45000/2=22500

De eerste regel waarin QF <= veld1 geldt, is de volgende:

    27519        0.14    1394.96

De belasting I is dan gelijk aan 0,14*R – 1394,96*nbParts=[0,14*45000-1394,96*2]=3510.

Maximale kinderbijslag: 1551 * 2 = 3102 euro

Minimale belasting: 3510 – 3102 = 408 euro

De reeds berekende bruto belasting met 3 delen (2115 euro) is hoger dan de minimale belasting (408 euro), dus de gezinsplafondregeling is hier niet van toepassing.

In het algemeen geldt dat de bruto belasting groter is dan (belasting1, belasting2), waarbij:

  • [impôt1]: de bruto belasting berekend met de kinderen;
  • [impôt2]: de bruto belasting berekend zonder kinderen, verminderd met de maximale vrijstelling (hier 1551 euro per halve aandeel) in verband met de kinderen;

4.1.3. Berekening van de korting

Image

Nog steeds voor de gehuwde werknemer met twee kinderen en een jaarsalaris S van 50.000 euro:

De bruto belasting (2115) uit de vorige stap is lager dan 2627 euro voor een echtpaar (1595 euro voor een alleenstaande): de korting is dus van toepassing. Deze wordt verkregen met de volgende berekening:

korting = drempel (echtpaar = 1970 / alleenstaande = 1196) - 0,75 * bruto belasting

korting = 1970 – 0,75 * 2115 = 383,75, afgerond op 384 euro.

Nieuwe bruto belasting = 2115 – 384 = 1731 euro

4.1.4. Berekening van de belastingvermindering

Image

Onder een bepaalde drempel wordt een korting van 20 % toegepast op de bruto belasting die uit de voorgaande berekeningen voortvloeit. In 2019 gelden de volgende drempels:

  • alleenstaanden: 21.037 euro;
  • paar: 42.074 euro; (het cijfer 37.968 dat in het bovenstaande voorbeeld wordt gebruikt, lijkt onjuist);

Deze drempel wordt verhoogd met de waarde: 3797 * (aantal halve delen dat door de kinderen wordt bijgedragen).

Nog steeds voor de gehuwde werknemer met twee kinderen en een jaarsalaris S van 50.000 euro:

  • zijn belastbaar inkomen (45.000 euro) ligt onder de drempel (42.074 + 2 * 3.797) = 49.668 euro;
  • hij heeft dus recht op een vermindering van 20 % van zijn belasting: 1731 * 0,2 = 346,2 euro, afgerond op 347 euro;
  • de bruto belasting van de belastingplichtige bedraagt dan: 1731 – 347 = 1384 euro;

4.1.5. Berekening van de nettobelasting

Onze berekening houdt hier op: de te betalen nettobelasting bedraagt 1384 euro. In de praktijk kan de belastingplichtige profiteren van andere kortingen, met name voor giften aan instellingen van algemeen of openbaar belang.

4.1.6. Gevallen van hoge inkomens

Ons vorige voorbeeld geldt voor de meeste werknemers. Bij hoge inkomens verloopt de belastingberekening echter anders.

4.1.6.1. Maximum voor de korting van 10 % op het jaarinkomen

In de meeste gevallen wordt het belastbaar inkomen berekend met de formule: R = 0,9 * S, waarbij S het jaarsalaris is. Dit wordt de korting van 10 % genoemd. Aan deze korting geldt een maximum. In 2019:

  • mag deze niet hoger zijn dan 12.502 euro;
  • mag deze niet lager zijn dan 437 euro;

Laten we het geval nemen van een ongehuwde werknemer zonder kinderen met een jaarsalaris van 200.000 euro:

  • de vermindering van 10 % bedraagt 200.000 euro > 12.502 euro. Deze wordt dus teruggebracht tot 12.502 euro;

4.1.6.2. Maximum van het gezinsquotiënt

Laten we een geval bekijken waarin de in de linkparagraaf genoemde maximering van de gezinsquotiënt van toepassing is. Laten we het geval nemen van een echtpaar met drie kinderen en een jaarinkomen van 100.000 euro. Laten we de stappen van de berekening nog eens doornemen:

  • de aftrek van 10 % bedraagt 10.000 euro < 12.502 euro. Het belastbaar inkomen R bedraagt dus 100.000 - 10.000 = 90.000 euro;
  • het echtpaar heeft nbParts = 2 + 0,5 × 2 + 1 = 4 delen;
  • hun gezinsquotiënt is dus QF = R / nbParts = 90.000 / 4 = 22.500 euro;
  • hun bruto belasting I1 met kinderen bedraagt I1=0,14*90.000-1.394,96*4= 7.020 euro;
  • zijn bruto belasting I2 zonder kinderen:
    • QF = 90.000 / 2 = 45.000 euro;
    • I2 = 0,3 × 90.000 – 5.798 × 2 = 15.404 euro;
    • volgens de regel inzake de maximering van het gezinsquotiënt mag het voordeel dat kinderen opleveren niet hoger zijn dan (1551 × 4 halve delen) = 6204 euro. In dit geval is het echter I2-I1 = 15404 – 7020 = 8384 euro, dus hoger dan 6204 euro;
    • de bruto belasting wordt daarom herberekend als I3 = I2-6204 = 15.404 - 6.204 = 9.200 euro;

Dit echtpaar krijgt geen korting of vermindering en hun uiteindelijke belastingbedrag bedraagt 9200 euro.

4.1.7. Officiële cijfers

De berekening van de belasting is complex. In dit document worden de berekeningen uitgevoerd aan de hand van de volgende voorbeelden. De resultaten zijn afkomstig van de simulator van de belastingdienst [https://www3.impots.gouv.fr/simulateur/calcul_impot/2019/simplifie/index.htm]:

Belastingplichtige
Officiële resultaten
Resultaten van het algoritme in dit document
Echtpaar met 2 kinderen en een jaarinkomen van 55555 euro
Belasting = 2815 euro
Belastingtarief = 14 %
Belasting = 2814 euro
Belastingtarief = 14 %
Echtpaar met 2 kinderen en een jaarinkomen van 50.000 euro
Belasting = 1385 euro
Korting = 720 euro
Korting = 0 euro
Belastingtarief = 14 %
Belasting = 1.384 euro
Korting = 384 euro
Korting = 347 euro
Belastingtarief = 14 %
Echtpaar met 3 kinderen en een jaarinkomen van 50.000 euro
Belasting = 0 euro
Korting = 384 euro
Korting = 346 euro
Belastingtarief = 14 %
Belasting = 0 euro
Korting = 720 euro
Korting = 0 euro
Belastingtarief = 14 %
Alleenstaande met 2 kinderen en een jaarinkomen van 100.000 euro
Belasting = 19.884 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Belasting = 19.884 euro
Toeslag = 4.480 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Alleenstaande met 3 kinderen en een jaarinkomen van 100.000 euro
Belasting = 16.782 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Belasting = 16.782 euro
Toeslag = 7.176 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Echtpaar met drie kinderen en een jaarinkomen van 100.000 euro
Belasting = 9.200 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 30 %
Belasting = 9.200 euro
Toeslag = 2180 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 30 %
Echtpaar met 5 kinderen en een jaarinkomen van 100.000 euro
Belasting = 4230 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 14 %
Belasting = 4.230 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 14 %
Alleenstaand zonder kinderen en met een jaarinkomen van 100.000 euro
Belasting = 22.986 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Belasting = 22.986 euro
Toeslag = 0 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Echtpaar met 2 kinderen en een jaarinkomen van 30.000 euro
Belasting = 0 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 0 %
Belasting = 0 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 0 %
Alleenstaande zonder kinderen en met een jaarinkomen van 200.000 euro
Belasting = 64.211 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 45 %
Belasting = 64.210 euro
Toeslag = 7498 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 45 %
Echtpaar met 3 kinderen en een jaarinkomen van 200.000 euro
Belasting = 42.843 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %
Belasting = 42.842 euro
Toeslag = 17.283 euro
Korting = 0 euro
Korting = 0 euro
Belastingtarief = 41 %

Hierboven wordt 'toeslag' genoemd wat mensen met een hoog inkomen extra betalen vanwege twee fenomenen:

  • de maximering van de aftrek van 10 % op het jaarinkomen;
  • de maximering van het gezinsquotiënt;

Deze indicator kon niet worden gecontroleerd, omdat de simulator van de belastingdienst deze niet weergeeft.

We zien dat het algoritme in het document telkens een juiste belasting oplevert, zij het met een foutmarge van 1 euro. Deze foutmarge is het gevolg van afrondingen. Alle bedragen worden soms naar boven afgerond, soms naar beneden. Aangezien ik de officiële regels niet kende, zijn de bedragen in het algoritme van het document afgerond:

  • naar boven afgerond voor kortingen en kortingsbedragen;
  • naar beneden afgerond voor toeslagen en de eindbelasting;

Vervolgens zullen er tests worden uitgevoerd om de geldigheid van de resultaten te controleren. Deze zullen worden uitgevoerd met de voorbeelden uit de vorige tabel, met een aanvaardbare foutmarge van 1 euro.

4.2. De boomstructuur van de scripts

Image

4.3. Versie 1

4.3.1. Het algoritme

We presenteren een eerste programma waarin:

  • de gegevens die nodig zijn voor de berekening van de belasting hard gecodeerd zijn in de code in de vorm van tabellen en constanten;
  • de gegevens van de belastingplichtigen (gehuwd, kinderen, salaris) in een eerste tekstbestand [taxpayersdata.txt] staan;
  • de resultaten van de belastingberekening (gehuwd, kinderen, salaris, belasting) worden opgeslagen in een tweede tekstbestand [resultats.txt];

Het script [version-01/main.php] ziet er als volgt uit:


<?php

// strikte typen voor functieparameters
declare(strict_types=1);

// globale constanten
define("PLAFOND_QF_DEMI_PART", 1551);
define("PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION", 21037);
define("PLAFOND_REVENUS_COUPLE_POUR_REDUCTION", 42074);
define("VALEUR_REDUC_DEMI_PART", 3797);
define("PLAFOND_DECOTE_CELIBATAIRE", 1196);
define("PLAFOND_DECOTE_COUPLE", 1970);
define("PLAFOND_IMPOT_COUPLE_POUR_DECOTE", 2627);
define("PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE", 1595);
define("ABATTEMENT_DIXPOURCENT_MAX", 12502);
define("ABATTEMENT_DIXPOURCENT_MIN", 437);

// definitie van lokale constanten
$DATA = "taxpayersdata.txt";
$RESULTATS = "resultats.txt";
$limites = array(9964, 27519, 73779, 156244, 0);
$coeffR = array(0, 0.14, 0.3, 0.41, 0.45);
$coeffN = array(0, 1394.96, 5798, 13913.69, 20163.45);

// gegevens lezen
$data = fopen($DATA, "r");
if (!$data) {
  print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
  exit;
}

// het resultatenbestand openen
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  exit;
}

// de huidige regel van het gegevensbestand wordt verwerkt
while ($ligne = fgets($data, 100)) {
  // eventueel einde-van-regel-teken verwijderen
  $ligne = cutNewLineChar($ligne);
  // de 3 velden 'gehuwd:kinderen:salaris' worden opgehaald, die samen $ligne vormen
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  // de belasting wordt berekend
  $result = calculImpot($marié, (int) $enfants, (float) $salaire, $limites, $coeffR, $coeffN);
  // het resultaat wordt in het resultatenbestand opgeslagen
  $result = ["marié" => $marié, "enfants" => $enfants, "salaire" => $salaire] + $result;
  fputs($résultats, \json_encode($result, JSON_UNESCAPED_UNICODE) . "\n");
  // volgende gegevens
}
// de bestanden worden gesloten
fclose($data);
fclose($résultats);

// einde
exit;

// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
  // het einde-van-regel-teken van $ligne wordt verwijderd, indien aanwezig
  $L = strlen($ligne);  // regellengte
  while (substr($ligne, $L - 1, 1) === "\n" or substr($ligne, $L - 1, 1) === "\r") {
    $ligne = substr($ligne, 0, $L - 1);
    $L--;
  }
  // einde
  return($ligne);
}

// belastingberekening
// --------------------------------------------------------------------------
function calculImpot(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {

  // resultaat
  return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}

// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {

  // resultaat
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

// revenuImposable=jaarsalaris-aftrek
// de vrijstelling heeft een minimum en een maximum
function getRevenuImposable(float $salaire): float {

  // resultaat
  return floor($revenuImposable);
}

// berekent een eventuele korting
function getDecote(string $marié, float $salaire, float $impots): float {

  // resultaat
  return ceil($décôte);
}

// berekent een eventuele korting
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
  /
  // resultaat
  return ceil($réduction);
}

Het gegevensbestand taxpayersdata.txt (gehuwd, kinderen, salaris):

oui,2,55555
oui,2,50000
oui,3,50000
non,2,100000
non,3,100000
oui,3,100000
oui,5,100000
non,0,100000
oui,2,30000
non,0,200000
oui,3,200000

De bestanden résultats.txt (gehuwd, kinderen, salaris, belasting, toeslag, korting, vermindering, belastingtarief) met de verkregen resultaten:

{"marié":"oui","enfants":"2","salaire":"55555","impôt":2814,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"oui","enfants":"2","salaire":"50000","impôt":1384,"surcôte":0,"décôte":384,"réduction":347,"taux":0.14}
{"marié":"oui","enfants":"3","salaire":"50000","impôt":0,"surcôte":0,"décôte":720,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"2","salaire":"100000","impôt":19884,"surcôte":4480,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"non","enfants":"3","salaire":"100000","impôt":16782,"surcôte":7176,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"3","salaire":"100000","impôt":9200,"surcôte":2180,"décôte":0,"réduction":0,"taux":0.3}
{"marié":"oui","enfants":"5","salaire":"100000","impôt":4230,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"0","salaire":"100000","impôt":22986,"surcôte":0,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"2","salaire":"30000","impôt":0,"surcôte":0,"décôte":0,"réduction":0,"taux":0}
{"marié":"non","enfants":"0","salaire":"200000","impôt":64210,"surcôte":7498,"décôte":0,"réduction":0,"taux":0.45}
{"marié":"oui","enfants":"3","salaire":"200000","impôt":42842,"surcôte":17283,"décôte":0,"réduction":0,"taux":0.41}

Opmerkingen

  • regel 4: we dwingen de strikte naleving van het type van de functieparameters af;
  • regels 7-16: definitie van alle constanten die nodig zijn voor de berekening van de belasting;
  • regel 19: de naam van het tekstbestand met de gegevens van de belastingplichtigen (getrouwd, kinderen, salaris);
  • regel 20: de naam van het tekstbestand met de resultaten (gehuwd, kinderen, salaris, belasting) van de belastingberekening;
  • regels 21-23: de drie tabellen met gegevens die de verschillende belastingschijven voor de belastingberekening definiëren;
  • regels 26-30: het bestand met de gegevens van de belastingplichtigen openen in leesmodus met [r]. De functie [fopen] retourneert de booleaanse waarde FALSE als het bestand niet kon worden geopend;
  • regels 33-37: het resultatenbestand openen in schrijfmodus met [w];
  • regels 40-51: lus voor het lezen van de regels (gehuwd, kinderen, salaris) uit het bestand met belastinggegevens;
  • regel 40: de functie [fgets] leest 100 tekens en stopt bij de eerste aangetroffen regeleinde-markering. Hier zijn alle regels korter dan 100 tekens. Als er een regeleinde is aangetroffen, wordt dit opgenomen in de geretourneerde tekenreeks. Wanneer het einde van het bestand is bereikt, retourneert de functie [fgets] de waarde FALSE;
  • regel 42: het regeleinde wordt verwijderd;
  • regel 44: de componenten (echtgenoot, kinderen, salaris) van de regel worden opgehaald;
  • regel 46: de belasting wordt berekend. Het resultaat wordt weergegeven in de vorm van een associatieve tabel (regel 76);
  • regel 48: aan het eerder opgehaalde array worden de sleutels [marié, enfants, salaire] toegevoegd;
  • regel 49: het resultaat wordt in het resultatenbestand opgeslagen in de vorm van een tekenreeks jSON;
  • regels 53-54: zodra het bestand met belastinggegevens volledig is verwerkt, worden de bestanden gesloten;
  • regel 60: de functie die het regeleinde-teken verwijdert uit een regel $ligne. Het regeleinde-teken is de tekenreeks "\r\n" op Windows-systemen en "\n" op Unix-systemen. Het resultaat is de invoertekenreeks zonder het regeleinde-teken.
  • regels 63-64: substr($chaîne,$début,$taille) is de subreeks van $chaîne die begint bij het teken $début en maximaal $taille tekens bevat;

De functie [calculImpot] is als volgt:


// algemene constanten
define("PLAFOND_QF_DEMI_PART", 1551);

// berekening van de belasting
// --------------------------------------------------------------------------
function calculImpot(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
  // $marié: ja, nee
  // $enfants: aantal kinderen
  // $salaire: jaarsalaris
  // $limites, $coeffR, $coeffN: de tabellen met gegevens voor de berekening van de belasting
  //
  // berekening van de belasting met kinderen
  $result1 = calculImpot2($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
  $impot1 = $result1["impôt"];
  // berekening van de belasting zonder kinderen
  if ($enfants != 0) {
    $result2 = calculImpot2($marié, 0, $salaire, $limites, $coeffR, $coeffN);
    $impot2 = $result2["impôt"];
    // toepassing van de maximering van het gezinsquotiënt
    if ($enfants < 3) {
      // $PLAFOND_QF_DEMI_PART euro voor de eerste twee kinderen
      $impot2 = $impot2 - $enfants * PLAFOND_QF_DEMI_PART;
    } else {
      // $PLAFOND_QF_DEMI_PART euro voor de eerste twee kinderen, het dubbele voor de volgende
      $impot2 = $impot2 - 2 * PLAFOND_QF_DEMI_PART - ($enfants - 2) * 2 * PLAFOND_QF_DEMI_PART;
    }
  } else {
    $impot2 = $impot1;
    $result2 = $result1;
  }
  // we nemen de hoogste belasting met het bijbehorende tarief en de bijbehorende toeslag
  if ($impot1 > $impot2) {
    $impot = $impot1;
    $taux = $result1["taux"];
    $surcôte = $result1["surcôte"];
  } else {
    $surcôte = $impot2 - $impot1 + $result2["surcôte"];
    $impot = $impot2;
    $taux = $result2["taux"];
  }
  // berekening van een eventuele korting
  $décôte = getDecote($marié, $salaire, $impot);
  $impot -= $décôte;
  // berekening van een eventuele belastingvermindering
  $réduction = getRéduction($marié, $salaire, $enfants, $impot);
  $impot -= $réduction;
  // resultaat
  return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}

// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {

  // resultaat
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

// revenuImposable=jaarsalaris-vrijstelling
// de aftrek van 10 % heeft een minimum en een maximum
function getRevenuImposable(float $salaire): float {

}

// berekent een eventuele korting
function getDecote(string $marié, float $salaire, float $impots): float {

  // resultaat
  return ceil($décôte);
}

// berekent een eventuele korting
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {

  // resultaat
  return ceil($réduction);
}

Opmerkingen

  • regel 10: de brutobelasting wordt berekend inclusief de kinderen. Het resultaat wordt weergegeven in de vorm ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]] met:
    • [‘impôt’]: de brutobelasting;
    • [‘surcôte’]: het bedrag van de toeslag, indien van toepassing. Deze toeslag is van toepassing wanneer de aftrek van 10 % de drempel van 12.502 euro overschrijdt;
    • [‘taux’]: het belastingtarief van de belastingplichtige;
  • regel 11: de te betalen bruto belasting [impot1];
  • regels 13-14: als de belastingplichtige ten minste één kind heeft, wordt de belastingberekening opnieuw uitgevoerd met dezelfde gegevens, maar met 0 kinderen. Deze tweede berekening is nodig om te zien of de korting als gevolg van de kinderen (nbParts*coeffN) hoger is dan een bepaalde drempel;
  • regel 15: de te betalen brutobelasting [impot2];
  • regels 16-23: voor de bruto belasting [impot2] worden nu de kinderen meegerekend: elk 1/2 aandeel dat door de kinderen wordt bijgedragen, leidt tot een vermindering van [PLAFOND_QF_DEMI_PART] euro;
  • regels 25-26: wanneer de belastingplichtige geen kinderen heeft. In dat geval is de berekening van [impot2] overbodig. Deze is gelijk aan [impot1];
  • regels 29-37: er zijn twee bruto belastingen berekend: [impot1, impot2]. De belastingdienst neemt de hoogste van de twee. Dit levert een bruto belasting op van [impot];
  • regels 39-40: op het brutobedrag [impot] kan een korting worden toegepast;
  • regels 42-43: op het brutobedrag [impot] kan een korting worden toegepast;
  • regel 45: [impot] is nu de te betalen nettobelasting. We geven de resultaten weer;

De functie [calculImpot2] is als volgt:


// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
  // $marié: ja, nee
  // $enfants: aantal kinderen
  // $salaire: jaarsalaris
  // $limites, $coeffR, $coeffN: de tabellen met gegevens voor de berekening van de belasting
  //
  // aantal aandelen
  $marié = strtolower($marié);
  if ($marié === "oui") {
    $nbParts = $enfants / 2 + 2;
  } else {
    $nbParts = $enfants / 2 + 1;
  }
  // 1 aandeel per kind vanaf het derde
  if ($enfants >= 3) {
    // een half extra aandeel voor elk kind vanaf het derde
    $nbParts += 0.5 * ($enfants - 2);
  }
  // belastbaar inkomen
  $revenuImposable = getRevenuImposable($salaire);
  // toeslag
  $surcôte = floor($revenuImposable - 0.9 * $salaire);
  // voor afrondingsproblemen
  if ($surcôte < 0) {
    $surcôte = 0;
  }
  // gezinsquotiënt
  $quotient = $revenuImposable / $nbParts;
  // wordt aan het einde van de tabel met limieten geplaatst om de daaropvolgende lus te beëindigen
  $limites[count($limites) - 1] = $quotient;
  // belastingberekening
  $i = 0;
  while ($quotient > $limites[$i]) {
    $i++;
  }
  // omdat $quotient aan het einde van de tabel $limites is geplaatst, de voorgaande lus
  // mag niet buiten de tabel $limites vallen
  // nu kunnen we de belasting berekenen
  $impôt = floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
  // resultaat
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

// revenuImposable = jaarsalaris - aftrek
// de vrijstelling heeft een minimum en een maximum
function getRevenuImposable(float $salaire): float {
  
  // resultaat
  return floor($revenuImposable);
}

Opmerkingen

  • hier wordt de belasting berekend volgens het zogenaamde progressieve tarief;
  • regel 9: strtolower($chaîne) zet $chaîne om in kleine letters;
  • regels 10-19: berekening van het aantal aandelen van de belastingplichtige;
  • regel 21: het belastbaar inkomen wordt berekend met behulp van een functie. We hebben namelijk gezien dat dit niet altijd 0,9*revenusAnnuels is. De aftrek van 10 % is namelijk beperkt tot 12.502 euro;
  • regel 23: berekening van de eventuele toeslag als het belastbaar inkomen hoger is dan 0,9*revenusAnnuels;
  • regels 25-27: corrigeert het feit dat er door afrondingsfouten soms [$surcôte=-1] staat;
  • regel 29: het gezinsquotiënt;
  • regels 30-36: aan de hand van dit quotiënt kan de belastingschijf van de belastingplichtige worden bepaald;
  • regel 40: zodra de belastingschijf van de belastingplichtige is bepaald, kan zijn bruto belasting worden berekend. De functie floor($x) levert het gehele getal op dat onmiddellijk lager is dan [$x];
  • regel 42: de berekende gegevens worden weergegeven;

De functie [getRevenuImposable] is als volgt:


// globale constanten
define("ABATTEMENT_DIXPOURCENT_MAX", 12502);
define("ABATTEMENT_DIXPOURCENT_MIN", 437);

// revenuImposable=jaarsalaris-aftrek
// de aftrek heeft een minimum en een maximum
function getRevenuImposable(float $salaire): float {
  // aftrek van 10% van het salaris
  $abattement = 0.1 * $salaire;
  // deze aftrek mag niet hoger zijn dan ABATTEMENT_DIXPOURCENT_MAX
  if ($abattement > ABATTEMENT_DIXPOURCENT_MAX) {
    $abattement = ABATTEMENT_DIXPOURCENT_MAX;
  }
  // de korting mag niet lager zijn dan ABATTEMENT_DIXPOURCENT_MIN
  if ($abattement < ABATTEMENT_DIXPOURCENT_MIN) {
    $abattement = ABATTEMENT_DIXPOURCENT_MIN;
  }
  // belastbaar inkomen
  $revenuImposable = $salaire - $abattement;
  // resultaat
  return floor($revenuImposable);
}

Opmerkingen

  • regel 5: de normale aftrek bedraagt 10 % van het jaarsalaris;
  • regels 7-9: de aftrek mag de maximale aftrek [ABATTEMENT_DIXPOURCENT_MAX] niet overschrijden;
  • regels 10-13: de aftrek mag niet lager zijn dan de minimale aftrek [ABATTEMENT_DIXPOURCENT_MIN];
  • regel 15: berekening van het belastbaar inkomen;

De functie [getDecote] is als volgt:


// algemene constanten
define("PLAFOND_DECOTE_CELIBATAIRE", 1196);
define("PLAFOND_DECOTE_COUPLE", 1970);
define("PLAFOND_IMPOT_COUPLE_POUR_DECOTE", 2627);
define("PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE", 1595);

// berekent een eventuele korting
function getDecote(string $marié, float $salaire, float $impots): float {
  // in eerste instantie een korting van nul
  $décôte = 0;
  // maximaal belastingbedrag om in aanmerking te komen voor de korting
  $plafondImpôtPourDécôte = $marié === "oui" ? PLAFOND_IMPOT_COUPLE_POUR_DECOTE : PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE;
  if ($impots < $plafondImpôtPourDécôte) {
    // maximaal bedrag van de korting
    $plafondDécôte = $marié === "oui" ? PLAFOND_DECOTE_COUPLE : PLAFOND_DECOTE_CELIBATAIRE;
    // theoretische korting
    $décôte = $plafondDécôte - 0.75 * $impots;
    // de korting mag het belastingbedrag niet overschrijden
    if ($décôte > $impots) {
      $décôte = $impots;
    }
    // geen korting <0
    if ($décôte < 0) {
      $décôte = 0;
    }
  }
  // resultaat
  return ceil($décôte);
}

Opmerkingen

  • regel 6: maximumbedrag van de brutobelasting om recht te hebben op een korting. Dit bedrag verschilt voor alleenstaanden en koppels;
  • regel 7: of de belastingplichtige recht heeft op de korting;
  • regel 11: de formule voor de korting. [plafondDécôte] is het maximumbedrag van de korting. Dit maximumbedrag wordt berekend in regel 9. Ook hier hangt het af van de situatie van de belastingplichtige: gehuwd of alleenstaand;
  • regels 13-15: de korting mag niet hoger zijn dan de te betalen brutobelasting. Dit is bijvoorbeeld het geval als [impots] in regel 11 gelijk is aan 0;
  • regels 17-19: om afronding naar -1 te voorkomen;

De functie [getRéduction] is als volgt:


// algemene constanten
define("PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION", 21037);
define("PLAFOND_REVENUS_COUPLE_POUR_REDUCTION", 42074);
define("VALEUR_REDUC_DEMI_PART", 3797);

// berekent een eventuele korting
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
  // de inkomensgrens om in aanmerking te komen voor de korting van 20%
  $plafondRevenuPourRéduction = $marié === "oui" ? PLAFOND_REVENUS_COUPLE_POUR_REDUCTION : PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION;
  $plafondRevenuPourRéduction += $enfants * VALEUR_REDUC_DEMI_PART;
  if ($enfants > 2) {
    $plafondRevenuPourRéduction += ($enfants - 2) * VALEUR_REDUC_DEMI_PART;
  }
  // belastbaar inkomen
  $revenuImposable = getRevenuImposable($salaire);
  // korting
  $réduction = 0;
  if ($revenuImposable < $plafondRevenuPourRéduction) {
    // korting van 20%
    $réduction = 0.2 * $impots;
  }
  // resultaat
  return ceil($réduction);
}

Opmerkingen

  • regels 4-10: om recht te hebben op een belastingvermindering moet het belastbaar inkomen (regel 10) lager zijn dan een maximum dat wordt berekend op basis van de regels 4-8;
  • regels 13-16: als aan de voorwaarden wordt voldaan, heeft de belastingplichtige recht op een belastingvermindering van 20 % (regel 15);

4.3.2. Resultaten

Het gegevensbestand taxpayersdata.txt (gehuwd, kinderen, salaris):

oui,2,55555
oui,2,50000
oui,3,50000
non,2,100000
non,3,100000
oui,3,100000
oui,5,100000
non,0,100000
oui,2,30000
non,0,200000
oui,3,200000

Het bestand résultats.txt (gehuwd, kinderen, salaris, belasting, toeslag, korting, vermindering, belastingtarief) met de verkregen resultaten:

{"marié":"oui","enfants":"2","salaire":"55555","impôt":2814,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"oui","enfants":"2","salaire":"50000","impôt":1384,"surcôte":0,"décôte":384,"réduction":347,"taux":0.14}
{"marié":"oui","enfants":"3","salaire":"50000","impôt":0,"surcôte":0,"décôte":720,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"2","salaire":"100000","impôt":19884,"surcôte":4480,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"non","enfants":"3","salaire":"100000","impôt":16782,"surcôte":7176,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"3","salaire":"100000","impôt":9200,"surcôte":2180,"décôte":0,"réduction":0,"taux":0.3}
{"marié":"oui","enfants":"5","salaire":"100000","impôt":4230,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"0","salaire":"100000","impôt":22986,"surcôte":0,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"2","salaire":"30000","impôt":0,"surcôte":0,"décôte":0,"réduction":0,"taux":0}
{"marié":"non","enfants":"0","salaire":"200000","impôt":64210,"surcôte":7498,"décôte":0,"réduction":0,"taux":0.45}
{"marié":"oui","enfants":"3","salaire":"200000","impôt":42842,"surcôte":17283,"décôte":0,"réduction":0,"taux":0.41}

De verkregen resultaten komen overeen met die van de simulator van de belastingdienst.

4.3.3. Conclusie

Het algoritme voor de berekening van de belasting is, zelfs in zogenaamd eenvoudige gevallen, complex. We zullen hier niet verder op ingaan. In de loop van de verschillende versies blijft de kern ervan hetzelfde, ondanks enkele wijzigingen in de presentatie. We zullen dan ook alleen op deze laatste ingaan.

4.4. Versie 2

4.4.1. De wijzigingen

In de vorige versie waren de gegevens die nodig zijn voor de belastingberekening hard gecodeerd in de vorm van constanten en tabellen. Deze methode is te vermijden. In de nieuwe versie zijn deze gegevens ondergebracht in een extern bestand met de naam jSON:

Image

De inhoud van het bestand [taxadmindata.json] is als volgt:


{
    "limites": [9964, 27519, 73779, 156244, 0],
    "coeffR": [0, 0.14, 0.3, 0.41, 0.45],
    "coeffN": [0, 1394.96, 5798, 13913.69, 20163.45],
    "PLAFOND_QF_DEMI_PART": 1551,
    "PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION": 21037,
    "PLAFOND_REVENUS_COUPLE_POUR_REDUCTION": 42074,
    "VALEUR_REDUC_DEMI_PART": 3797,
    "PLAFOND_DECOTE_CELIBATAIRE": 1196,
    "PLAFOND_DECOTE_COUPLE": 1970,
    "PLAFOND_IMPOT_COUPLE_POUR_DECOTE": 2627,
    "PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE": 1595,
    "ABATTEMENT_DIXPOURCENT_MAX": 12502,
    "ABATTEMENT_DIXPOURCENT_MIN": 437
}

De nieuwe versie [version-02/main.php] is als volgt:


<?php

// strikte naleving van de opgegeven typen van de functieparameters
declare (strict_types=1);

// definitie van constanten
$TAXPAYERSDATA = "taxpayersdata.txt";
$RESULTATS = "resultats.txt";
$TAXADMINDATA = "taxadmindata.json";

// de inhoud van het belastinggegevensbestand wordt opgehaald
$fileContents = \file_get_contents($TAXADMINDATA);
$erreur = FALSE;
// fout?
if (!$fileContents) {
  // de fout wordt genoteerd
  $erreur = TRUE;
  $message = "Le fichier des données [$TAXADMINDATA] n'existe pas";
}

if (!$erreur) {
  // de code jSON uit het configuratiebestand wordt opgehaald in een associatieve array
  $taxAdminData = \json_decode($fileContents, true);
  // fout?
  if (!$taxAdminData) {
    // de fout wordt genoteerd
    $erreur = TRUE;
    $message = "Le fichier de données jSON [$TAXADMINDATA] n'a pu être exploité correctement";
  }
}

// fout?
if ($erreur) {
  print "$message\n";
  exit;
}

// het resultatenbestand openen
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  // uitvoer
  exit;
}

// belastinggegevensbestand openen
$taxpayersdata = fopen($TAXPAYERSDATA, "r");
if (!$taxpayersdata) {
  print "Impossible d'ouvrir le fichier des contribuables [$TAXPAYERSDATA]\n";
  // uitvoer
  exit;
}

// de huidige regel van het gegevensbestand wordt verwerkt
while ($ligne = fgets($taxpayersdata, 100)) {
  // eventueel einde-van-regel-teken verwijderen
  $ligne = cutNewLineChar($ligne);
  // de 3 velden 'gehuwd:kinderen:salaris' worden opgehaald, die samen $ligne vormen
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  // de belasting wordt berekend
  $result = calculImpot($taxAdminData, $marié, (int) $enfants, (int) $salaire);
  // het resultaat wordt in het resultatenbestand opgeslagen
  $result = ["marié" => $marié, "enfants" => $enfants, "salaire" => $salaire] + $result;
  fputs($résultats, \json_encode($result, JSON_UNESCAPED_UNICODE) . "\n");
  // volgende gegevens
}
// de bestanden worden gesloten
fclose($taxpayersdata);
fclose($résultats);

// einde
exit;

// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne) {

  // einde
  return($ligne);
}

// berekening van de belasting
// --------------------------------------------------------------------------
function calculImpot(array $taxAdminData, string $marié, int $enfants, float $salaire) {
  // $marié: ja, nee
  // $enfants: aantal kinderen
  // $salaire: jaarsalaris
  // $taxAdminData: gegevens van de belastingdienst
  //
  // belastingberekening met kinderen
  $result1 = calculImpot2($taxAdminData, $marié, $enfants, $salaire);
  $impot1 = $result1["impôt"];
  // belastingberekening zonder kinderen
  if ($enfants != 0) {
    $result2 = calculImpot2($taxAdminData, $marié, 0, $salaire);
    $impot2 = $result2["impôt"];
    // toepassing van de maximering van de gezinsquotiënt
    if ($enfants < 3) {
      // $PLAFOND_QF_DEMI_PART euro voor de eerste twee kinderen
      $impot2 = $impot2 - $enfants * $taxAdminData["PLAFOND_QF_DEMI_PART"];
    } else {
      // $PLAFOND_QF_DEMI_PART euro voor de eerste twee kinderen, het dubbele voor de volgende
      $impot2 = $impot2 - 2 * $taxAdminData["PLAFOND_QF_DEMI_PART"] - ($enfants - 2) * 2 * $taxAdminData["PLAFOND_QF_DEMI_PART"];
    }
  } else {
    $impot2 = $impot1;
    $result2 = $result1;
  }
  // we nemen de hoogste belasting met het bijbehorende tarief en de bijbehorende toeslag
  if ($impot1 > $impot2) {
    $impot = $impot1;
    $taux = $result1["taux"];
    $surcôte = $result1["surcôte"];
  } else {
    $surcôte = $impot2 - $impot1 + $result2["surcôte"];
    $impot = $impot2;
    $taux = $result2["taux"];
  }
  // berekening van een eventuele korting
  $décôte = getDecote($taxAdminData, $marié, $salaire, $impot);
  $impot -= $décôte;
  // berekening van een eventuele belastingvermindering
  $réduction = getRéduction($taxAdminData, $marié, $salaire, $enfants, $impot);
  $impot -= $réduction;
  // resultaat
  return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}

// --------------------------------------------------------------------------
function calculImpot2(array $taxAdminData, string $marié, int $enfants, float $salaire) {
  // $marié: ja, nee

  // resultaat
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

// revenuImposable=jaarsalaris-vrijstelling
// de aftrek heeft een minimum en een maximum
function getRevenuImposable(array $taxAdminData, float $salaire): float {

  // resultaat
  return floor($revenuImposable);
}

// berekent een eventuele korting
function getDecote(array $taxAdminData, string $marié, float $salaire, float $impots): float {

  // resultaat
  return ceil($décôte);
}

// berekent een eventuele korting
function getRéduction(array $taxAdminData, string $marié, float $salaire, int $enfants, float $impots): float {

  // resultaat
  return ceil($réduction);
}

Opmerkingen

  • regels 11-19: er wordt geprobeerd de inhoud van het bestand jSON, met de naam [TAXADMINDATA], te lezen;
  • regels 21-30: als het bestand jSON met succes is gelezen, wordt de inhoud ervan gedecodeerd in de associatieve array [$taxAdminData];
  • regels 32-36: als er een fout is opgetreden bij een van de twee voorgaande bewerkingen, wordt er een foutmelding naar de console geschreven en wordt het programma beëindigd;
  • het verschil met versie 01 is dat hier de gegevens (arrays en constanten) van de belastingdienst in de associatieve array [$taxAdminData] staan, terwijl ze in versie 01 in globale arrays en constanten stonden. Het is juist het globale karakter van deze constanten dat het verschil tussen de twee versies uitmaakt:
    • in versie 01 waren de constanten bekend in alle functies van [main.php];
    • om in versie 02 hetzelfde resultaat te bereiken, moet de associatieve tabel [$taxAdminData] als parameter aan alle functies worden doorgegeven (regels 83, 129, 138, 145, 152);
  • elke functie van versie 02 moet de inhoud van de array [$taxAdminData] gebruiken;
  • regels 83-126: in de functie [calculerImpot], waar voorheen globale constanten of de tabellen [limites, coeffR, coeffN] werden gebruikt, wordt nu de inhoud van de als parameter ontvangen tabel [$taxAdminData] gebruikt (regels 99, 102);
  • alle andere functies zijn op dezelfde manier herschreven;

De verkregen resultaten zijn dezelfde als die in de vorige versie.

4.4.2. Conclusie

Versie 02 is veel flexibeler dan versie 01. In 2020 zal het algoritme voor de belastingberekening waarschijnlijk hetzelfde zijn als in 2019. Alleen de belastingschijven en de berekeningsconstanten zullen zijn gewijzigd. Het volstaat dan om het bestand [taxadmindata.json] bij te werken. Bij versie 01 moet men in de broncode de belastingschijven en de berekeningsconstanten aanpassen. Het is echter waarschijnlijk dat degenen die de waarden van de belastingschijven en de berekeningsconstanten moeten wijzigen, geen toegang hebben tot de broncode van het algoritme.