Skip to content

11. Toepassingsopdracht: versie 3

Image

Deze nieuwe versie bevat twee wijzigingen:

  • de gegevens die nodig zijn voor de berekening van de belasting en die door de belastingdienst worden verstrekt, worden in een bestand jSON [admindata.json] geplaatst:

{
    "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 resultaten van de belastingberekening worden eveneens in een bestand jSON [résultats.json] geplaatst:

[
  {
    "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": 200000,
    "impôt": 42842,
    "surcôte": 17283,
    "décôte": 0,
    "réduction": 0,
    "taux": 0.41
  }
]

11.1. Het configuratiescript [config.py]

Het configuratiescript ziet er als volgt uit:


def configure():
    import os

    # absoluut pad naar de map van dit script
    script_dir = os.path.dirname(os.path.abspath(__file__))
    # afhankelijkheden van de applicatie
    absolute_dependencies = [
        f"{script_dir}/../shared",
    ]
    # configuratie van de applicatie
    config = {
        # absoluut pad naar het bestand met belastingplichtigen
        "taxpayersFilename"f"{script_dir}/../data/taxpayersdata.txt",
        # absoluut pad naar het resultatenbestand
        "resultsFilename"f"{script_dir}/../data/résultats.json",
        # absoluut pad naar het bestand met gegevens van de belastingdienst
        "admindataFilename"f"{script_dir}/../data/admindata.json"
    }
    # syspath bijwerken
    from myutils import set_syspath

    set_syspath(absolute_dependencies)

    # de configuratie wordt teruggezet
    return config
  • regel 8: we voegen de map [shared] toe aan het Python-pad. Deze map bevat de module [impôts_module_02] die door het hoofdscript wordt gebruikt;

11.2. Hoofdscript [main.py]

Het hoofdscript van versie 3 is als volgt:


# de applicatie wordt geconfigureerd
import config

config = config.configure()

# het syspath is geconfigureerd – we kunnen de imports uitvoeren
from impôts_module_02 import calcul_impôt, get_admindata, get_taxpayers_data, record_results_in_json_file

# bestand met belastingplichtigen
taxpayers_filename = config['taxpayersFilename']
# resultatenbestand
results_filename = config['resultsFilename']
# bestand met gegevens van de belastingdienst
admindata_filename = config['admindataFilename']
# code
try:

    # uitlezen van gegevens van de belastingdienst
    admindata = get_admindata(admindata_filename)
    # uitlezen van belastingplichtigengegevens
    taxpayers = get_taxpayers_data(taxpayers_filename)
    # lijst met resultaten
    results = []
    # de belasting van de belastingplichtigen wordt berekend
    for taxpayer in taxpayers:
        # de belastingberekening retourneert een sleutelwoordenboek
        # ['marié', 'enfants', 'salaire', 'impôt', 'surcôte', 'décôte', 'réduction', 'taux']
        result = calcul_impôt(admindata, taxpayer['marié'], taxpayer['enfants'], taxpayer['salaire'])
        # het woordenboek wordt toegevoegd aan de resultatenlijst
        results.append(result)
    # de resultaten worden opgeslagen
    record_results_in_json_file(results_filename, results)
except BaseException as erreur:
    # er kunnen verschillende fouten optreden: bestand ontbreekt, onjuiste bestandsinhoud
    # de fout wordt weergegeven en de applicatie wordt afgesloten
    print(f"L'erreur suivante s'est produite : {erreur}]\n")
finally:
    print("Travail terminé...")

Opmerkingen

  • regels 2-4: hier wordt de applicatie geconfigureerd, met name het Python-pad;
  • regel 7: de benodigde functies worden geïmporteerd in [main.py];
  • regels 9-14: de namen van de bestanden die door de applicatie worden gebruikt, worden uit de configuratie opgehaald;
  • het hoofdscript van versie 3 vertoont drie verschillen ten opzichte van dat van de versies 1 en 2:
  • regel 21: de gegevens van de belastingdienst worden uit het bestand jSON [./data/admindata.json] gehaald;
  • regel 32: de resultaten van de belastingberekening worden opgeslagen in het bestand jSON [./data/résultats.json];
  • regel 7: de functies van versie 3 zijn te vinden in de module [impots.modules.impôts_module_02];

11.3. De module [impots.v02.modules.impôts_module_02]

De module [impots.v02.modules.impôts_module_02] heeft de volgende structuur:

Image

  • In de module zijn functies terug te vinden die al aanwezig waren in de module die door versie 1 werd gebruikt, maar met één verschil. Wanneer de module van versie 2 een functie overneemt die in de module van versie 1 aanwezig is, gebeurt dit met een extra parameter: [adminData] (regels 29, 51, 77, 127). Deze parameter vertegenwoordigt het woordenboek met fiscale gegevens uit het bestand jSON [adminData.json]. In de module van versie 1 hoefden deze gegevens niet aan de functies te worden doorgegeven, omdat ze globaal voor deze functies waren gedefinieerd, waardoor de functies ermee bekend waren;

11.4. Het inlezen van gegevens van de belastingdienst

De functie [get_admindata] is als volgt:


# de gegevens van de belastingdienst worden uit een bestand gelezen jSON
# ----------------------------------------
def get_admindata(admindata_filename: str) -> dict:
    # gegevens van de belastingdienst inlezen
    # eventuele uitzonderingen worden doorgegeven: bestand ontbreekt, inhoud van jSON is onjuist
    file = None
    try:
        # het bestand jSON in leesmodus openen
        file = codecs.open(admindata_filename, "r", "utf8")
        # de inhoud wordt overgebracht naar een woordenboek
        admin_data = json.load(file)
        # het resultaat wordt weergegeven
        return admin_data
    finally:
        # het bestand sluiten als het geopend was
        if file:
            file.close()
  • regel 9: het beeldwoordenboek wordt opgehaald uit het gelezen bestand jSON;

11.5. Resultaten opslaan

De functie [record_results_in_json_file] werkt als volgt:


# de resultaten worden weggeschreven naar een bestand jSON
# ----------------------------------------
def record_results_in_json_file(results_filename: str, results: list):
    file = None
    try:
        # het resultatenbestand openen
        file = codecs.open(results_filename, "w", "utf8")
        # in één keer opslaan
        json.dump(results, file, ensure_ascii=False)
    finally:
        # het bestand wordt gesloten als het geopend was
        if file:
            file.close()
  • regel 7: er wordt een bestand aangemaakt dat is gecodeerd in UTF-8;
  • regel 9: de lijst [results] wordt naar het bestand jSON geschreven. De tekens UTF-8 worden niet geëscape (ensure_ascii=False);

11.6. Wijzigingen in de functies

Sommige functies krijgen nu een extra parameter [admin_data]. Dit verandert de schrijfwijze ervan enigszins. Laten we bijvoorbeeld de functie [calcul_impôt] nemen:


# berekening van de belasting - stap 1
# ----------------------------------------
def calcul_impôt(admin_data: dict, marié: str, enfants: int, salaire: int) -> dict:
    # gehuwd: ja, nee
    # kinderen: aantal kinderen
    # salaris: jaarsalaris
    # grenzen, coeffr, coeffn: de tabellen met gegevens voor de belastingberekening
    #
    # berekening van de belasting met kinderen
    result1 = calcul_impôt_2(admin_data, marié, enfants, salaire)
    impot1 = result1["impôt"]
    # belastingberekening zonder kinderen
    if enfants != 0:
        result2 = calcul_impôt_2(admin_data, marié, 0, salaire)
        impot2 = result2["impôt"]
        # toepassing van het maximum voor het gezinsquotiënt
        if enfants < 3:
            # PLAFOND_QF_DEMI_PART euro voor de eerste twee kinderen
            impot2 = impot2 - enfants * admin_data['plafond_qf_demi_part']
        else:
            # PLAFOND_QF_DEMI_PART euro voor de eerste twee kinderen, het dubbele voor de volgende
            impot2 = impot2 - 2 * admin_data['plafond_qf_demi_part'] - (enfants - 2) * 2 * admin_data[
                '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 = get_décôte(admin_data, marié, salaire, impot)
    impot -= décôte
    # berekening van een eventuele belastingvermindering
    réduction = get_réduction(admin_data, marié, salaire, enfants, impot)
    impot -= réduction
    # resultaat
    return {"marié": marié, "enfants": enfants, "salaire": salaire, "impôt": math.floor(impot), "surcôte": surcôte,
            "décôte": décôte, "réduction": réduction, "taux": taux}

Opmerkingen

  • waar [calcul_impôt] andere functies aanroept, wordt [admin_data] als eerste parameter doorgegeven (regels 10, 14, 39, 42);
  • waar [calcul_impôt] fiscale constanten gebruikt, maakt deze nu gebruik van het woordenboek [admin_data] (regels 19, 22);

Alle functies die [admin_data] als parameter ontvangen, ondergaan dezelfde soort wijzigingen.

11.7. Resultaten

De verkregen resultaten zijn dezelfde als die aan het begin van paragraaf 8.3 worden weergegeven.