Skip to content

11. Anwendungsaufgabe: Version 3

Image

Diese neue Version führt zwei Änderungen ein:

  • Die für die Steuerberechnung erforderlichen Daten, die von der Steuerbehörde bereitgestellt werden, werden in einer Datei jSON [admindata.json] abgelegt:

{
    "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
}
  • Die Ergebnisse der Steuerberechnung werden ebenfalls in einer Datei mit den Namen jSON und [résultats.json] gespeichert:

[
  {
    "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. Das Konfigurationsskript [config.py]

Das Konfigurationsskript lautet wie folgt:


def configure():
    import os

    # Absoluter Pfad zum Ordner dieses Skripts
    script_dir = os.path.dirname(os.path.abspath(__file__))
    # Abhängigkeiten der Anwendung
    absolute_dependencies = [
        f"{script_dir}/../shared",
    ]
    # Konfiguration der Anwendung
    config = {
        # absoluter Pfad zur Steuerzahlerdatei
        "taxpayersFilename"f"{script_dir}/../data/taxpayersdata.txt",
        # Absoluter Pfad zur Ergebnisdatei
        "resultsFilename"f"{script_dir}/../data/résultats.json",
        # Absoluter Pfad zur Datei mit den Daten der Steuerbehörde
        "admindataFilename"f"{script_dir}/../data/admindata.json"
    }
    # Aktualisierung des Syspath
    from myutils import set_syspath

    set_syspath(absolute_dependencies)

    # Konfiguration wird wiederhergestellt
    return config
  • Zeile 8: Der Ordner „[shared]“ wird in den Python-Pfad aufgenommen. Dieser Ordner enthält das Modul „[impôts_module_02]“, das vom Hauptskript verwendet wird;

11.2. Hauptskript [main.py]

Das Hauptskript der Version 3 lautet wie folgt:


# die Anwendung wird konfiguriert
import config

config = config.configure()

# Der Syspath ist konfiguriert – die Importe können durchgeführt werden
from impôts_module_02 import calcul_impôt, get_admindata, get_taxpayers_data, record_results_in_json_file

# Steuerpflichtigen-Datei
taxpayers_filename = config['taxpayersFilename']
# Ergebnisdatei
results_filename = config['resultsFilename']
# Datei mit den Daten der Steuerbehörde
admindata_filename = config['admindataFilename']
# Code
try:

    # Einlesen der Daten der Steuerbehörde
    admindata = get_admindata(admindata_filename)
    # Einlesen der Steuerzahlerdaten
    taxpayers = get_taxpayers_data(taxpayers_filename)
    # Ergebnisliste
    results = []
    # Berechnung der Steuer der Steuerpflichtigen
    for taxpayer in taxpayers:
        # Die Steuerberechnung gibt ein Schlüsselwörterbuch zurück
        # ['marié', 'enfants', 'salaire', 'impôt', 'surcôte', 'décôte', 'réduction', 'taux']
        result = calcul_impôt(admindata, taxpayer['marié'], taxpayer['enfants'], taxpayer['salaire'])
        # Das Wörterbuch wird zur Ergebnisliste hinzugefügt
        results.append(result)
    # Die Ergebnisse werden gespeichert
    record_results_in_json_file(results_filename, results)
except BaseException as erreur:
    # Es können verschiedene Fehler auftreten: fehlende Datei, falscher Dateiinhalt
    # Der Fehler wird angezeigt und die Anwendung wird beendet
    print(f"L'erreur suivante s'est produite : {erreur}]\n")
finally:
    print("Travail terminé...")

Hinweise

  • Zeilen 2–4: Hier wird die Anwendung konfiguriert, insbesondere der Python-Pfad;
  • Zeile 7: Die benötigten Funktionen werden aus [main.py] importiert;
  • Zeilen 9–14: Die Namen der von der Anwendung verwendeten Dateien werden aus der Konfiguration abgerufen;
  • Das Hauptskript der Version 3 weist drei Unterschiede gegenüber dem der Versionen 1 und 2 auf:
  • Zeile 21: Die Daten der Steuerbehörde werden aus der Datei jSON [./data/admindata.json] übernommen;
  • Zeile 32: Die Ergebnisse der Steuerberechnung werden in die Datei jSON [./data/résultats.json] geschrieben;
  • Zeile 7: Die Funktionen der Version 3 befinden sich im Modul [impots.modules.impôts_module_02];

11.3. Das Modul [impots.v02.modules.impôts_module_02]

Das Modul [impots.v02.modules.impôts_module_02] hat folgende Struktur:

Image

  • In diesem Modul finden sich Funktionen wieder, die bereits im von Version 1 verwendeten Modul vorhanden waren, allerdings mit einem Unterschied. Wenn das Modul der Version 2 eine im Modul der Version 1 vorhandene Funktion übernimmt, geschieht dies mit einem zusätzlichen Parameter: [adminData] (Zeilen 29, 51, 77, 127). Dieser Parameter steht für das Verzeichnis der Steuerdaten aus den Dateien jSON und [adminData.json]. Im Modul der Version 1 mussten diese Daten nicht an die Funktionen übergeben werden, da sie global für diese definiert waren, sodass die Funktionen sie bereits kannten;

11.4. Einlesen der Daten der Steuerbehörde

Die Funktion [get_admindata] lautet wie folgt:


# Einlesen der Daten der Steuerbehörde in eine Datei jSON
# ----------------------------------------
def get_admindata(admindata_filename: str) -> dict:
    # Einlesen der Daten der Steuerbehörde
    # Eventuelle Ausnahmen werden gemeldet: Datei fehlt, Inhalt von jSON ist fehlerhaft
    file = None
    try:
        # Öffnen der Datei jSON im Lesemodus
        file = codecs.open(admindata_filename, "r", "utf8")
        # Übertragung des Inhalts in ein Wörterbuch
        admin_data = json.load(file)
        # Das Ergebnis wird ausgegeben
        return admin_data
    finally:
        # Schließen der Datei, falls sie geöffnet wurde
        if file:
            file.close()
  • Zeile 9: Das Bildwörterbuch wird aus der gelesenen Datei jSON abgerufen;

11.5. Speichern der Ergebnisse

Die Funktion [record_results_in_json_file] hat folgende Aufgabe:


# Schreiben der Ergebnisse in eine Datei jSON
# ----------------------------------------
def record_results_in_json_file(results_filename: str, results: list):
    file = None
    try:
        # Öffnen der Ergebnisdatei
        file = codecs.open(results_filename, "w", "utf8")
        # Blockweise schreiben
        json.dump(results, file, ensure_ascii=False)
    finally:
        # Die Datei wird geschlossen, falls sie geöffnet wurde
        if file:
            file.close()
  • Zeile 7: Es wird eine in UTF-8 kodierte Datei erstellt;
  • Zeile 9: Die Liste [results] wird in die Datei jSON geschrieben. Die Zeichen UTF-8 werden nicht maskiert (ensure_ascii=False);

11.6. Änderungen an den Funktionen

Einige Funktionen erhalten nun einen zusätzlichen Parameter [admin_data]. Dadurch ändert sich ihre Schreibweise geringfügig. Nehmen wir zum Beispiel die Funktion [calcul_impôt]:


# Steuerberechnung – Schritt 1
# ----------------------------------------
def calcul_impôt(admin_data: dict, marié: str, enfants: int, salaire: int) -> dict:
    # verheiratet: ja, nein
    # Kinder: Anzahl der Kinder
    # Gehalt: Jahresgehalt
    # Grenzen, Koeffizient, Koeffizient: Die Datentabellen zur Berechnung der Steuer
    #
    # Steuerberechnung mit Kindern
    result1 = calcul_impôt_2(admin_data, marié, enfants, salaire)
    impot1 = result1["impôt"]
    # Steuerberechnung ohne Kinder
    if enfants != 0:
        result2 = calcul_impôt_2(admin_data, marié, 0, salaire)
        impot2 = result2["impôt"]
        # Anwendung der Obergrenze für den Familienquotienten
        if enfants < 3:
            # PLAFOND_QF_DEMI_PART Euro für die ersten beiden Kinder
            impot2 = impot2 - enfants * admin_data['plafond_qf_demi_part']
        else:
            # PLAFOND_QF_DEMI_PART Euro für die ersten beiden Kinder, das Doppelte für die folgenden
            impot2 = impot2 - 2 * admin_data['plafond_qf_demi_part'] - (enfants - 2) * 2 * admin_data[
                'plafond_qf_demi_part']
    else:
        impot2 = impot1
        result2 = result1

    # Es gilt der höchste Steuersatz mit dem dazugehörigen Satz und dem entsprechenden Aufschlag
    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"]

    # Berechnung eines eventuellen Steuerabzugs
    décôte = get_décôte(admin_data, marié, salaire, impot)
    impot -= décôte
    # Berechnung einer möglichen Steuerermäßigung
    réduction = get_réduction(admin_data, marié, salaire, enfants, impot)
    impot -= réduction
    # Ergebnis
    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}

Hinweise

  • Wo [calcul_impôt] andere Funktionen aufruft, übergibt sie [admin_data] als ersten Parameter (Zeilen 10, 14, 39, 42);
  • Wo [calcul_impôt] Steuerkonstanten verwendet, greift sie nun auf das Wörterbuch [admin_data] zurück (Zeilen 19, 22);

Alle Funktionen, die [admin_data] als Parameter erhalten, unterliegen denselben Änderungen.

11.7. Ergebnisse

Die erzielten Ergebnisse entsprechen denen, die zu Beginn von Abschnitt 8.3 vorgestellt wurden.